1

The first of these two lines fails to compile, the second compiles in MSVC 2017:

//    std::cout << sizeof(decltype(++std::declval<int>())) << "\n";  //error.  expression must be a modifiable lvalue.
    std::cout << sizeof(decltype(++std::declval<int&>())) << "\n";

The error message is "expression must be a modifiable lvalue."

I know that declval adds an rvalue reference. So in the first line, the compiler considers (does it not?) the outcome of std::declval<int>() to be an rvalue reference. In the second line, the compiler considers the outcome of std::declval<int&>() to be an lvalue reference, due to the collapsing rules.

Why is the rvalue reference not a modifiable lvalue, while the lvalue reference is?

TRPh
  • 187
  • 1
  • 9
  • I think, because you can't say "7=42" but you can say "this integer over here, current value 7, needs to be 42" – Tim Randall Jun 15 '21 at 20:00
  • Do you understand that lvalues are the opposite of rvalues? The last sentence boil down to "why rvalues are not lvalues, while lvalues are lvalues". – HolyBlackCat Jun 15 '21 at 20:00
  • 1
    It does not matter as the program is ill-formed (no diagnostic required) if std::declval is odr-used. – Öö Tiib Jun 15 '21 at 20:06
  • 1
    @ÖöTiib It is used in the context of `sizeof`. – François Andrieux Jun 15 '21 at 20:06
  • @FrançoisAndrieux the question was about modifiability of its return value but that does not matter when the function isn't odr-used. – Öö Tiib Jun 15 '21 at 20:12
  • 1
    @HolyBlackCat an rvalue reference can be an lvalue, when it is a variable for example. Why isn't the rvalue reference here an lvalue? – TRPh Jun 15 '21 at 20:28
  • 3
    Oh, I get the question now. When used as an expression, the name of any variable is an lvalue, regardless of its type. But the value category of a function call result depends on the reference-ness of the return type (prvalue if not a reference, lvalue if `&`, xvalue if `&&`). – HolyBlackCat Jun 15 '21 at 20:32

0 Answers0