Another Opinion on “Almost Always Auto”
by Malte Skarupke
Herb Sutter has been promoting his almost always auto style again, and I think it is harmful. I would agree with “almost always auto” in Scala. I disagree with it in C++. And that’s because there is a slight difference in syntax for type inference between the two languages.
Here’s type deduction in Scala:
val inferred = 0 val typed : Int = 1
And here it is in C++
auto inferred = 0; int typed = 1;
Seems similar, right? But the difference in syntax leads to different long term programmer behavior.
Here’s how explicit typing is explained in the book Programming Scala: A Comprehensive Step-by-Step Guide, 2nd Edition (page 70):
When the Scala interpreter (or compiler) can infer types, it is often best to let it do so rather than fill the code with unnecessary, explicit type annotations. You can, however, specify a type explicitly if you wish, and sometimes you probably should. An explicit type annotation can both ensure the Scala compiler infers the type you intend, as well as serve as useful documentation for future readers of the code.
In Scala adding type information to a variable is purely an additive operation. When you are adding type information, it is seen as improving the code. Another common recommendation is that when you get compiler errors, it often helps to add type annotations to find where the type went wrong.
The important part here is that if you add type information to my code in Scala, I will not remove it again. I probably won’t initially add type information to all my code because often you don’t need it and often it’s faster to just leave it out. (all of Herb Sutter’s arguments also apply)
But Scala’s design ensures that in the long term your code will gather more and more type annotations. Where if you follow Herb Sutter’s advice in C++, that is not the case.
So if I had to translate the Scala method to C++ it would be “start off with auto, but whenever you get the chance, make the types explicit.” But I don’t like this rule. It makes sense in Scala because in Scala type inference is the default. In C++ there is no default, so why recommend doing the version that will benefit from being changed later?
As for Herb’s specific arguments: He is convinced that using auto does not decrease readability. He uses a template as an example of where we already don’t have type information. Which is ironic, because templates are notoriously unreadable. There are reasons why so many people are intimidated by templates, and the lack of type information is one of them.
Another problem is that I search for types a lot. Whenever I come to a new piece of code I do a lot of searches for type names and function names to get a rough understanding of how pieces fit together. In Visual Studio I can search for all references of a type, but it is unreliable. I usually just do a plain text search because it is more reliable than using the smarter search. Using auto makes searching for types more difficult, which adds work for people when they want to learn how objects are used.
Which is why I’m much more pragmatic about auto: I use it only if I think that the type information will not be terribly useful for people looking at my code. Meaning mainly for iterators.