I was recently working on a small programming project, and decided to fully embrace the new C++11 keyword auto. Auto allows the compiler to deduce types. The canonical example is:
// before C++11 for( vector::const_iterator i = begin(c); i != end(c); ++i ) // with C++11 for( auto i = begin(c); i != end(c); ++i )
The compiler knows that i is an iterator based on the return type of begin(). The compiler can examine the usage of i to determine that i should either be a const or non_const iterator. The example shows two important things: 1) how much easier it is to read, and 2) how the programmer no longer has to worry about the type of c changing. If the type of c changes to a different container, or even a C-style array, the code will continue to compile correctly.
Here are a few observations from my initial experience using auto:
- I used auto somewhat more than expected. Out of 737 lines of code, auto appears on 58 lines (8%)
- Of those 58 lines:
- 17 instances were for loops (29%) similar to what I showed above
for( auto i = 0u; i < len; ++i ) // common use
- The 41 remaining instances were variable declarations (71%). Here are some examples.
// casts auto c = static_cast<char>( tolower( letter ) ); auto p = reinterpret_cast<unsigned int*>( pData ); // typical assignments auto len = s.length(); auto i = lower_bound( begin(c), end(c), toFind ); auto isFound = ( i != end(c) ); const auto& item = *i; auto result = QueryPerformanceCounter( &li ); auto seconds = millisecs / 1000.0; // typical copy constructors auto nextItem( item );
One of my concerns was that I would miss seeing the obvious “type-ness” of variables, but that fear was mostly unfounded. The type is almost always immediately obvious. It’s certainly obvious with casts. It’s obvious when the variable name was appropriately named, such as isFound (boolean!) and len (integer!). In fact, there was only one place where I could have used auto that I chose not to — a function that established some connections between items.
void CrossConnectNodes( size_t i, size_t j )
{
Node* pNodeI = nodeList[i];
Node* pNodeJ = nodeList[j];
pNodeI->CrossConnect( pNodeJ );
pNodeJ->CrossConnect( pNodeI );
}
The Node declarations could be auto, but Visual Studio Intellisense (VS 2012) doesn’t (yet) allow you to jump to the definition of the Node class if you use the auto keyword. I suspect Microsoft will address this in the future.
I’m a fan and will be using auto on future projects. Once Visual Studio Intellisense fully supports auto, then I can completely endorse auto everywhere.
For even more recommendations on why auto is a good idea (efficiency, guaranteed initialization, and correctness), see Herb’s GotW #93.
{code}auto c = static_cast( tolower( letter ) );
auto p = reinterpret_cast( pData );{code}
it’s nonsense for me. did i something miss?
if it’s valid code – hmm.. what a hell?!
Thanks for catching that error! It looks like WordPress thoughtfully removed the content in the casts 😦
I put them back.
You should check out decltype from here too. e.g. std::vector. I used this recently because I had a template accepting all kinds of function (std::function, lambda, function ptr), so I used it to determine the return value of that function at compile time. Then I specialized that template to do something different if that function returned void. Looked ugly as hell though 🙂
Sigh. std::vector left-angle-bracket decltype(result) right-angle-bracket 😛