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?
Whether to use T const& or T&&
993 views Asked by Austin Salgat AtThere are 3 answers
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)
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 typeconst std::string
, thenT
will be deduced asconst 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