Requirements of value category on operands of some built-in operators

157 views
Skip to first unread message

ai.a...@gmail.com

unread,
Jan 22, 2013, 2:03:40 AM1/22/13
to std-dis...@isocpp.org
Maybe I am missing something, but I cannot find any clear wording about requirements of value category on operands of some built-in operators.

I believe that the following built-in operators expect a prvalue for their operands; unary operators except for the address-of operator, multiplicative operators, additive operators, shift operators, relational operators, equality operators, bitwise operators, logical operators, the first operand of conditional operator and the right operand of assignment operators. However, I cannot find (or even infer from a combination of wording) the requirements of value category on operands of these built-in operators.

Therefore, I would like to ask experts where the corresponding wording is. Or, does the standard intentionally leave such requirements unspecified?

wolfei...@gmail.com

unread,
Jan 22, 2013, 7:05:27 AM1/22/13
to std-dis...@isocpp.org, ai.a...@gmail.com
They do not have value category requirements- any expression of the correct type is suitable.

ai.a...@gmail.com

unread,
Jan 22, 2013, 8:03:49 AM1/22/13
to std-dis...@isocpp.org, ai.a...@gmail.com, wolfei...@gmail.com
2013年1月22日火曜日 21時05分27秒 UTC+9 wolfei...@gmail.com:

They do not have value category requirements- any expression of the correct type is suitable.

Really? I think that value category requirements are important because they are significant in determining whether or not lvalue-to-rvalue conversion is applied to those operands, and which in turn is significant in determining whether or not uninitialized glvalues can be used for those operands, or variables appearing in those operands are odr-used.

wolfei...@gmail.com

unread,
Jan 22, 2013, 7:20:22 PM1/22/13
to std-dis...@isocpp.org, ai.a...@gmail.com, wolfei...@gmail.com
If it is not a primitive operator that cannot be used on an rvalue, then lvalue-to-rvalue conversion is used to convert it to an rvalue, I think. But I do know that all primitive operators can operate on lvalues, and all of the ones listed operate on both.

ai.a...@gmail.com

unread,
Jan 22, 2013, 10:34:18 PM1/22/13
to std-dis...@isocpp.org, ai.a...@gmail.com, wolfei...@gmail.com
2013年1月23日水曜日 9時20分22秒 UTC+9 wolfei...@gmail.com:

If it is not a primitive operator that cannot be used on an rvalue, then lvalue-to-rvalue conversion is used to convert it to an rvalue, I think. But I do know that all primitive operators can operate on lvalues, and all of the ones listed operate on both.

I understand that all of the operands of built-in operators I listed can accept an expression with any value category (prvalue, xvalue, lvalue). Even if a built-in operator expects a prvalue for its operand, a glvalue can be used for that operand because lvalue-to-rvalue conversion is implicitly applied.

However, whether a prvalue is expected for an operand is the important point because it determines that lvalue-to-rvalue conversion is applied to a glvalue operand.

Do you mean that lvalue-to-rvalue conversion is not performed on glvalue operands in the cases I listed above? In other words, for example,

long i;
i + 0l; // do you mean that lvalue-to-rvalue conversion is not performed on the left operand?

wolfei...@gmail.com

unread,
Jan 23, 2013, 5:38:14 AM1/23/13
to std-dis...@isocpp.org, ai.a...@gmail.com, wolfei...@gmail.com
Perhaps I just don't understand your question.

Primitive operators (the ones under discussion) can transparently act on any expression of correct type. Strictly, they do this by lvalue-to-rvalue conversion for lvalue operands. If you understand this, then what's the question?

ai.a...@gmail.com

unread,
Jan 24, 2013, 12:03:34 AM1/24/13
to std-dis...@isocpp.org, ai.a...@gmail.com, wolfei...@gmail.com
2013年1月23日水曜日 19時38分14秒 UTC+9 wolfei...@gmail.com:

Perhaps I just don't understand your question.

Primitive operators (the ones under discussion) can transparently act on any expression of correct type. Strictly, they do this by lvalue-to-rvalue conversion for lvalue operands. If you understand this, then what's the question?

