I've been using the new auto
keyword available in the C++11 standard for complicated templated types which is what I believe it was designed for. But I'm also using it for things like:
auto foo = std::make_shared<Foo>();
And more skeptically for:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
I haven't seen much discussion on this topic. It seems that auto
could be overused since a type is often a form of documentation and sanity checks. Where do you draw the line in using auto
and what are the recommended use cases for this new feature?
To clarify: I'm not asking for a philosophical opinion; I'm asking for the intended use of this keyword by the standard committee, possibly with comments on how that intended use is realized in practice.
The auto keyword is a simple way to declare a variable that has a complicated type. For example, you can use auto to declare a variable where the initialization expression involves templates, pointers to functions, or pointers to members.
auto: This is the default storage class for all the variables declared inside a function or a block. Hence, the keyword auto is rarely used while writing programs in C language. Auto variables can be only accessed within the block/function they have been declared and not outside them (which defines their scope).
In C++11, auto can be used for declaring local variables and for the return type of a function with a trailing return type. In C++14, auto can be used for the return type of a function without specifying a trailing type and for parameter declarations in lambda expressions.
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.
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)
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;...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With