I use const auto on occasion, when the element type is inexpensive to copy. If I'm iterating over a vector if int's, why would I prefer const auto& over const auto? Assuming the compiler does not try to optimize the const auto&, const auto should be faster than accessing a value through a reference.
Using const auto& over const auto makes your code more robust. For example, what if you later decide to change the type of items in the vector from ints to something that is more expensive to copy? You would need to track all uses of the vector and add an ampersand there. And as for the access speed, YMMV but compilers are generally good at optimizations and will drop the reference when it would be faster to just cop…
Auto Type Deduction in C++ Range-Based For Loops
11–20 of 28 posts
Re: Auto Type Deduction in C++ Range-Based For Loops
#12I use const auto on occasion, when the element type is inexpensive to copy. If I'm iterating over a vector if int's, why would I prefer const auto& over const auto? Assuming the compiler does not try to optimize the const auto&, const auto should be faster than accessing a value through a reference.
Using const auto& over const auto makes your code more robust. For example, what if you later decide to change the type of items in the vector from ints to something that is more expensive to copy? You would need to track all uses of the vector and add an ampersand there. And as for the access speed, YMMV but compilers are generally good at optimizations and will drop the reference when it would be faster to just cop…
Re: Auto Type Deduction in C++ Range-Based For Loops
#13I don't like that at all. Sure if you consider: for (auto& p : wordCount) { // ... word: p.first, count: p.second } then for (auto& [word, count] : wordCount) { // C++1z // ... } seems like an improvement because you immediately know the semantics of the two parts of the pair. But you have no idea what "word" or "count" is . In this example with words like "word" or "count" the semantics somehow encode type informati…
> if you consider:
>
> for (auto& p : wordCount) {
> ...
> But you have no idea what "word" or "count" *is*.
If you know what wordCount is, you'll know what types word and count are.I remember back when I was still a very new programmer I somehow got the syntax for an iterator-based loop wrong ("for std::vector::iterator itor = v.begin(); itor != v.end(); ++itor)"). I don't remember my mistake. I probably missed a const somewhere. The compiler told me that "std::vector::iterator" did not match the type of v.begin(), but it wouldn't tell me what would match. Even as a beginning programmer, I knew the compiler knew, but all it would say was "you got it wrong."
And, of course, I didn't care what the type of v.begin() was. All I cared about was whether I could iterate over the elements of v. And I knew that v contained int's.
Many programmers learned about strong typing ( https://en.wikipedia.org/wiki/Strong_and_weak_typing ) and static typing ( https://en.wikipedia.org/wiki/Type_system#STATIC ) in languages that require manifest typing ( https://en.wikipedia.org/wiki/Manifest_typing ), so they often don't realize those are three distinct ideas. You can write strongly typed programs in Haskell, Ocaml, Go and Rust without many type statements.
Re: Auto Type Deduction in C++ Range-Based For Loops
#14Wouldn't one want to use 'f(std::forward(x))' with 'auto&&' ?
I think the example with function application is a bad one here - moving the element potentially leaves it in an undefined state. It would be a better example if the code did something with x instead of calling a function on it. So I don't think you'd want to forward it. Note that you also need the element's type to forward it, which isn't possible in general with the example's signature.
void somefunction(int && i) // i is an rvalue reference
template void somefunction2(T && i) // i is a universal reference
It might be a similar thing with auto&&. So I would tentatively agree that std::forward should be used.
Re: Auto Type Deduction in C++ Range-Based For Loops
#15Earlier quoted context omitted.
Using const auto& over const auto makes your code more robust. For example, what if you later decide to change the type of items in the vector from ints to something that is more expensive to copy? You would need to track all uses of the vector and add an ampersand there. And as for the access speed, YMMV but compilers are generally good at optimizations and will drop the reference when it would be faster to just cop…
But be careful about the lifetime of the object referenced! Just because its 'const' doesn't mean it cant go out of scope.
[1]: https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-th...
Re: Auto Type Deduction in C++ Range-Based For Loops
#16Earlier quoted context omitted.
But be careful about the lifetime of the object referenced! Just because its 'const' doesn't mean it cant go out of scope.
Local const reference prolongs the object lifetime[1]. There shouldn't be any problems whenever you use it in a for loop. [1]: https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-th...
Re: Auto Type Deduction in C++ Range-Based For Loops
#17Earlier quoted context omitted.
I think the example with function application is a bad one here - moving the element potentially leaves it in an undefined state. It would be a better example if the code did something with x instead of calling a function on it. So I don't think you'd want to forward it. Note that you also need the element's type to forward it, which isn't possible in general with the example's signature.
This has been slightly confusing to me, but the syntax auto&& might not mean an rvalue reference. According to the post, it means a universal reference. I wish they would have made a different syntax. For example, with templates, my understanding is: void somefunction(int && i) // i is an rvalue reference template void somefunction2(T && i) // i is a universal reference It might be a similar thing with auto&&. So I w…
- if you put in an rvalue reference, it's like std::move
- if you put in anything else, it does nothing.
So my point about the article's formulation ("when you want to modify elements in the range in generic code") and its example remains.
Re: Auto Type Deduction in C++ Range-Based For Loops
#18I don't like that at all. Sure if you consider: for (auto& p : wordCount) { // ... word: p.first, count: p.second } then for (auto& [word, count] : wordCount) { // C++1z // ... } seems like an improvement because you immediately know the semantics of the two parts of the pair. But you have no idea what "word" or "count" is . In this example with words like "word" or "count" the semantics somehow encode type informati…
Re: Auto Type Deduction in C++ Range-Based For Loops
#19I don't like that at all. Sure if you consider: for (auto& p : wordCount) { // ... word: p.first, count: p.second } then for (auto& [word, count] : wordCount) { // C++1z // ... } seems like an improvement because you immediately know the semantics of the two parts of the pair. But you have no idea what "word" or "count" is . In this example with words like "word" or "count" the semantics somehow encode type informati…
What auto says is "I don't care what type this value is. I just want it to support the semantics that I'm about to describe in this block." If you change the return type of the value in the auto expression, as long as the new return type supports the same semantics as the original return type, you don't need to touch that function after the refactor.
The compiler still complains when it can't find a way to make the return value support the semantics you're asking for. This is an improvement, but only in cases where you genuinely don't care what type it is, but only that it supports iteration. You still have to use auto with care, like every other keyword, but it does significantly improve maintainability in code bases where traditionally you would mechanically key in the same type information multiple times throughout the declaration of a class and its usage. Typedef and using statements solve similar problems, but they don't solve exactly the same problem.
For a good example of why this is a wonderful thing, try to determine what return type you should declare for an STL iterator, or try using Boost while avoiding the auto keyword.
Re: Auto Type Deduction in C++ Range-Based For Loops
#20Wouldn't one want to use 'f(std::forward(x))' with 'auto&&' ?
I think the example with function application is a bad one here - moving the element potentially leaves it in an undefined state. It would be a better example if the code did something with x instead of calling a function on it. So I don't think you'd want to forward it. Note that you also need the element's type to forward it, which isn't possible in general with the example's signature.