You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Many binary operators that expect operands of arithmetic or enumeration type
cause conversions and yield result types in a similar way.
The purpose is to yield a common type
-, which+; unless otherwise stated, that common type
is also the type of the result.
This pattern is called the usual arithmetic conversions, which are defined as follows:
The usual arithmetic conversions are performed on the operands and determine the type of the result.
But why wouldn't the usual arithmetic conversions determine the result by default? [expr.arith.conv] simply states what the result is, and that wording isn't conditional on "if stated to determine the type of the result". Also note that [expr.add] relies on the type of 0 + 0 being determined by the usual arithmetic conversions without this being stated explicitly; it is nowhere stated in [expr.add] what the type of 0 + 0 is.
In short, we end up with three cases at least:
[expr.add] implicitly uses the result type of usual arithmetic conversions
[expr.mul] explicitly uses the result type of usual arithmetic conversions
[expr.rel] inadvertently (?) uses the result type and contradicts prior wording
On another side note, I couldn't find any wording which states what the value category of 0 + 0 is.
My preferred overarching fix would be to purge the practice of using [expr.arith.conv] to determine the result type completely (it's weird, done inconsistently, and doesn't save that much wording elsewhere anyway), and that could be done as an editorial fix once normative wording problems are fixed.
I think we should limit "usual arithmetic conversions" to exactly that: conversions on the operands. The result type (and value category) should be specified by each individual operator.
Because the blast radius is pretty large here, and I think as a drive-by fix, we should also specify the value category where needed. I'll look into how big of a change that really is first. I guess I can post the diff here and see if that needs a paper.
In the end, we should clearly state that e.g. x + y for integers is a prvalue of the common type after usual arithmetic conversions.
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows: [...]
Editor's note: While it's not incorrect that result types are also often yielded in a similar way, it's not always the case (e.g. [expr.rel], [expr.eq]), and we should purge any mention of result types if these conversions aren't stated to determine the result anyway.
The usual arithmetic conversions are performed on the operands and determine the type of the result, and the result is a prvalue of the common type determined by the usual arithmetic conversions.
The additive operators + and - group left-to-right.
Each operand shall be a prvalue.
If both operands have arithmetic or unscoped enumeration type, the usual arithmetic conversions are performed on the operands, and the result is a prvalue of the common type determined by the usual arithmetic conversions.
Otherwise, if one operand has arithmetic or unscoped enumeration type, integral promotion is applied to that operand.
A converted or promoted operand is used in place of the corresponding original operand for the remainder of this section.
[...] The type of the result is a prvalue of type bool.
Editor's note: Since we state that false or true are always yielded, this is only an editorial fix. Nonetheless, we should do it for consistency here. This core issue introduces "prvalue of type" wording for every case that was previously covered by the usual arithmetic conversions, and so updating this part of [expr.rel] should be within its scope.
If both operands are of arithmetic or enumeration type, the usual arithmetic conversions are performed on both operands; each of the operators shall yield true if the specified relationship is true and false if it is false.
The result is a prvalue of type bool.
The & operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions are performed on the operands, and the result is a prvalue of the common type determined by the usual arithmetic conversions. [...]
The ^ operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions are performed on the operands, and the result is a prvalue of the common type determined by the usual arithmetic conversions. [...]
The | operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions are performed on the operands, and the result is a prvalue of the common type determined by the usual arithmetic conversions. [...]
Activity
eisenwave commentedon Jan 2, 2025
I'm not really sure what the intended wording strategy here is. https://eel.is/c++draft/expr.mul chooses to say that:
But why wouldn't the usual arithmetic conversions determine the result by default? [expr.arith.conv] simply states what the result is, and that wording isn't conditional on "if stated to determine the type of the result". Also note that [expr.add] relies on the type of
0 + 0being determined by the usual arithmetic conversions without this being stated explicitly; it is nowhere stated in [expr.add] what the type of0 + 0is.In short, we end up with three cases at least:
On another side note, I couldn't find any wording which states what the value category of
0 + 0is.My preferred overarching fix would be to purge the practice of using [expr.arith.conv] to determine the result type completely (it's weird, done inconsistently, and doesn't save that much wording elsewhere anyway), and that could be done as an editorial fix once normative wording problems are fixed.
jensmaurer commentedon Jan 2, 2025
I think we should limit "usual arithmetic conversions" to exactly that: conversions on the operands. The result type (and value category) should be specified by each individual operator.
eisenwave commentedon Jan 2, 2025
You know what, I think I'll just make a paper for that.
jensmaurer commentedon Jan 2, 2025
Why a paper? I certainly want a bit of CWG review on the change, but this feels entirely like a core issue.
eisenwave commentedon Jan 2, 2025
Because the blast radius is pretty large here, and I think as a drive-by fix, we should also specify the value category where needed. I'll look into how big of a change that really is first. I guess I can post the diff here and see if that needs a paper.
In the end, we should clearly state that e.g.
x + yfor integers is a prvalue of the common type after usual arithmetic conversions.jensmaurer commentedon Jan 2, 2025
9 places (max) need updates.
eisenwave commentedon Jan 2, 2025
Suggested resolution v2
Update [expr.arith.conv] paragraph 1 as follows:
Editor's note: While it's not incorrect that result types are also often yielded in a similar way, it's not always the case (e.g. [expr.rel], [expr.eq]), and we should purge any mention of result types if these conversions aren't stated to determine the result anyway.
Update [expr.mul] paragraph 2 as follows:
Update [expr.add] paragraph 1 as follows:
Update [expr.rel] paragraph 2 as follows:
Editor's note: Since we state that
falseortrueare always yielded, this is only an editorial fix. Nonetheless, we should do it for consistency here. This core issue introduces "prvalue of type" wording for every case that was previously covered by the usual arithmetic conversions, and so updating this part of [expr.rel] should be within its scope.Update [expr.eq] paragraph 7 as follows:
Update [expr.bit.and] paragraph 1 as follows:
Update [expr.xor] paragraph 1 as follows:
Update [expr.bit.or] paragraph 1 as follows:
jensmaurer commentedon Jan 2, 2025
CWG2981 with suggested resolution adjusted to be consistent with [expr.cond] p7.2
[-][expr.arith.conv] `0 < 0` is an `int`[/-][+]CWG2981 [expr.arith.conv] `0 < 0` is an `int`[/+]