q126y
q126y

Reputation: 1671

Const Rvalue reference to capture overloads which are not supposed to be compilable

Scott Meyers in this talk at 44:15, says const Rvalue references are used in c++0x standard library to capture certain overloads which are not supposed to be compilable.

Code snippet to illustrate the above mentioned point would be helpful. Thanks.

Upvotes: 3

Views: 54

Answers (1)

vsoftco
vsoftco

Reputation: 56547

One usage that I found useful is to disable temporaries biding to reference members. For example, consider the code below:

struct Foo{};

class X
{
    const Foo& _foo;
public:    
    X(const Foo&&) = delete;       // prevents rvalue binding
    X(const Foo& foo): _foo(foo){} // lvalue is OK
};

Foo get_Foo()
{
    return {};
}

const Foo get_const_Foo()
{
    return {};
}

Foo& get_lvalue_Foo()
{
    static Foo foo;
    return foo;
}

int main() 
{
//  X x1{get_Foo()};        // does not compile, use of deleted function
//  X x2{get_const_Foo()};  // does not compile, use of deleted function
    X x3{get_lvalue_Foo()}; // OK
}

You definitely want to disable a rvalue being passed to the constructor of X, since rvalues do not bind to const references via constructor parameters, so you end up with a dangling reference. Why const Foo&& and not simply Foo&&? Because if you use X(Foo&&) = delete;, then if your get_Foo() returns const Foo (which is a bad idea, but nevertheless is seen in actual code), it will bind to X(const Foo&) instead, and you end up with a dangling reference. However, X(const Foo&&) in the code above is a better match for a const Foo rvalue, so we obtain the desired effect of not being able to construct an X with a rvalue.

You may also ask why not defining X(Foo&) instead for the lvalue constructor. Then you won't be able to bind const lvalues. So the best approach is to mark X(const Foo&&) = delete;. Hope this clarifies it.

Upvotes: 1

Related Questions