Search code examples
c++functiontypesreturn-typelvalue

Why can int not be used as an l-value of a return type while a user-defined class can?


struct A {};

A f1()
{
    return A();
}

int f2()
{
    return int();
}

int main()
{
    f1() = A();   // OK
    f2() = int(); // error C2106: '=' : left operand must be l-value
}

Why is f1() = A(); OK while f2() = int(); is failed?


Solution

  • The function f1 returns a rvalue, which might become an xvalue (an “eXpiring” value). The function f2 returns a builtin type which is an rvalue becomming an prvalue (“pure” rvalue).

    From 3.10 [Lvalues and rvalues]

    — An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2).

    Hence, due to an implicit move operation the assignment of A becomes valid.

    Changing A to:

    struct A {
        A() {}
        A(A&&) = delete;
        A& operator = (const A&) { return *this; }
    };
    

    produces: error: use of deleted function ‘A::A(A&&)’ with g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2