I have three function calls that I think should be treated (about) the same, but clearly they are not. I'm trying to understand why one of three doesn't compile (g++ -std=c++0x).
// Minimal example to reproduce a compile bug I want to understand.
#include <iostream>
#include <string>
using namespace std;
void bar(const string &&x) { cout << "bar: " << x << endl; }
string returns_a_string() { return string("cow"); }
int main( int argc, char *argv[] )
{
bar(string("horse")); // ok
bar(returns_a_string()); // ok
string aardvark = "aardvark";
bar(aardvark); // not ok, fails to compile, error in next comment
/*
rvalue-min.cpp:29:22: error: cannot bind ‘std::string {aka std::basic_string<char>}’ lvalue to ‘const string&& {aka const std::basic_string<char>&&}’
rvalue-min.cpp:10:6: error: initializing argument 1 of ‘void barR(const string&&)’
*/
}
This question is a bit along the lines of C++0x rvalue references - lvalues-rvalue binding, but, if it's answered there, my apologies, I wasn't able to distil it out.
What I want is to be able to call my function bar() with any sort of string and have it just work. It's enough to define void barR(const string &x)
, but I'd really like to understand why.
Thanks much for any help in understanding why the third call is different.
The purpose of r-value reference parameters is to detect specifically when an object is an r-value. Because if an object is an r-value, then the function knows it won't be used again, so it can do whatever it wants with it. If an l-value could bind to an r-value reference, that would mean the detection I was talking about wasn't actually taking place.
If you want to pass an l-value to one of these functions, you need to use std::move
. Passing an object via std::move
to a function that takes an r-value reference is like saying, "here, take this object, rip it's guts out, I don't care what happens to it".
For your purposes, the correct answer is to make the parameter const reference. An r-value is perfectly happy being bound to a const reference. Except for move constructors, making r-value reference parameters is almost never the correct thing to do.
You need to use std::move
. This works fine :
bar(std::move(aardvark));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With