2.1.9 Auto

Section 2.1.8 explained how one could deduce the type of an expression with decltype to set the type of a local variable to match the type of an expression.

Now what about storing a lambda in a local variable, what would be the type of the variable? As seen in 2.1.7.0, the type of the lambda is generated by the compiler, and thus out of reach for the programmer. The solution is then found in the auto keyword, introduced in C++11.

bool has_string_of_size 
(const std::vector<std::string>& strings, std::size_t s) 
{ 
  auto predicate = 
     [=](const std::string& string) -> bool 
     { 
       return string.size() == s; 
     }; 
 
  return 
    std::find_if(strings.begin(), strings.end(), predicate) 
    != strings.end(); 
}
Auto as a Type Placeholder

The auto keyword tells the compiler to deduce the actual type of a variable from whatever is assigned to it. It can be used as long as there is an expression the compiler can use to find the type. It can be augmented with const or &.

A typical use is for iterating over an associative container in a for loop:

template<typename F> 
void for_each_entry(const std::map<int, int>& m, F& f) 
{ 
  for (const auto& e : m) 
    f(e.first, e.second); 
}

In the spirit of 2.1.1, the type of e is deduced to std::map<int, int>::value_type, to which are added the const and the &.

When used as a return type, the auto keyword allows to defer the declaration of the actual return type after the argument list. For example, if we don’t know what is the type but we know it is exactly the one of a given expression, we can combine this with decltype:

template<typename F> 
auto indirect_call(F&& f) -> decltype(f()) 
{ 
  return f(); 
}
When not to Use auto

It is tempting to use the auto keyword everywhere, especially for programmers coming from loosely typed languages such as Python or JavaScript. Moreover, using auto gives the satisfying feeling of writing seemingly “generic” code that can work with whatever type is deduced.

In practice, the use of this keyword has lead to very painful to read code, where nothing can be understood without going through every expression assigned to an auto variable, and where entire functions have to be interpreted to eventually find the returned type. This is a very high load to pass to the next reader.

Guideline

Mind the next reader; write what you mean.

Declaring a variable or a function as auto is like writing an innuendo, and innuendos make the communication more difficult; if you see what I mean.

As a rule of thumb, use auto only if:

Absolutely never use auto in place where you could have used basic types like int or bool, or by laziness. It is not because it is shorter that it improves the readability. On the contrary, the readability is improved by being clear about what is going on.