What standard clause mandates this lvalue-to-rvalue conversion? - c++

Given:
int main() {
int x = 0;
int y = x; // <---
}
Could someone please tell me which clause of the standard (2003 preferred) mandates the conversion of the expression x from lvalue to rvalue in the initialisation of the object y?
(Or, if I'm mistaken and no such conversion takes place, then I'd like to learn that too!)

I find it easier (if maybe not 100% precise) to think of lvalue-s as real objects and rvalue-s as the value stored in the object. The expression x is an lvalue expression that refers to the object x defined in the first line, but when used as the right hand side of an assignment to a type that is not a user defined type the actual value is read, and that is where the conversion from lvalue to rvalue is performed: reading the contents of the object.
As to the specific clause in the standard that dictates that conversion... well, the closest that I can think is 4.1 [conv.lvalue]/2 (Lvalue to Rvalue conversion):
The value contained in the object indicated by the lvalue is the rvalue result.
The requirement that the right hand side of the assignment is an rvalue is either implicit or missing from 5.17 [expr.ass], but that is the case or else the following expression would be an error since the rhs is an rvalue and there is no rvalue-to-lvalue conversion:
int x = 5;
EDIT: For initialization, 8.5 [dcl.init]/14, last bullet (which refers to fundamental types) states (emphasis mine):
Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. [...]
That value there means that the lvalue expression in your example is read (i.e. converted to an rvalue). At any rate the previous paragraph that referred to assignment could be applied here: if initialization required an lvalue rather than an rvalue, the expression int i = 0; would be ill-formed.

I do believe that this is intuitive to some degree (what others already said - the value is needed, so there is an obvious need to convert the object designator to the value contained therein). The best I could come up with, by 4p3:
An expression e can be implicitly converted to a type T if and only if the declaration "T t=e;" is well-formed, for some invented temporary variable t (8.5). The effect of the implicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The result is an lvalue if T is a reference type (8.3.2), and an rvalue otherwise. The expression e is used as an lvalue if and only if the initialization uses it as an lvalue.
Note the "if and only if" at the end - the initializer therefor is used as an rvalue, because the initialization uses it as an rvalue (result of the conversion). So by 3.10p7
Whenever an lvalue appears in a context where an rvalue is expected, the lvalue is converted to an rvalue; see 4.1, 4.2, and 4.3.
EDIT: The paragraph for entering 4p3 can be found at 8.5p16, last bullet:
Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression.
Also note the comments below.

Is this what you're looking for:
§3.10/7
Whenever an lvalue appears in a context where an rvalue is expected, the lvalue is converted to an rvalue; see 4.1, 4.2, and 4.3.
And I think when you write int y = x, it basically copies the value contained in the object x which is a lvalue, but the value itself is an rvalue, hence the context expects an rvalue.
§4.1/2 says,
The value contained in the object indicated by the lvalue is the rvalue result.
Maybe these two quotations clarify your doubt. Correct me if my understanding is wrong. I would like to learn new things.
#Tomalak's comment:
My problem with this is that int& y = x; is valid, so in this case of course x may not be an rvalue. I don't know how irrelevant the difference in my example makes that, though
Well int &y = x does NOT copy the value. It just creates an alias of the object itself. But as I previously said int y = x, basically copies the value which is an rvalue. Hence, the context expects an rvalue, as a copying is being done here.

The initializer has the follwing grammar:
initializer:
= initializer-clause
( expression-list )
initializer-clause:
assignment-expression
{ initializer-list ,opt }
{ }
In your example, x is an assignment-expression which follows this chain of grammar productions:
conditional-expression ==>
logical-or-expression ==>
logical-and-expression ==>
inclusive-or-expression ==>
exclusive-or-expression ==>
and-expression ==>
equality-expression ==>
relational-expression ==>
shift-expression ==>
additive-expression ==>
multiplicative-expression ==>
pm-expression ==>
cast-expression ==>
unary-expression ==>
postfix-expression ==>
primary-expression ==>
id-expression ==>
unqualified-id ==>
identifier
And an identifier "is an lvalue if the entity is a function or variable" (5.1/4 "Primary expressions").
So in your example, the expression to the right of the = is an expression that happens to be an lvalue. It could be an rvalue of course, but it doesn't have to be. And there is no mandated lvalue-to-rvalue conversion.
I'm not sure what the value in knowing this is, though.

