camino
camino

Reputation: 10584

Any member function invoked from a rvalue will return a rvalue?

I am wondering if any member function invoked from a rvalue will return a rvalue in c++11 standard.

for example:

Obj foo();
struct Obj
{
    int& operator[](int i)
    {   
        return data_[i]; 
    }
    int data_[20];
};
foo()[1]; // this expression will be treated as rvalue, right? 
          // althrough operator[] return a reference

UPDATE:

if not, it will be very easy to make the mistake below:

decltype(foo()[1]) ai = foo()[1];  //both reference to an obj destroied
decltype(auto) ai = foo()[1];

Upvotes: 1

Views: 63

Answers (2)

Shoe
Shoe

Reputation: 76240

No, the result of foo()[1] is an lvalue. According to §3.10:

An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. [ Example: If E is an expression of pointer type, then *E is an lvalue expression referring to the object or function to which E points. As another example, the result of calling a function whose return type is an lvalue reference is an lvalue. — end example ]

(emphasis mine)

On the other hand you can make it so it returns an rvalue reference in that case, by using:

struct Obj
{
    int&& operator[](int i) &&
    //                      ^^
    {   
        return std::move(data_[i]); 
        //     ^^^^^^^^^^        ^
    }
    int data_[20];
};

or declare the function to be not allowed on r-values by

struct Obj
{
    int& operator[](int i) &
    //                      ^^
    {   
        return data_[i];
    }
    int data_[20];
};

This will now trigger a compile-time error when you do bar()[0].

Upvotes: 2

TartanLlama
TartanLlama

Reputation: 65610

Nope, it'll be an lvalue and if you store a reference to it some place you're on the fast-track to undefined behaviour.

A similar relatively common mistake is storing the result of std::string::c_str():

const char* dont_do_this = getStdString().c_str();

Regarding your update code, the solution is to be aware of object lifetimes when you could be creating a reference. decltype(x) can be a reference type, so you better be sure that if it is, you aren't referencing something which is going to be blasted into oblivion.

Upvotes: 3

Related Questions