Whether to use T const& or T&&
Asked Answered
O

3

7

I'm curious if, in general, you are to use T&& (universal reference) instead of the classic T const& (l-value reference) for templated function parameters starting with C++11. What I'm especially curious is how you get around the fact that you are forced to lose the const if you want to also handle r-value references; is there a way around this?

Oralla answered 8/6, 2015 at 23:54 Comment(4)
I'm not sure what you're asking; can you give an example?Infatuation
How do I enforce const for all references even if I am not passed a const l-value reference? It seems like using T&& poses the risk of losing that const if the user doesn't pass a const reference to it.Oralla
So you want a function that deduces an rvalue of type T as T &&, const lvalue as const T & and (non-const) lvalue also as const T &. Is that what you are saying? The intent of your question is really hard to, well, deduce.Mcmillian
The question was two part: if T&& is preferred over T const& and how to force const even if the type deduced is not const. Sorry if the question wasn't clear enough.Oralla
B
8

There is no problem with "losing the const". T will be deduced with cv-qualifiers if the argument is cv-qualified. For example, if the argument is an rvalue of type const std::string, then T will be deduced as const std::string. You cannot possibly violate const-correctness by using forwarding references. If you could, it would be a major language defect.

As for the broader question of when forwarding references should be used, see here: Proper use of universal references

Brundage answered 9/6, 2015 at 0:18 Comment(2)
I was under the impression you used T const& to guarantee your function would not modify the variable. What if the user doesn't pass you a const cast l-value reference but doesn't want you to modify it? Just make sure you don't?Oralla
@Salgat If you want to write a function that will never modify its argument then maybe you had better stick with T const&. Forwarding references are useful when you might want to move out of the value passed in, or something like that.Brundage
M
1

You are not forced to lose const: template<typename T> void fun(T &&val) might bind non-const lvalues, const l-values and rvalues. You are still perfectly allowed to do template<typename T> void fun(const T &v) which will be a more specialized overload for const references, hence non-modifiable l-values will hit this overload.

The first overload, with the 'forward reference' will bind to modifiable values and rvalues. If I read a prototype of a template function with a forwarding reference (what S. Meyers baptized as "universal reference") what that tells me is that the function might take advantage of move semantics, nothing more.

It is possible to detect the constness of the argument internally; however, since you ask whether this is the recommended general way, I would say that managing the non-modifiable l-value in its own overload is recommended except when impractical (such as when dealing with multiple parameters that may or not be const)

Mitzvah answered 9/6, 2015 at 0:19 Comment(0)
T
0

This question is pretty marginal since you're asking for an opinion, but to answer the technical bit, you don't loose the const. That's why it's called a universal reference.

Tetra answered 9/6, 2015 at 0:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.