3.10 Lvalues and rvalues
1 Every expression is either an lvalue
or an rvalue.
2 An lvalue refers to an object or
function. Some rvalue
expressions—those of class or
cvqualified class type—also refer to
objects.47)
3 [Note: some builtin operators and
function calls yield lvalues.
[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 function int& f(); yields
an lvalue, so the call f() is an
lvalue expression. ]
[Note: some builin operators expect lvalue operands. [Example: builtin
assignment operators all expect their
left hand operands to be lvalues. ]
Other builtin operators yield rvalues,
and some expect them. [Example: the
unary and binary + operators expect
rvalue arguments and yield rvalue
results. ] The discussion of each
builtin operator in clause 5 indicates
whether it expects lvalue operands and
whether it yieldsan lvalue. ]
5 The result of calling a function
that does not return a reference is an
rvalue. User defined operators are
functions, and whether such operators
expect or yield lvalues is determined
by their parameter and return types.
6 An expression which holds a
temporary object resulting from a cast
to a nonreference type is an rvalue
(this includes the explicit creation
of an object using functional notation
(5.2.3)).
7 Whenever an lvalue appears in a context where an rvalue is expected,
the lvalue is converted to an rvalue;
see 4.1, 4.2, and 4.3.
8 The discussion of reference
initialization in 8.5.3 and of
temporaries in 12.2 indicates the
behavior of lvalues and rvalues in
other significant contexts.
9 Class rvalues can have cvqualified
types; nonclass rvalues always have
cvunqualified types. Rvalues shall
always have complete types or the void
type; in addition to these types,
lvalues can also have incomplete
types.
10 An lvalue for an object is
necessary in order to modify the
object except that an rvalue of class
type can also be used to modify its
referent under certain circumstances.
[Example: a member function called for
an object (9.3) can modify the object.
]
11 Functions cannot be modified, but
pointers to functions can be
modifiable.
12 A pointer to an incomplete type can
be modifiable. At some point in the
program when the pointed to type is
complete, the object at which the
pointer points can also be modified.
13 The referent of a constqualified
expression shall not be modified
(through that expression), except that
if it is of class type and has a
mutable component, that component can
be modified (7.1.5.1).
14 If an expression can be used to
modify the object to which it refers,
the expression is called modifiable. A
program that attempts to modify an
object through a nonmodifiable lvalue
or rvalue expression is illformed.
15 If a program attempts to access the
stored value of an object through an
lvalue of other than one of the
following types the behavior is
undefined48): — the dynamic type of
the object, — a cvqualified version of
the dynamic type of the object, — a
type that is the signed or unsigned
type corresponding to the dynamic type
of the object, — a type that is the
signed or unsigned type corresponding
to a cvqualified version of the
dynamic type of the object, — an
aggregate or union type that includes
one of the aforementioned types among
its members (including, recursively, a
member of a subaggregate or contained
union), — a type that is a (possibly
cvqualified) base class type of the
dynamic type of the object, — a char
or unsigned char type.

Related

Is a temporary struct an r-value or an x-value?

I wanted a clarification regarding C++ value categories.
struct Foo {...};
void do_something(Foo{});
Is the Foo{} above a r-value or an x-value?
I understand that there is a hierarchy of value categories, and that r-values are actually either an x-value or a pr-value. I also know that the standard says that "temporary materialization is an x-value" but I wasn't sure if the creation of a temporary fits under this definition.
But what I wasn't sure about was whether gl-value and r-value were "abstract" categories in the hierarchy, with the leafs (l-value, x-value, and pr-value) being the actual implementations.
Could someone explain this for me?
From https://eel.is/c++draft/basic.lval (accessed 04/02/2021):
Every expression belongs to exactly one of the fundamental
classifications in this taxonomy: lvalue, xvalue, or prvalue. This
property of an expression is called its value category.
This answers your question of whether gl-value and r-value are categories of values: they are.
On what kind of value your particular case is, let's look at xvalue:
An xvalue is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).
[ ... snip ... ]
# [Note 3: An expression is an xvalue if it is:
(4.1) the result of calling a function, whether implicitly or explicitly, whose return
type is an rvalue reference to object type ([expr.call]),
(4.2) a cast to an rvalue reference to object type ([expr.type.conv],
[expr.dynamic.cast], [expr.static.cast] [expr.reinterpret.cast],
[expr.const.cast], [expr.cast]),
(4.3) a subscripting operation with
an xvalue array operand ([expr.sub]),
(4.4) a class member access
expression designating a non-static data member of non-reference type
in which the object expression is an xvalue ([expr.ref]), or
(4.5) a
.* pointer-to-member expression in which the first operand is an
xvalue and the second operand is a pointer to data member
([expr.mptr.oper]).
Your case does not appear to fit any of those. Now let's look at prvalue:
A prvalue is an expression whose evaluation initializes an object or computes the value of an operand of an operator, as specified by the context in which it appears, or an expression that has type cv void.
Your case appears to be initialising an object. For this reason, I would say it's a prvalue.

Why do lvalue-to-rvalue conversions exist? Why are they required? [duplicate]