Yeah, I should have organized my question better before submitting this post. I'm very sorry for the confusion.

Now, let me correct my question.

My first question is "where is the wording that specifies that the built-in assignment operators expect that the right operand is a prvalue in Chapter 5?"

The note in [basic.lval]/1 says "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..." Therefore, there should be the discussion in Chapter 5 from which I can derive a conclusion that the built-in assignment operators expect that the right operand is a prvalue. However, I cannot find any corresponding wording. Where is it?

My second question is "is there any consistent explanation why the lvalue-to-rvalue conversion is performed on glvalue operands of some built-in operators while not on glvalue operands of other built-in operators?"

For example, consider the following snippet.

short s;
s + 0; // (A)
int i;
i + 0; // (B)

The lvalue-to-rvalue conversion is performed on the left operand in (A). Because the built-in additive operators invoke the usual arithmetic conversion ([expr.add]/1), and the integral promotions are performed on both operands (the 5th bullet of [expr]/9). The integral promotions expect a prvalue ([conv.prom]/1). Therefore, the lvalue-to-rvalue conversion is performed on the left operand in (A) before the integral promotions are performed ([expr]/8).

On the other hand, the lvalue-to-rvalue conversion is not performed on the left operand in (B). Because no wording of the built-in additive operators ([expr.add]), the usual arithmetic conversion ([expr]/9) and the integral promotions ([conv.prom]) says anything about the case of (B).

Where does the difference between (A) and (B) come from?

Kazutoshi Satoda

unread,
Jan 24, 2013, 11:02:52 AM1/24/13
to std-dis...@isocpp.org, ai.a...@gmail.com
ai.a...@gmail.com wrote:
> Maybe I am missing something, but I cannot find any clear wording about
> requirements of value category on operands of some built-in operators.
(snip)
> Therefore, I would like to ask experts where the corresponding wording is.
> Or, does the standard intentionally leave such requirements unspecified?

Here are some relevant words I could find in the current draft N3485 so
far.
3.10 [basic.lval] p1 (in a Note)
> 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.
5 [expr] p9
> 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.

These wordings both imply that there are corresponding wordings about
expected value categories for each operands of operators. But I could
find very little wordings. Here is an example about left operand of
assignment operator.
5.17 [expr.ass] p1
> The assignment operator (=) and the compound assignment operators all
> group right-to-left. All require a modifiable lvalue as their left
> operand and return an lvalue referring to the left operand.
There are some clear wordings about value category of *result* of some
operators, though.

FYI, the C standard is clear on this point.
C (N1570) 6.3.2.1 p2
> Except when it is the operand of the sizeof operator, the _Alignof
> operator, the unary & operator, the ++ operator, the -- operator, or the
> left operand of the . operator or an assignment operator, an lvalue that
> does not have array type is converted to the value stored in the
> designated object (and is no longer an lvalue); this is called lvalue
> conversion.

The lack of clear wordings about expected value categories of operands
for each operator looks like a defect of C++ standard, at least for me.

--
k_satoda

ai.a...@gmail.com

unread,
Jan 24, 2013, 9:35:52 PM1/24/13
to std-dis...@isocpp.org, ai.a...@gmail.com
2013年1月25日金曜日 1時02分52秒 UTC+9 Kazutoshi SATODA:

These wordings both imply that there are corresponding wordings about
expected value categories for each operands of operators. But I could
find very little wordings. Here is an example about left operand of
assignment operator.
5.17 [expr.ass] p1
> The assignment operator (=) and the compound assignment operators all
> group right-to-left. All require a modifiable lvalue as their left
> operand and return an lvalue referring to the left operand.
There are some clear wordings about value category of *result* of some
operators, though.
Agreed.
 
FYI, the C standard is clear on this point.
C (N1570) 6.3.2.1 p2
> Except when it is the operand of the sizeof operator, the _Alignof
> operator, the unary & operator, the ++ operator, the -- operator, or the
> left operand of the . operator or an assignment operator, an lvalue that
> does not have array type is converted to the value stored in the
> designated object (and is no longer an lvalue); this is called lvalue
> conversion.
I understand that lvalue conversion in C roughly corresponds to lvalue-to-rvalue conversion in C++.

