Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How much is too much with C++11 auto keyword?

I think that one should use the auto keyword whenever it's hard to say how to write the type at first sight, but the type of the right hand side of an expression is obvious. For example, using:

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

to get the composite key type in boost::multi_index, even though you know that it is int. You can't just write int because it could be changed in the future. I would write auto in this case.

So if the auto keyword improves readability in a particular case then use it. You can write auto when it is obvious to the reader what type auto represents.

Here are some examples:

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)

Use auto everywhere you can—particularly const auto so that side effects are less of a concern. You won’t have to worry about types except in the obvious cases, but they’ll still be statically verified for you, and you can avoid some repetition. Where auto isn't feasible, you can use decltype to express types semantically as contracts based on expressions. Your code will look different, but it will be a positive change.


Easy. Use it when you don't care what the type is. For example

for (const auto & i : some_container) {
   ...

All I care about here is that i is whatever's in the container.

It's a bit like typedefs.

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

Here, I don't care whether h and w are floats or doubles, only that they are whatever type is suitable to express heights and weights.

Or consider

for (auto i = some_container .begin (); ...

Here all I care about is that it's a suitable iterator, supporting operator++(), it's kind of like duck typing in this respect.

Also the type of lambdas can't be spelled, so auto f = []... is good style. The alternative is casting to std::function but that comes with overhead.

I can't really conceive of an "abuse" of auto. The closest I can imagine is depriving yourself of an explicit conversion to some significant type -- but you wouldn't use auto for that, you'd construct an object of the desired type.

If you can remove some redundancy in your code without introducing side effects, then it must be good to do so.

Counterexamples (borrowed from someone else's answers):

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

Here we DO care what the type is, so we should write Someclass i; and for(unsigned x = y;...


Go for it. Use auto anywhere it makes writing code easier.

Every new feature in any language is going to get overused by at least some types of programmers. It is only through moderate overuse by some experienced programmers (not noobs) that the rest of the experienced programmers learn the boundaries of proper use. Extreme overuse is usually bad, but could be good because such overuse may lead to improvements in the feature or a better feature to replace it.

But if I were working on code with more than a few lines like

auto foo = bla();

where the type is indicated zero times, I might want to change those lines to include types. The first example is great since the type is stated once, and auto saves us from having to write messy templated types twice. Hooray for C++++. But explicitly showing the type zero times, if it's not easily visible in a nearby line, makes me nervous, at least in C++ and its immediate successors. For other languages designed to work at a higher level with more abstraction, polymorphism and genericity, it's fine.


At C++ and Beyond 2012 in the Ask Us Anything panel, there was a fantastic exchange between Andrei Alexandrescu, Scott Meyers and Herb Sutter talking about when to use and not use auto. Skip to minute 25:03 for a 4 minute discussion. All three speakers give excellent points that should be kept in mind for when to not use auto.

I highly encourage people to come to their own conclusion, but my take away was to use auto everywhere unless:

  1. It hurts readability
  2. There is concern about automatic type conversion (e.g. from constructors, assignment, template intermediate types, implicit conversion between integer widths)

Liberal use of explicit helps reduce concern for the latter, which helps minimize the amount of time the former is an issue.

Rephrasing what Herb said, "if you're not doing X, Y, and Z, use auto. Learn what X, Y, and Z are and go forth and use auto everywhere else."


Yes, it can be overused to the detriment of readability. I suggest using it in the contexts where exact types are long, or unutterable, or not important for readability, and variables are short-lived. For example, iterator type usually is long and isn't important, so auto would work:

   for(auto i = container.begin(); i != container.end(); ++i);

auto here doesn't hurt readability.

Another example is parser rule type, which can be long and convoluted. Compare:

   auto spaces = space & space & space;

with

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

On the other hand, when type is known and is simple, it's much better if it stated explicitly:

int i = foo();

rather than

auto i = foo();