I see the term "lvalue-to-rvalue conversion" used in many places throughout the C++ standard. This kind of conversion is often done implicitly, as far as I can tell.
One unexpected (to me) feature of the phrasing from the standard is that they decide to treat lvalue-to-rvalue as a conversion. What if they had said that a glvalue is always acceptable instead of a prvalue. Would that phrase actually have a different meaning? For example, we read that lvalues and xvalues are examples of glvalues. We don't read that lvalues and xvalues are convertible to glvalues. Is there a difference in meaning?
Before my first encounter with this terminology, I used to model lvalues and rvalues mentally more or less as follows: "lvalues are always able to act as rvalues, but in addition can appear on the left side of an =, and to the right of an &".
This, to me, is the intuitive behavior that if I have a variable name, then I can put that name everywhere where I would have put a literal. This model seems consistent with lvalue-to-rvalue implicit conversions terminology used in the standard, as long as this implicit conversion is guaranteed to happen.
But, because they use this terminology, I started wondering whether the implicit lvalue-to-rvalue conversion may fail to happen in some cases. That is, maybe my mental model is wrong here. Here is a relevant part of the standard: (thanks to the commenters).
Whenever a glvalue appears in a context where a prvalue is expected, the glvalue is converted to a prvalue; see 4.1, 4.2, and 4.3. [Note: An attempt to bind an rvalue reference to an lvalue is not such a context; see 8.5.3 .—end note]
I understand what they describe in the note is the following:
int x = 1;
int && y = x; //in this declaration context, x won't bind to y.
// but the literal 1 would have bound, so this is one context where the implicit
// lvalue to rvalue conversion did not happen.
// The expression on right is an lvalue. if it had been a prvalue, it would have bound.
// Therefore, the lvalue to prvalue conversion did not happen (which is good).
So, my question is (are):
1) Could someone clarify the contexts where this conversion can happen implicitly? Specifically, other than the context of binding to an rvalue reference, are there any other where lvalue-to-rvalue conversions fail to happen implicitly?
2) Also, the parenthetical [Note:...] in the clause makes it seem that we could have figured it out from the sentence before. Which part of the standard would that be?
3) Does that mean that rvalue-reference binding is not a context where we expect a prvalue expression (on the right)?
4) Like other conversions, does the glvalue-to-prvalue conversion involve work at runtime that would allow me to observe it?
My aim here is not to ask if it is desirable to allow such a conversion. I'm trying to learn to explain to myself the behavior of this code using the standard as starting point.
A good answer would go through the quote I placed above and explain (based on parsing the text) whether the note in it is also implicit from its text. It would then maybe add any other quotes that let me know the other contexts in which this conversion may fail to happen implicitly, or explain there are no more such contexts. Perhaps a general discussion of why glvalue to prvalue is considered a conversion.
I think the lvalue-to-rvalue conversion is more than just use an lvalue where an rvalue is required. It can create a copy of a class, and always yields a value, not an object.
I'm using n3485 for "C++11" and n1256 for "C99".
Objects and values
The most concise description is in C99/3.14:
object
region of data storage in the execution environment, the contents of which can represent
values
There's also a bit in C++11/[intro.object]/1
Some objects are polymorphic; the implementation generates information associated with
each such object that makes it possible to determine that object’s type during program execution. For other objects, the interpretation of the values found therein is determined by the type of the expressions used to access them.
So an object contains a value (can contain).
Value categories
Despite its name, value categories classify expressions, not values. lvalue-expressions even cannot be considered values.
The full taxonomy / categorization can be found in [basic.lval]; here's a StackOverflow discussion.
Here are the parts about objects:
An lvalue ([...]) designates a function or an object. [...]
An xvalue (an “eXpiring” value) also refers to an object [...]
A glvalue (“generalized” lvalue) is an lvalue or an xvalue.
An rvalue ([...]) is an xvalue, a temporary object or subobject thereof, or a value that is not associated with an object.
A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [...]
Note the phrase "a value that is not associated with an object". Also note that as xvalue-expressions refer to objects, true values must always occur as prvalue-expressions.
The lvalue-to-rvalue conversion
As footnote 53 indicates, it should now be called "glvalue-to-prvalue conversion". First, here's the quote:
1 A glvalue of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed. If the object to which the glvalue refers is not an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program
that necessitates this conversion has undefined behavior. If T is a non-class type, the type of the prvalue is the cv-unqualified version of T. Otherwise, the type of the prvalue is T.
This first paragraph specifies the requirements and the resulting type of the conversion. It isn't yet concerned with the effects of the conversion (other than Undefined Behaviour).
2 When an lvalue-to-rvalue conversion occurs in an unevaluated operand or a subexpression thereof the value contained in the referenced object is not accessed. Otherwise, if the glvalue has a class type, the conversion copy-initializes a temporary of type T from the glvalue and the result of the conversion is a prvalue for the temporary. Otherwise, if the glvalue has (possibly cv-qualified) type std::nullptr_t, the
prvalue result is a null pointer constant. Otherwise, the value contained in the object indicated by the glvalue is the prvalue result.
I'd argue that you'll see the lvalue-to-rvalue conversion most often applied to non-class types. For example,
struct my_class { int m; };
my_class x{42};
my_class y{0};
x = y;
The expression x = y does not apply the lvalue-to-rvalue conversion to y (that would create a temporary my_class, by the way). The reason is that x = y is interpreted as x.operator=(y), which takes y per default by reference, not by value (for reference binding, see below; it cannot bind an rvalue, as that would be a temporary object different from y). However, the default definition of my_class::operator= does apply the lvalue-to-rvalue conversion to x.m.
Therefore, the most important part to me seems to be
Otherwise, the value contained in the object indicated by the glvalue is the prvalue result.
So typically, an lvalue-to-rvalue conversion will just read the value from an object. It isn't just a no-op conversion between value (expression) categories; it can even create a temporary by calling a copy constructor. And the lvalue-to-rvalue conversion always returns a prvalue value, not a (temporary) object.
Note that the lvalue-to-rvalue conversion is not the only conversion that converts an lvalue to a prvalue: There's also the array-to-pointer conversion and the function-to-pointer conversion.
values and expressions
Most expressions don't yield objects[[citation needed]]. However, an id-expression can be an identifier, which denotes an entity. An object is an entity, so there are expressions which yield objects:
int x;
x = 5;
The left hand side of the assignment-expression x = 5 also needs to be an expression. x here is an id-expression, because x is an identifier. The result of this id-expression is the object denoted by x.
Expressions apply implicit conversions: [expr]/9
Whenever a glvalue expression appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue, array-to-pointer, or function-to-pointer standard conversions are applied to convert the expression to a prvalue.
And /10 about usual arithmetic conversions as well as /3 about user-defined conversions.
I'd love now to quote an operator that "expects a prvalue for that operand", but cannot find any but casts. For example, [expr.dynamic.cast]/2 "If T is a pointer type, v [the operand] shall be a prvalue of a pointer to complete class type".
The usual arithmetic conversions required by many arithmetic operators do invoke an lvalue-to-rvalue conversion indirectly via the standard conversion used. All standard conversions but the three that convert from lvalues to rvalues expect prvalues.
The simple assignment however doesn't invoke the usual arithmetic conversions. It is defined in [expr.ass]/2 as:
In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.
So although it doesn't explicitly require a prvalue expression on the right hand side, it does require a value. It is not clear to me if this strictly requires the lvalue-to-rvalue conversion. There's an argument that accessing the value of an uninitialized variable should always invoke undefined behaviour (also see CWG 616), no matter if it's by assigning its value to an object or by adding its value to another value. But this undefined behaviour is only required for an lvalue-to-rvalue conversion (AFAIK), which then should be the only way to access the value stored in an object.
If this more conceptual view is valid, that we need the lvalue-to-rvalue conversion to access the value inside an object, then it'd be much easier to understand where it is (and needs to be) applied.
Initialization
As with simple assignment, there's a discussion whether or not the lvalue-to-rvalue conversion is required to initialize another object:
int x = 42; // initializer is a non-string literal -> prvalue
int y = x; // initializer is an object / lvalue
For fundamental types, [dcl.init]/17 last bullet point says:
Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. Standard conversions will be used, if necessary, to convert the initializer expression to the cv-unqualified version of the destination type; no user-defined conversions are considered. If the conversion cannot be done, the initialization is ill-formed.
However, it also mentioned the value of the initializer expression. Similar to the simple-assignment-expression, we can take this as an indirect invocation of the lvalue-to-rvalue conversion.
Reference binding
If we see lvalue-to-rvalue conversion as a way to access the value of an object (plus the creation of a temporary for class type operands), we understand that it's not applied generally for binding to a reference: A reference is an lvalue, it always refers to an object. So if we bound values to references, we'd need to create temporary objects holding those values. And this is indeed the case if the initializer-expression of a reference is a prvalue (which is a value or a temporary object):
int const& lr = 42; // create a temporary object, bind it to `r`
int&& rv = 42; // same
Binding a prvalue to an lvalue reference is prohibited, but prvalues of class types with conversion functions that yield lvalue references may be bound to lvalue references of the converted type.
The complete description of reference binding in [dcl.init.ref] is rather long and rather off-topic. I think the essence of it relating to this question is that references refer to objects, therefore no glvalue-to-prvalue (object-to-value) conversion.
On glvalues: A glvalue ("generalized" lvalue) is an expression that is either an lvalue or an xvalue.
A glvalue may be implicitly converted to prvalue with lvalue-to-rvalue, array-to-pointer, or function-to-pointer implicit conversion.
Lvalue transformations are applied when lvalue argument (e.g. reference to an object) is used in context where rvalue (e.g. a number) is expected.
Lvalue to rvalue conversion
A glvalue of any non-function, non-array type T can be implicitly converted to prvalue of the same type. If T is a non-class type, this conversion also removes cv-qualifiers. Unless encountered in unevaluated context (in an operand of sizeof, typeid, noexcept, or decltype), this conversion effectively copy-constructs a temporary object of type T using the original glvalue as the constructor argument, and that temporary object is returned as a prvalue. If the glvalue has the type std::nullptr_t, the resulting prvalue is the null pointer constant nullptr.

