Search code examples
c++c++11rvaluethis-pointer

C++ what is the value category of *this?


Section 9.3.2.1 of the C++ standard states:

In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*. If the member function is declared const, the type of this is const X*, if the member function is declared volatile, the type of this is volatile X*, and if the member function is declared const volatile, the type of this is const volatile X*.

So if this is a prvalue, what is the value category of *this? The following suggests that even when the object is an rvalue, *this is always an lvalue. Is this correct? Please refer to the standard, if possible.

struct F;
struct test
{
    void operator()(F &&) { std::cout << "rvalue operator()" << std::endl; }
    void operator()(F const &&) { std::cout << "const rvalue operator()" << std::endl; }
    void operator()(F &) { std::cout << "lvalue operator()" << std::endl; }
    void operator()(F const &) { std::cout << "const lvalue operator()" << std::endl; }
};

struct F
{
    void operator ()()
    {
        struct test t;
        t(*this);
    }
};

int main()
{
    struct F f;
    f();
    std::move(f)();
}

Output:

lvalue operator()
lvalue operator()

Solution

  • From [basic.lval]:

    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 ]

    And from [expr.unary.op]:

    The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points.

    Dereferencing a pointer is an lvalue. So *this is an lvalue.

    Alternatively, anything that isn't an lvalue is an rvalue. An rvalue is:

    An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

    And *this is definitely none of those things.