If I have the following two loops:
std::vector<int> v;
for(auto i : v)
//do something with i
for(auto& j : v)
//do something with j
When I hover over i, intellisense shows it as int i (as expected). However, when I hover over j I don't get int& as I expected to, but rather
std::_Simple_types<std::_Wrap_alloc<std::_Vec_base_types<int, std::allocator<int> >::_Alloc>::value_type>::value_type &j
What is this complicated definition? Is it the same as int&? If not, what is it? And if it is, why can it deduce just int for i, but not int& for j?
The auto keyword by itself represents a value type, similar to int or char . It can be modified with the const keyword and the & symbol to represent a const type or a reference type, respectively. These modifiers can be combined.
As explained above, the auto keyword in C++ detects the data type of a variable by itself. This means that we can replace the data type of a variable with the keyword auto in C++. The compiler will automatically detect the variable's data type at compile time.
The auto there works just the same. for(auto val : range) will always copy, for(auto& ref : range) will always be a reference.
auto is a keyword in C++11 and later that is used for automatic type deduction. The decltype type specifier yields the type of a specified expression. Unlike auto that deduces types based on values being assigned to the variable, decltype deduces the type from an expression passed to it.
The standard states in 6.5.4 [stmt.ranges]:
For a range-based for statement of the form
for ( for-range-declaration : expression ) statementlet
range-initbe equivalent to the expression surrounded by parentheses( expression )In each case, a range-based for statement is equivalent to
{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
So you can see that in your case the types of i and j are deduced from the type of *it where it is a std::vector iterator. std::vector iterators are implementation defined, however the result of *it is not.
As indicated in the comments, a std::vector iterator is a forward iterator, and after 24.2.5/1 [forward.iterators]:
A class or pointer type
Xsatisfies the requirements of a forward iterator if
- ...
- if X is a mutable iterator,
referenceis a reference toT; ifXis a const iterator,referenceis a reference toconst T,
Here reference is used in 24.4.4/2 [iterator.iterators] to indicate the return type of *it.
Thus for your case the standard requires the type of i to be int and the type of j to be int&. This is probably the case for MSVC++, and intellisense is just not able to correctly resolve the type.
Edit: Fixed the answer regarding the return type when dereferencing iterators.
IntelliSense is giving you a peek into the implementation of std::vector. That is a complicated way of saying reference to std::vector<int>::value_type or, in this case, reference to int.
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