Is an element of an rvalue array (the element is obtained using subscript expression) an rvalue? [duplicate]

struct S{
int a[3] = {1,2,3};
};
S&& f(){return S();}
&f().a; //[Error] taking address of xvalue (rvalue reference)
&f().a[0]; //ok in GCC 5.1.0 and Clang 3.6.0
S s;
&static_cast<S&&>(s).a; //[Error] taking address of xvalue (rvalue reference)
&static_cast<S&&>(s).a[0]; //ok in GCC 5.1.0 and Clang 3.6.0
5.7 An expression is an xvalue if it is:
(7.1) — the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type,
(7.2) — a cast to an rvalue reference to object type,
(7.3) — a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue, or
(7.4) — a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member.
5.2.1 Subscripting
A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions
shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration
or integral type. The result is of type “T”. The type “T” shall be a completely-defined object type. The expression E1[E2] is identical (by definition) to *((E1)+(E2))<<*t [ Note: see 5.3 and 5.7 for details of * and
+ and 8.3.4 for details of arrays. —end note ], except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.
So, is f().a[0] an xvalue?
I think f().a[0] should be an xvalue.
[Edit1]
Ignoring &f().a; and &f().a[0]; because 12.2[class.temporary]p5.2
The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not
extended; the temporary is destroyed at the end of the full-expression in the return statement
static_cast<S&&>(s).a is an xvalue(7.2 and 7.3).
" except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise."
So I think static_cast<S&&>(s).a[0] should be an xvalue, but
&static_cast<S&&>(s).a[0]; //ok in GCC 5.1.0 and Clang 3.6.0
Questing:
Am I wrong? If I am wrong, show me an example that subscripting an array results an xvalue.
As far as I can tell you are indeed correct, this looks a "bug", although to be fair this changed recently with CWG defect 1213 which says:
Because the subscripting operation is defined as indirection through a pointer value, the result of a subscript operator applied to an xvalue array is an lvalue, not an xvalue. This could be surprising to some.
and this changed section 5.2.1 [expr.sub] as follows:
A postfix expression followed by an expression in square brackets is a
postfix expression. One of the expressions shall have the type
“array of T” or “pointer to T” and the other shall have unscoped enumeration or integral type. The result is an lvalue of type
“T.” The type “T” shall be a completely-defined object type.62 The
expression E1[E2] is identical (by definition) to *((E1)+(E2)) [Note:
see 5.3 [expr.unary] and 5.7 [expr.add] for details of * and + and
8.3.4 [dcl.array] for details of arrays. —end note], except that in the case of an array operand, the result is an lvalue if that operand
is an lvalue and an xvalue otherwise.
So indeed the result of f().a[0]; and static_cast<S&&>(s).a[0] should be xvalues.
This defect did not have a proposed resolution until December 2012 and clangs defect report support lists the support of that defect report as unknown so most likely the implementers have not gotten to fixing this defect yet.
Update
Filed a clang bug report: Subscript operator applied to an temporary array results in an lvalue.
I could test in Clang 3.4.1 std=c++11.
Here are my conclusions :
int i = f().a[0] would be correct : you get a reference to a temporary struct, the lifetime of the temporary is extended for the duration of the reference, you take a value : fine.
int *i = &f().a[0] is accepted by the compiler. However, the warning on f saying that you are returning reference to local temporary object makes sense here. The lifetime of the temporary object is extended for the duration of the reference : here the time to copy the address. As soon as you have taken the address of a, the containing object vanishes and you only have a dangling reference.
int *i = f().a is exactly same case as previous one.
But when you do &f().a, you are taking the address of an rvalue of type 'int [3]', and it does not make sense to take such an address : you can only take its value.
Let's go one step further :
S s = f(); is correct. You get a reference to a temporary struct, the lifetime of the temporary is extended for the duration of the reference, you take a value : fine.
Now &s.a[0] is a well defined pointer to int, as is int *ix2 = &static_cast<S&&>(s).a[0];
You can even write : int (*ix3)[3] = &s.a; to take the address of an array to 3 int, but still for same reason, you cannot write &static_cast<S&&>(s).a because you would take the address of an rvalue of type 'int [3]'
TL/DR
With S s = f(); s.a is a well defined rvalue, s.a[0] is a well defined lvalue (you can write s.a[0] = 5;).
f().s is a rvalue, but using it will invoke UB, because it ends in a reference to a temporary object that will be destroyed before you can use it.
f().s[0] can be used as a well defined rvalue. You can use it as a lvalue, but for the same reason as above, it would invoke UB.

