Search code examples
c++referencelvaluervalue

Is this true that variables whose address can be taken are lvalues?


Recently while reading blog on universal reference by scott meyers i came along statement that "if you can take the address of an expression, the expression is an lvalue." but is this really true

Suppose i have following code

class Test
{
};
int main()
{
   std::cout << "Address is " << &(Test()) << std::endl;
   Test() = Test();
   Test&& t = Test();
   return 0;
}

In above case Test() is temporary i.e rvalue and i am able to take address of that (with gcc we can use -fpremissive and with msvc it will compile directly) so with this we can say it is lvalue and also bcoz we can do Test() = Test() but since we can take rvalue reference to it so it should be rvalue.

So why we always say that if we can take address of variable then it is lvalue ?


Solution

  • Your first code is incorrect because the declaration of z should be int*, this code compiles and works fine:

    int x = 12;  // x is lvalue
    int& y = x;  // y is lvalue reference
    int *z = &y; // can take address of lvalue reference (address of the referenced)
    assert(z == &x);
    

    For your second example, Test() is actually a prvalue and you cannot take its address in a portable way as mentioned per the standard.

    MSVC has extensions that allow you to take the address of prvalues, and GCC allows you to enable this kind of extension using -fpermissive:

    Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive will allow some nonconforming code to compile.

    This means that Scott Meyers is right and the compilers are wrong, at least in the question of conforming to the standard. Also, by passing -fpermissive you told gcc to be less strict, i.e. allow your non-conforming code to compile. To be completely conforming, you should always compile with -pedantic or -pedantic-errors (because just like MSVC, gcc also enables some language extensions by default).