mardi 22 août 2023

Why rvalue references behave differently based on types?

I'm reading about C++ rvalue references and value categories for expressions. However, I'm not able to grasp (from a lvalue, xvalue, prvalue point of view) why the following code works as expected:

struct S {
    int a;
};

S&& t(S& a) {
    return (S&&)a;
}

int main()
{   
    S s = { 1 };
    t(s) = S{ 2 };
    cout << s.a; // prints 2
    return 0;
}

Whereas the following one doesn't even compile, and shows error: using rvalue as lvalue:

int&& t(int& a) {
    return (int&&)(a);
}

int main()
{   
    int s = 1;
    t(s) = 2; // error
    std::cout << s;
    return 0;
}

To me, in both cases t(s) should behave as an xvalue. Hence, it can appear to the left of the assignment operator (not discussing operator overriding in this context). The standard literally says that The result of calling a function whose return type is an rvalue reference is an xvalue. Why is it behaving differently for int and for struct S? Is this behavior, in any way, predicted by the standard (or by cppreference.com)? I couldn't realize what order of ideas gets into this scenario.

I was expecting the second code to print 2, based on the reasoning that the memory location of s, initially holding 1 would be overwritten by 2 by means of the rvalue reference.

Aucun commentaire:

Enregistrer un commentaire