lvalue to rvalue implicit conversion

I see the term "lvalue-to-rvalue conversion" used in many places throughout the C++ standard. This kind of conversion is often done implicitly, as far as I can tell.
One unexpected (to me) feature of the phrasing from the standard is that they decide to treat lvalue-to-rvalue as a conversion. What if they had said that a glvalue is always acceptable instead of a prvalue. Would that phrase actually have a different meaning? For example, we read that lvalues and xvalues are examples of glvalues. We don't read that lvalues and xvalues are convertible to glvalues. Is there a difference in meaning?
Before my first encounter with this terminology, I used to model lvalues and rvalues mentally more or less as follows: "lvalues are always able to act as rvalues, but in addition can appear on the left side of an =, and to the right of an &".
This, to me, is the intuitive behavior that if I have a variable name, then I can put that name everywhere where I would have put a literal. This model seems consistent with lvalue-to-rvalue implicit conversions terminology used in the standard, as long as this implicit conversion is guaranteed to happen.
But, because they use this terminology, I started wondering whether the implicit lvalue-to-rvalue conversion may fail to happen in some cases. That is, maybe my mental model is wrong here. Here is a relevant part of the standard: (thanks to the commenters).
Whenever a glvalue appears in a context where a prvalue is expected, the glvalue is converted to a prvalue; see 4.1, 4.2, and 4.3. [Note: An attempt to bind an rvalue reference to an lvalue is not such a context; see 8.5.3 .—end note]
I understand what they describe in the note is the following:
int x = 1;
int && y = x; //in this declaration context, x won't bind to y.
// but the literal 1 would have bound, so this is one context where the implicit
// lvalue to rvalue conversion did not happen.
// The expression on right is an lvalue. if it had been a prvalue, it would have bound.
// Therefore, the lvalue to prvalue conversion did not happen (which is good).
So, my question is (are):
1) Could someone clarify the contexts where this conversion can happen implicitly? Specifically, other than the context of binding to an rvalue reference, are there any other where lvalue-to-rvalue conversions fail to happen implicitly?
2) Also, the parenthetical [Note:...] in the clause makes it seem that we could have figured it out from the sentence before. Which part of the standard would that be?
3) Does that mean that rvalue-reference binding is not a context where we expect a prvalue expression (on the right)?
4) Like other conversions, does the glvalue-to-prvalue conversion involve work at runtime that would allow me to observe it?
My aim here is not to ask if it is desirable to allow such a conversion. I'm trying to learn to explain to myself the behavior of this code using the standard as starting point.
A good answer would go through the quote I placed above and explain (based on parsing the text) whether the note in it is also implicit from its text. It would then maybe add any other quotes that let me know the other contexts in which this conversion may fail to happen implicitly, or explain there are no more such contexts. Perhaps a general discussion of why glvalue to prvalue is considered a conversion.
I think the lvalue-to-rvalue conversion is more than just use an lvalue where an rvalue is required. It can create a copy of a class, and always yields a value, not an object.
I'm using n3485 for "C++11" and n1256 for "C99".
Objects and values
The most concise description is in C99/3.14:
object
region of data storage in the execution environment, the contents of which can represent
values
There's also a bit in C++11/[intro.object]/1
Some objects are polymorphic; the implementation generates information associated with
each such object that makes it possible to determine that object’s type during program execution. For other objects, the interpretation of the values found therein is determined by the type of the expressions used to access them.
So an object contains a value (can contain).
Value categories
Despite its name, value categories classify expressions, not values. lvalue-expressions even cannot be considered values.
The full taxonomy / categorization can be found in [basic.lval]; here's a StackOverflow discussion.
Here are the parts about objects:
An lvalue ([...]) designates a function or an object. [...]
An xvalue (an “eXpiring” value) also refers to an object [...]
A glvalue (“generalized” lvalue) is an lvalue or an xvalue.
An rvalue ([...]) is an xvalue, a temporary object or subobject thereof, or a value that is not associated with an object.
A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [...]
Note the phrase "a value that is not associated with an object". Also note that as xvalue-expressions refer to objects, true values must always occur as prvalue-expressions.
The lvalue-to-rvalue conversion
As footnote 53 indicates, it should now be called "glvalue-to-prvalue conversion". First, here's the quote:
1 A glvalue of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed. If the object to which the glvalue refers is not an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program
that necessitates this conversion has undefined behavior. If T is a non-class type, the type of the prvalue is the cv-unqualified version of T. Otherwise, the type of the prvalue is T.
This first paragraph specifies the requirements and the resulting type of the conversion. It isn't yet concerned with the effects of the conversion (other than Undefined Behaviour).
2 When an lvalue-to-rvalue conversion occurs in an unevaluated operand or a subexpression thereof the value contained in the referenced object is not accessed. Otherwise, if the glvalue has a class type, the conversion copy-initializes a temporary of type T from the glvalue and the result of the conversion is a prvalue for the temporary. Otherwise, if the glvalue has (possibly cv-qualified) type std::nullptr_t, the
prvalue result is a null pointer constant. Otherwise, the value contained in the object indicated by the glvalue is the prvalue result.
I'd argue that you'll see the lvalue-to-rvalue conversion most often applied to non-class types. For example,
struct my_class { int m; };
my_class x{42};
my_class y{0};
x = y;
The expression x = y does not apply the lvalue-to-rvalue conversion to y (that would create a temporary my_class, by the way). The reason is that x = y is interpreted as x.operator=(y), which takes y per default by reference, not by value (for reference binding, see below; it cannot bind an rvalue, as that would be a temporary object different from y). However, the default definition of my_class::operator= does apply the lvalue-to-rvalue conversion to x.m.
Therefore, the most important part to me seems to be
Otherwise, the value contained in the object indicated by the glvalue is the prvalue result.
So typically, an lvalue-to-rvalue conversion will just read the value from an object. It isn't just a no-op conversion between value (expression) categories; it can even create a temporary by calling a copy constructor. And the lvalue-to-rvalue conversion always returns a prvalue value, not a (temporary) object.
Note that the lvalue-to-rvalue conversion is not the only conversion that converts an lvalue to a prvalue: There's also the array-to-pointer conversion and the function-to-pointer conversion.
values and expressions
Most expressions don't yield objects[[citation needed]]. However, an id-expression can be an identifier, which denotes an entity. An object is an entity, so there are expressions which yield objects:
int x;
x = 5;
The left hand side of the assignment-expression x = 5 also needs to be an expression. x here is an id-expression, because x is an identifier. The result of this id-expression is the object denoted by x.
Expressions apply implicit conversions: [expr]/9
Whenever a glvalue expression appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue, array-to-pointer, or function-to-pointer standard conversions are applied to convert the expression to a prvalue.
And /10 about usual arithmetic conversions as well as /3 about user-defined conversions.
I'd love now to quote an operator that "expects a prvalue for that operand", but cannot find any but casts. For example, [expr.dynamic.cast]/2 "If T is a pointer type, v [the operand] shall be a prvalue of a pointer to complete class type".
The usual arithmetic conversions required by many arithmetic operators do invoke an lvalue-to-rvalue conversion indirectly via the standard conversion used. All standard conversions but the three that convert from lvalues to rvalues expect prvalues.
The simple assignment however doesn't invoke the usual arithmetic conversions. It is defined in [expr.ass]/2 as:
In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.
So although it doesn't explicitly require a prvalue expression on the right hand side, it does require a value. It is not clear to me if this strictly requires the lvalue-to-rvalue conversion. There's an argument that accessing the value of an uninitialized variable should always invoke undefined behaviour (also see CWG 616), no matter if it's by assigning its value to an object or by adding its value to another value. But this undefined behaviour is only required for an lvalue-to-rvalue conversion (AFAIK), which then should be the only way to access the value stored in an object.
If this more conceptual view is valid, that we need the lvalue-to-rvalue conversion to access the value inside an object, then it'd be much easier to understand where it is (and needs to be) applied.
Initialization
As with simple assignment, there's a discussion whether or not the lvalue-to-rvalue conversion is required to initialize another object:
int x = 42; // initializer is a non-string literal -> prvalue
int y = x; // initializer is an object / lvalue
For fundamental types, [dcl.init]/17 last bullet point says:
Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. Standard conversions will be used, if necessary, to convert the initializer expression to the cv-unqualified version of the destination type; no user-defined conversions are considered. If the conversion cannot be done, the initialization is ill-formed.
However, it also mentioned the value of the initializer expression. Similar to the simple-assignment-expression, we can take this as an indirect invocation of the lvalue-to-rvalue conversion.
Reference binding
If we see lvalue-to-rvalue conversion as a way to access the value of an object (plus the creation of a temporary for class type operands), we understand that it's not applied generally for binding to a reference: A reference is an lvalue, it always refers to an object. So if we bound values to references, we'd need to create temporary objects holding those values. And this is indeed the case if the initializer-expression of a reference is a prvalue (which is a value or a temporary object):
int const& lr = 42; // create a temporary object, bind it to `r`
int&& rv = 42; // same
Binding a prvalue to an lvalue reference is prohibited, but prvalues of class types with conversion functions that yield lvalue references may be bound to lvalue references of the converted type.
The complete description of reference binding in [dcl.init.ref] is rather long and rather off-topic. I think the essence of it relating to this question is that references refer to objects, therefore no glvalue-to-prvalue (object-to-value) conversion.
On glvalues: A glvalue ("generalized" lvalue) is an expression that is either an lvalue or an xvalue.
A glvalue may be implicitly converted to prvalue with lvalue-to-rvalue, array-to-pointer, or function-to-pointer implicit conversion.
Lvalue transformations are applied when lvalue argument (e.g. reference to an object) is used in context where rvalue (e.g. a number) is expected.
Lvalue to rvalue conversion
A glvalue of any non-function, non-array type T can be implicitly converted to prvalue of the same type. If T is a non-class type, this conversion also removes cv-qualifiers. Unless encountered in unevaluated context (in an operand of sizeof, typeid, noexcept, or decltype), this conversion effectively copy-constructs a temporary object of type T using the original glvalue as the constructor argument, and that temporary object is returned as a prvalue. If the glvalue has the type std::nullptr_t, the resulting prvalue is the null pointer constant nullptr.

