const auto&
would suffice if I want to perform read-only operations. However, I have bumped into
for (auto&& e : v) // v is non-const
a couple of times recently. This makes me wonder:
Is it possible that in some obscure corner cases there is some performance benefit in using universal references, compared to auto&
or const auto&
?
(shared_ptr
is a suspect for obscure corner cases)
Update Two examples that I found in my favorites:
Any disadvantage of using const reference when iterating over basic types?
Can I easily iterate over the values of a map using a range-based for loop?
Please concentrate on the question: why would I want to use auto&& in range-based for loops?
I virtually always use
auto&&
. Why get bitten by an edge case when you don't have to? It's shorter to type too, and I simply find it more... transparent. When you useauto&& x
, then you know thatx
is exactly*it
, every time.Using
auto&&
or universal references with a range-basedfor
-loop has the advantage that you captures what you get. For most kinds of iterators you'll probably get either aT&
or aT const&
for some typeT
. The interesting case is where dereferencing an iterator yields a temporary: C++ 2011 got relaxed requirements and iterators aren't necessarily required to yield an lvalue. The use of universal references matches the argument forwarding instd::for_each()
:The function object
f
can treatT&
,T const&
, andT
differently. Why should the body of a range-basedfor
-loop be different? Of course, to actually take advantage of having deduced the type using universal references you'd need to pass them on correspondingly:Of course, using
std::forward()
means that you accept any returned values to be moved from. Whether objects like this makes much sense in non-template code I don't know (yet?). I can imagine that using universal references can offer more information to the compiler to do the Right Thing. In templated code it stays out of making any decision on what should happen with the objects.The only advantage I can see is when the sequence iterator returns a proxy reference and you need to operate on that reference in a non-const way. For example consider:
This doesn't compile because rvalue
vector<bool>::reference
returned from theiterator
won't bind to a non-const lvalue reference. But this will work:All that being said, I wouldn't code this way unless you knew you needed to satisfy such a use case. I.e. I wouldn't do this gratuitously because it does cause people to wonder what you're up to. And if I did do it, it wouldn't hurt to include a comment as to why:
Edit
This last case of mine should really be a template to make sense. If you know the loop is always handling a proxy reference, then
auto
would work as well asauto&&
. But when the loop was sometimes handling non-proxy references and sometimes proxy-references, then I thinkauto&&
would become the solution of choice.