Correct me if I misunderstand, but I understand that glvalue is a model of the address (locator value) of an expression, prvalue is a model of the contents of an expression, and lvalue-to-rvalue conversion is roughly equivalent to a fetch of the contents (prvalue) from the address (glvalue). The build-in operators I listed in my original post should require the contents (not address) of the operands to compute their result. This is the reason why I believe that the operands I listed expect a prvalue. Otherwise, the usage of the word "lvalue-to-rvalue conversion" in other parts of the standard may lead to inconsistency.

The lack of clear wordings about expected value categories of operands
for each operator looks like a defect of C++ standard, at least for me.
Me, too. 

Bb Hh

unread,
Jan 24, 2013, 10:58:19 PM1/24/13
to std-dis...@isocpp.org
N3485
4/1 ... A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.
2 [ Note: expressions with a given type will be implicitly converted to other types in several contexts:
— When used as operands of operators. The operator’s requirements for its operands dictate the destination type (Clause 5).
— When used in the condition of an if statement or iteration statement (6.4, 6.5). The destination type is bool.
— When used in the expression of a switch statement. The destination type is integral (6.4).
— When used as the source expression for an initialization (which includes use as an argument in a function call and use as the expression in a return statement). The type of the entity being initialized is (generally) the destination type. See 8.5, 8.5.3.
—end note ]

I think it might be proper to place something specifying the value category here, adding "except where otherwise specified".




2013/1/25 <ai.a...@gmail.com>

--
 
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.

To post to this group, send email to std-dis...@isocpp.org.

ai.a...@gmail.com

unread,
Jan 24, 2013, 11:41:43 PM1/24/13
to std-dis...@isocpp.org
2013年1月25日金曜日 12時58分19秒 UTC+9 FrankHB1989:

N3485
4/1 ... A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.
2 [ Note: expressions with a given type will be implicitly converted to other types in several contexts:
— When used as operands of operators. The operator’s requirements for its operands dictate the destination type (Clause 5).
— When used in the condition of an if statement or iteration statement (6.4, 6.5). The destination type is bool.
— When used in the expression of a switch statement. The destination type is integral (6.4).
— When used as the source expression for an initialization (which includes use as an argument in a function call and use as the expression in a return statement). The type of the entity being initialized is (generally) the destination type. See 8.5, 8.5.3.
—end note ]

I think it might be proper to place something specifying the value category here, adding "except where otherwise specified".
Ah, of course, value category requirements should be specified not only for the operands of built-in operators but also for expressions appearing in statements or the source of initializations. The place you suggested looks suitable for such requirement.

wolfei...@gmail.com

unread,
Jan 25, 2013, 8:26:48 AM1/25/13
to std-dis...@isocpp.org, ai.a...@gmail.com
I disagree. I think it would be easier to cut lvalue-to-rvalue conversion altogether from the Standard, and simply specify the primitive types in terms of being class types. This would be substantially simpler than the current specification.

FrankHB1989

unread,
Jan 30, 2013, 7:29:46 PM1/30/13
to std-dis...@isocpp.org, ai.a...@gmail.com, wolfei...@gmail.com


在 2013年1月25日星期五UTC+8下午9时26分48秒,wolfei...@gmail.com写道:
I disagree. I think it would be easier to cut lvalue-to-rvalue conversion altogether from the Standard, and simply specify the primitive types in terms of being class types. This would be substantially simpler than the current specification.
That can't be easier. Too much work need to do, such as initialization of references and conversion category of overloading.
 

wolfei...@gmail.com

unread,
Jan 30, 2013, 7:31:40 PM1/30/13
to std-dis...@isocpp.org, ai.a...@gmail.com, wolfei...@gmail.com
Sorry- I didn't actually mean *all* the primitive types, just the primitive values- not pointers or references.
Reply all
Reply to author
Forward
0 new messages