Repository navigation
CWG2981 [expr.arith.conv] 0 < 0 is an int #663
Description
Activity
I'm not really sure what the intended wording strategy here is. https://eel.is/c++draft/expr.mul chooses to say that:
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 + 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:
- [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 + 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.
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.
Reacted by Jan Schultke and A. JiangYou know what, I think I'll just make a paper for that.
Why a paper? I certainly want a bit of CWG review on the change, but this feels entirely like a core issue.
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.9 places (max) need updates.
Reacted by A. JiangSuggested resolution v2
Update [expr.arith.conv] paragraph 1 as follows:
Many binary operators that expect operands of arithmetic or enumeration type cause conversions
and yield result typesin 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.
Update [expr.mul] paragraph 2 as follows:
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.Update [expr.add] paragraph 1 as follows:
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.Update [expr.rel] paragraph 2 as follows:
[...] The
type of theresult is a prvalue of typebool.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:
If both operands are of arithmetic or enumeration type, the usual arithmetic conversions are performed on both operands; each of the operators shall yield
trueif the specified relationship is true andfalseif it is false.
The result is a prvalue of typebool.Update [expr.bit.and] paragraph 1 as follows:
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. [...]Update [expr.xor] paragraph 1 as follows:
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. [...]Update [expr.bit.or] paragraph 1 as follows:
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. [...]Reacted by A. JiangCWG2981 with suggested resolution adjusted to be consistent with [expr.cond] p7.2
- changed the title
[-][expr.arith.conv] `0 < 0` is an `int`[/-][+]CWG2981 [expr.arith.conv] `0 < 0` is an `int`[/+]on Jan 2, 2025
Reference (section label): [expr.arith.conv] pargraph 1
Issue description
[expr.rel] paragraph 2 states that the result of the relational operator for e.g.
0 < 0isbool. This is subsequently contradicted by [expr.rel] paragraph 3, which states that the usual arithmetic conversions are applied, and [expr.arith.conv] paragraph 1 states:If paragraph 3 supersedes paragraph 2, then
0 < 0is of typeint.Suggested resolution
Update [expr.arith.conv] paragraph 1 as follows: