Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++0x const RValue reference as function parameter

I am trying to understand why someone would write a function that takes a const rvalue reference.

In the code example below what purpose is the const rvalue reference function (returning "3"). And why does overload resolution preference the const Rvalue above the const LValue reference function (returning "2").

#include <string> #include <vector> #include <iostream>  std::vector<std::string> createVector() { return std::vector<std::string>(); }   //takes movable rvalue void func(std::vector<std::string> &&p) { std::cout << "1"; }  //takes const lvalue void func(const std::vector<std::string> &p)  { std::cout << "2"; }  //takes const rvalue??? //what is the point of const rvalue? if const I assume it is not movable? void func(const std::vector<std::string> &&p) { std::cout << "3"; }  int main() {     func(createVector());     return 0; } 
like image 426
MW_dev Avatar asked Jun 10 '11 14:06

MW_dev


People also ask

How do you pass rvalue reference to a function?

If you want pass parameter as rvalue reference,use std::move() or just pass rvalue to your function.

Can R values be const qualified?

They are allowed and even functions ranked based on const , but since you can't move from const object referred by const Foo&& , they aren't useful.

When should a function take rvalue reference?

rvalue references are more often used as function parameters. This is most useful for function overloads when you want to have different behavior for lvalue and rvalue arguments. Rule 1: Do not write && to return type of a function, and there is no need to return a local variable using std::move .

Can a function return an rvalue?

Typically rvalues are temporary objects that exist on the stack as the result of a function call or other operation. Returning a value from a function will turn that value into an rvalue. Once you call return on an object, the name of the object does not exist anymore (it goes out of scope), so it becomes an rvalue.


2 Answers

Lvalues strongly prefer binding to lvalue references, and similarly rvalue references strongly prefer binding to rvalue references. Modifiable expressions weakly prefer binding to a non-const reference.

So when your compiler is doing overload resolution, it checks if there's an overload that takes an rvalue reference, because that's preferred strongly. In this case since the experssion is a modifiable rvalue, so the rvalue reference overload wins.

There is actually use for const rvalue references, they can be used to make sure something does not bind to an rvalue. Remember that an rvalue binds to a const lvalue reference, hence if you did:

template <typename T> void foo(const T& bar) { /* ... */ } 

And called the function with:

foo(createVector()); 

It'd work fine. However sometimes it is desired to ensure that you can only pass lvalues to a function (this is the case for std::ref for one). You can achieve this by adding an overload:

template <typename T> void foo(const T&&) = delete; 

Remember, rvalues strongly prefer binding to rvalue references, and modifiable expressions prefer weakly binding to non-const references. Since we have a const rvalue-reference, it basically means that every single rvalue will bind to this, hence if you try to pass a rvalue to foo(), your compiler will give an error. This is the only way to achieve such functionality, and thus is sometimes useful.

like image 113
reko_t Avatar answered Sep 23 '22 07:09

reko_t


Overload resolution prefers const rvalue over const lvalue because, well, it's an rvalue and you're binding it to an rvalue reference, but you have to add const in both cases, so rvalue reference definitely preferred.

Such things are generally pointless- it's best to leave them binding to the const lvalue overloads. const rvalues don't have any real use.

like image 43
Puppy Avatar answered Sep 23 '22 07:09

Puppy