What expressions create xvalues?

I'm trying to understand the C++11 concepts.
The standard draft which I have says:
An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its
resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving
rvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvalue
reference is an xvalue. —end example ]
OK, so what exactly are the "certain kinds of expressions" that produce xvalues? This part of the spec does not detail a list of these expressions.
I understand lvalue and prvalue (at least I think, I understand).
There is a helpful non-normative note in the introduction to §5 (C++11 §5[expr]/6):
[ Note: An expression is an xvalue if it is:
the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type,
a cast to an rvalue reference to object type,
a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue, or
a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member.
In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues; rvalue references to functions are treated as lvalues whether named or not. —end note ]
Searching through the rest of §5, this list appears exhaustive. The list is followed by an example:
struct A {
int m;
};
A&& operator+(A, A);
A&& f();
A a;
A&& ar = static_cast<A&&>(a);
The expressions f(), f().m, static_cast<A&&>(a), and a + a are xvalues. The expression ar is an lvalue.
There are two common ways to get an xvalue expression:
Use std::move to move an object. std::move performs a static_cast to an rvalue reference type and returns the rvalue reference.
Use std::forward to forward an rvalue. std::forward is typically used in a function template to enable perfect forwarding of a function argument.
If the argument provided to the function template was an rvalue, the parameter type will be an rvalue reference, which is an lvalue. In this case, std::forward performs a static_cast to an rvalue reference type and returns the rvalue reference.
(Note: If the argument provided to the function template was an lvalue, the parameter type will be an lvalue reference and std::forward will return an lvalue reference.)
Clause 5, which describes the syntax of valid expressions, lists for each expression syntax the conditions in which the expression is an lvalue, an xvalue, or a prvalue. The complete list of possible xvalues from clause 5 is:
5.2.2 paragraph 10: A function call is ... an xvalue if the result type is an rvalue reference to object type.
(In the technical language of the Standard, "object type" doesn't mean the same as "class type". "Object type" includes fundamental types, pointers, and arrays, and excludes only function types. An rvalue reference to function type is always treated as an lvalue, not xvalue.)
The most notable functions which return an rvalue reference are of course std::move and sometimes std::forward.
5.2.5 paragraph 4: If E2 is a non-static data member ... if E1 is an xvalue, then E1.E2 is an xvalue
(On the other hand, a data member lookup E1->E2 is always an lvalue.)
Similarly, if E1 is an xvalue, then the data member lookup E1.*E2 is an xvalue:
5.5 paragraph 6: The result of a .* expression whose second operand is a pointer to a data member is of the same value category (3.10) as its first operand.
For the various types of casts:
dynamic_cast<Type>(expr): 5.2.7 paragraph 2
static_cast<Type>(expr): 5.2.9 paragraph 1
reinterpret_cast<Type>(expr): 5.2.10 paragraph 1
const_cast<Type>(expr): 5.2.11 paragraph 1
(Type) expr: 5.4 paragraph 1
the expression is an xvalue if and only if Type is an rvalue reference to object type. The same is also true for Type(expr), since
5.2.3 paragraph 1: If the expression list [in parentheses following a type name] is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4).
(On the other hand, Type{expr} is always a prvalue.)
Section 5.16 on the conditional operator ends up saying that A ? B : C can sometimes be an xvalue if B and/or C is an xvalue. But the complete rules are difficult to summarize.
If an expression ends up calling a user-defined overloaded operator function, then section 5.2.2 applies to that expression, not the one that describes the built-in operator's behavior. (See the expression a + a in the example #James posted.)
As you mentioned,
An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example).
Focus: object, be moved, end lifetime
Here is an example:
void move_test(){
std::string s = "I'm here!";
std::string m = std::move(s); // move from <s> to <m>
// s is now in an undefined, but valid state;
std::cout << "s=" << s << "; &s=" << &s << std::endl;
}
By moving, we can convert a named value (an lvalue,here is s) to being an rvalue(that is std::move(s)). More specifically, since it can’t be a prvalue (it has a name! In other words, it has an identity), it ends up being an xvalue.
xvalue always serves C++ move semantics.
What I gather from what I've read is that calling something an xvalue is a fancy way of saying:
An xvalue is just an rvalue whose storage may have been deallocated, so using it means you have to verify its existence by yourself.
Generally, it's one or more levels of indirection away from an actual rvalue.
By contrast, an rvalue is guaranteed to have its storage space existing as long as it is in scope.
I may be wrong but this is what I've understood.