Summary:
Section 3.10 [basic.lval] promises that "the discussion of each built-in
operator in Clause 5 indicates [...] the value categories of the operands it
expects." However, many of the value categories of operands are left
unspecified, leaving us to infer that they are prvalues from non-normative
notes and suggestions. Whether an operator expects a prvalue operand is
important in determining whether lvalue-to-rvalue conversion occurs.
Prior Discussion:
Details:
Both Sections 3.10 [basic.lval] and 5 [expr] discuss the value categories of
operands of built-in operators. In a Note in 3.10/1 [basic.lval], it is said:
The discussion of each built-in operator in Clause 5 indicates the category
of the value it yields and the value categories of the operands it expects.
For example, the built-in assignment operators expect that the left operand
is an lvalue and that the right operand is a prvalue and yield an lvalue as
the result.
This tells us two things: we should expect the the value categories of built-in
operands to be specified in Section 5 [expr] and that the built-in assignment
operators expect their right operand to be a prvalue expression. However, this
a note and therefore non-normative.
We are also told in 3.10/2 [basic.lval]:
Whenever a glvalue appears in a context where a prvalue is expected, the
glvalue is converted to a prvalue
That is, when an operator expects a prvalue operand, lvalue-to-rvalue
conversion must occur. This is further backed up in Section 5/8 [expr]:
Whenever a glvalue expression appears as an operand of an operator that
expects a prvalue for that operand, the lvalue-to-rvalue (4.1), array-to-
pointer (4.2), or function-to-pointer (4.3) standard conversions are applied
to convert the expression to a prvalue.
We expect any operators that make use of the value of an operand to require
that operand to be a prvalue expression, because lvalue-to-rvalue
conversion is logically the act of reading the value of an object. However,
only those operands that are required to be glvalues are enumerated in
Section 5 [expr] and many value categories of operands are left unspecified.
One response to this is that these unspecified operands can be expressions
of any value category and should be left unspecified. However, we need to
know if it expects a prvalue to determine if lvalue-to-rvalue conversion
occurs.
As quoted above in Section 3.10/1, the Note says that "the built-in assignment
operators expect [...] that the right operand is a prvalue". This is not
actually specified in Section 5.17 [expr.ass]. Only the left operand being
an lvalue is specified.
Value categories are also left unspecified for the following operators:
indirection [expr.unary.op], multiplicative operators [expr.mul], additive
operators [expr.add], shift operators [expr.shift], relational operators
[expr.rel], equality operators [expr.eq], bitwise and logical operators
[expr.bit.and] [expr.xor] [expr.or] [expr.log.and] [expr.log.or], conditional
operator [expr.cond], assignment operators [expr.ass], and the comma operator
[expr.comma].
It is generally assumed that when the value category is left unspecified, it
should be a prvalue. However, this can only be inferred through non-normative
references and could easily be better specified. It can further be inferred
through the following suggestive quotes. Firstly, Section 5.19/2 [expr.const]:
A conditional-expression is a core constant expression unless it involves one
of the following as a potentially evaluated subexpression [..]
- an lvalue-to-rvalue conversion (4.1) unless it is applied to
- a glvalue of integral or enumeration type that refers to a non-volatile
const object with a preceding initialization, initialized with a
constant expression
- [...]
- [...]
And Section 4/5 [conv] suggests that lvalue-to-rvalue conversion is always
done unless specifically suppressed (by taking an lvalue operand):
[ Note: There are some contexts where certain conversions are suppressed. For
example, the lvalue-to-rvalue conversion is not done on the operand of the
unary & operator. Specific exceptions are given in the descriptions of those
operators and contexts. — end note ]
Further, the Note in Section 3.10/4 [basic.lval] of the C++03 standard
previously stated that "the discussion of each built-in operator in clause 5
indicates whether it expects lvalue operands and whether it yields an lvalue."
This suggests that the lvalue operands are enumerated, but the prvalue
operands are not.
Proposed Solutions:
1. Modify Section 5/8 [expr] to:
When the expected value category of an operand of a built-in
operator is not stated explicitly, the operator expects that
operand to be a prvalue expression. Whenever a glvalue expression
appears as an operand of an operator that expects a prvalue for
that operand, the lvalue-to-rvalue (4.1), array-to-pointer (4.2),
or function-to-pointer (4.3) standard conversions are applied to
convert the expression to a prvalue.
2. Explicitly provide the value categories of all operators described in
the subsections of Section 5 [expr].