I thought I've managed to fully understand (with the help of other SO questions, thanks) the C++17's change regarding value categories, but now I've noticed this problem which suggests I don't really understand them.
In C++11, there was a "has identity / can be moved from" interpretation of value categories and the definition of what "identity" means is still present in cppreference:
has identity: it's possible to determine whether the expression refers to the same entity as another expression, such as by comparing addresses of the objects or the functions they identify (obtained directly or indirectly).
In C++17, "has identity / can be moved from" is no longer true, but the new definition is also based on the concept of "identity":
a glvalue (“generalized” lvalue) is an expression whose evaluation determines the identity of an object, bit-field, or function;
My question/misunderstanding is: is this the same meaning of "identity", or is it a different "identity"? The way I understand it, the situation in c++17 is as follows:
A f() { return A(); }
A a = f(); // 1: f() is a prvalue expression, used to directly initialize a.
f(); // 2: f() is a prvalue expr., converted to xvalue by temporary materialization
A&& r = f(); // 3: f() is a prvalue expr., converted to xvalue by temporary materialization
In the 2nd and 3rd case, I obtain an xvalue, which means it should have an identity. So I should be able to get its address [edited:] I should be able to determine whether it refers to the same entity as some other expression, but I don't think I can. Of course, in the 3rd case I'm able to do "&r" as a separate command and then compare its address to the other expression's address, but that's because A&& is an lvalue. Is taking the address via A&& what they mean in this case by "obtained directly or indirectly"? I assumed this can't be the correct answer, because in C++11 I can also easily do
A&& r = f(); // 4: f() is a prvalue expression. Temporary materialization does
// not happen, the temporary (prvalue) gets its lifetime
// extended to match the lifetime of the reference
&r;
and yet the object referenced by r is still a temporary despite having its lifetime extended, and in c++11 temporaries are prvalues. So I assume just the fact I can bind A&& to it (of which, like any lvalue, I can take an address but only in a separate expression) is not enough to conclude that its evaluation determines an identity (after all, whatever happens in the line "&r;" is not part of an evaluation of my original expression), and yet in c++17 it looks to me like this would be the only possible interpretation?
Can you help me by determining which part of what I wrote is incorrect? Or is it correct, and the answer is simply that the word "identity" has changed its meaning?