Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whether to use T const& or T&&

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?

like image 955
Austin Salgat Avatar asked Jun 08 '15 23:06

Austin Salgat


People also ask

When should you use const?

The const keyword allows you to specify whether or not a variable is modifiable. You can use const to prevent modifications to variables and const pointers and const references prevent changing the data pointed to (or referenced).

Should I always use const reference?

Yes, you should use const whenever possible. It makes a contract that your code will not change something. Remember, a non-const variable can be passed in to a function that accepts a const parameter.

Why should you declare a variable const even though the compiler doesn't require it?

The compiler will issue an error if an attempt is made to change a value using a const qualified pointer, but declaring such a pointer will not change the generated code.

Why should we use const?

We use the const qualifier to declare a variable as constant. That means that we cannot change the value once the variable has been initialized. Using const has a very big benefit. For example, if you have a constant value of the value of PI, you wouldn't like any part of the program to modify that value.


2 Answers

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

like image 132
Brian Bi Avatar answered Oct 04 '22 02:10

Brian Bi


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)

like image 21
TheCppZoo Avatar answered Oct 04 '22 01:10

TheCppZoo