Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #85937 > unrolled thread
| Started by | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| First post | 2022-08-15 10:45 -0700 |
| Last post | 2022-08-17 09:08 -0700 |
| Articles | 16 — 7 participants |
Back to article view | Back to comp.lang.c++
`bool` in pointer arithmetic: when does the promotion occur, if ever? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-08-15 10:45 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? David Brown <david.brown@hesbynett.no> - 2022-08-15 20:09 +0200
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-08-15 11:29 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-08-15 11:35 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? David Brown <david.brown@hesbynett.no> - 2022-08-15 21:20 +0200
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? red floyd <no.spam.here@its.invalid> - 2022-08-15 13:49 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-08-15 13:59 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? David Brown <david.brown@hesbynett.no> - 2022-08-16 09:12 +0200
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-08-16 09:56 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-09-15 07:18 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Language Lawyer <language.lawyer@gmail.com> - 2022-09-19 03:28 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-10-02 12:37 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-08-15 14:36 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-08-15 14:57 -0700
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-08-16 21:13 +0200
Re: `bool` in pointer arithmetic: when does the promotion occur, if ever? Language Lawyer <language.lawyer@gmail.com> - 2022-08-17 09:08 -0700
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-08-15 10:45 -0700 |
| Subject | `bool` in pointer arithmetic: when does the promotion occur, if ever? |
| Message-ID | <tde0o3$3nqef$1@dont-email.me> |
Hello
Sound like a silly question (and it might just as well be), but
nevertheless:
int *a = <whatever>;
bool b = true;
a + b;
How does the binary `+` work in this case? Its operands are an `int *`
and a `bool`. `bool` is an integer type, so the requirements are met and
the expression is valid. Naturally we expect that `bool` to be promoted
to an integer value of 1, and the rest is clear.
But where does it say in the standard that `bool` should get promoted in
this context? There is no global rule requiring an unconditional
promotion, i.e. each operator's specification mandates integral
promotions individually and explicitly. And I don't see integral
promotions mentioned anywhere in [expr.add].
It does mention usual arithmetic conversions (UAC), of course, and UAC
include integral promotions. But UAC are only applicable when _both_
operands have enumeration or arithmetic type. UAC are not applied when
one operand is a pointer. (The definition of UAC does not accommodate
for such possibility.)
So, how does pointer+bool addition work then? When does `true` turn into
1 here?
--
Best regards
Andrey
[toc] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-08-15 20:09 +0200 |
| Message-ID | <tde24g$3o0ua$1@dont-email.me> |
| In reply to | #85937 |
On 15/08/2022 19:45, Andrey Tarasevich wrote: > Hello > > Sound like a silly question (and it might just as well be), but > nevertheless: > > int *a = <whatever>; > bool b = true; > a + b; > > How does the binary `+` work in this case? Its operands are an `int *` > and a `bool`. `bool` is an integer type, so the requirements are met and > the expression is valid. Naturally we expect that `bool` to be promoted > to an integer value of 1, and the rest is clear. Yes. > > But where does it say in the standard that `bool` should get promoted in > this context? There is no global rule requiring an unconditional > promotion, i.e. each operator's specification mandates integral > promotions individually and explicitly. And I don't see integral > promotions mentioned anywhere in [expr.add]. > My numbering here is from C++20 draft N4860. I don't think anything relevant has changed in different standards, but of course section numbers might. "7.3.6 Integral promotions" says that a "prvalue of type bool can be converted to a prvalue of type int". This is one of the "integral promotions". "7.4 Usual arithmetic conversions" says that integral promotions are performed on both operands of many binary operators, if they are not trumped by floating point conversions. There is a footnote saying "As a consequence, operands of type bool, char8_t, char16_t, char32_t, wchar_t, or an enumerated type are converted to some integral type." > It does mention usual arithmetic conversions (UAC), of course, and UAC > include integral promotions. But UAC are only applicable when _both_ > operands have enumeration or arithmetic type. UAC are not applied when > one operand is a pointer. (The definition of UAC does not accommodate > for such possibility.) > > So, how does pointer+bool addition work then? When does `true` turn into > 1 here? > Under "7.6.6 Additive operators", it says that the usual arithmetic conversions are performed on operands of arithmetic or enumeration type - that includes bool.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-08-15 11:29 -0700 |
| Message-ID | <tde3ab$3o7iu$1@dont-email.me> |
| In reply to | #85938 |
On 8/15/2022 11:09 AM, David Brown wrote: >> >> So, how does pointer+bool addition work then? When does `true` turn >> into 1 here? >> > > Under "7.6.6 Additive operators", it says that the usual arithmetic > conversions are performed on operands of arithmetic or enumeration type > - that includes bool. No, no, no... You can't just arbitrarily pluck this part out of the whole rule. After/if you apply usual arithmetic conversions here, you are required to continue to follow the spec and complete all steps. You are required to follow the "Then the following rules are applied to the promoted operands:" part in 7.4/1.3 (http://eel.is/c++draft/expr.arith.conv#1.3) The specification of usual arithmetic conversions does not have an "early exit" clause if one operand is a pointer. Now, once you start following these "following rules", it becomes clear that they are not applicable (or defective) if one operand is a pointer. Firstly, the concept of "[integer conversion] rank" is not applicable to pointer types. Secondly, (if we ignore the "firstly") these rules ultimately require us to convert both operands to a common integer type. Obviously, in pointer+bool contexts operands are NOT converted to a common integer type. So, no, usual arithmetic conversions do not apply here. As I already stated, the intent of the standard wording is to say that usual arithmetic conversions apply only when _both_ operands have integral or enum type. -- Best regards, Andrey
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-08-15 11:35 -0700 |
| Message-ID | <tde3lq$3oaov$1@dont-email.me> |
| In reply to | #85940 |
On 8/15/2022 11:29 AM, Andrey Tarasevich wrote: > On 8/15/2022 11:09 AM, David Brown wrote: > Secondly, (if we ignore the "firstly") these rules > ultimately require us to convert both operands to a common integer type. > > Obviously, in pointer+bool contexts operands are NOT converted to a > common integer type. So, no, usual arithmetic conversions do not apply > here. As I already stated, the intent of the standard wording is to say > that usual arithmetic conversions apply only when _both_ operands have > integral or enum type. ... when both operands have *arithmetic* or enum type. -- Best regards, Andrey
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-08-15 21:20 +0200 |
| Message-ID | <tde69i$3oucq$1@dont-email.me> |
| In reply to | #85940 |
On 15/08/2022 20:29, Andrey Tarasevich wrote: > On 8/15/2022 11:09 AM, David Brown wrote: >>> >>> So, how does pointer+bool addition work then? When does `true` turn >>> into 1 here? >>> >> >> Under "7.6.6 Additive operators", it says that the usual arithmetic >> conversions are performed on operands of arithmetic or enumeration >> type - that includes bool. > > No, no, no... You can't just arbitrarily pluck this part out of the > whole rule. After/if you apply usual arithmetic conversions here, you > are required to continue to follow the spec and complete all steps. You > are required to follow the "Then the following rules are applied to the > promoted operands:" part in 7.4/1.3 > (http://eel.is/c++draft/expr.arith.conv#1.3) The specification of usual > arithmetic conversions does not have an "early exit" clause if one > operand is a pointer. > > Now, once you start following these "following rules", it becomes clear > that they are not applicable (or defective) if one operand is a pointer. > Firstly, the concept of "[integer conversion] rank" is not applicable to > pointer types. Secondly, (if we ignore the "firstly") these rules > ultimately require us to convert both operands to a common integer type. > > Obviously, in pointer+bool contexts operands are NOT converted to a > common integer type. So, no, usual arithmetic conversions do not apply > here. As I already stated, the intent of the standard wording is to say > that usual arithmetic conversions apply only when _both_ operands have > integral or enum type. > Read the paragraphs in the standards, and follow the rules. When you write "p + b", with "p" being a pointer-to-int and "b" being a bool, you get the following chain: "7.6.6 Additive operators" says "The usual arithmetic conversions (7.4) are performed for operands of arithmetic or enumeration type." The pointer is not an arithmetic or enumeration type, but the boolean is. The "7.4 Usual arithmetic conversions" are primarily concerned about two operands, but the pattern-matching list of "Otherwise, if either operand is ..." can be applied to a single operand too. Since there are no floats, we hit "the integral promotions shall be performed on both operands" - in this case, just the one. None of the rules after that are triggered. (Perhaps the "usual arithmetic conversions" are actually applied to both operands. A pointer would return unscathed by "integral promotions" as it matches none of the rule triggers there.)
[toc] | [prev] | [next] | [standalone]
| From | red floyd <no.spam.here@its.invalid> |
|---|---|
| Date | 2022-08-15 13:49 -0700 |
| Message-ID | <tdebh2$3pvpl$1@redfloyd.dont-email.me> |
| In reply to | #85944 |
On 8/15/2022 12:20 PM, David Brown wrote:
> On 15/08/2022 20:29, Andrey Tarasevich wrote:
>> On 8/15/2022 11:09 AM, David Brown wrote:
>>>>
>>>> So, how does pointer+bool addition work then? When does `true` turn
>>>> into 1 here?
>>>>
>>>
>>> Under "7.6.6 Additive operators", it says that the usual arithmetic
>>> conversions are performed on operands of arithmetic or enumeration
>>> type - that includes bool.
>>
>> No, no, no... You can't just arbitrarily pluck this part out of the
>> whole rule. After/if you apply usual arithmetic conversions here, you
>> are required to continue to follow the spec and complete all steps.
>> You are required to follow the "Then the following rules are applied
>> to the promoted operands:" part in 7.4/1.3
>> (http://eel.is/c++draft/expr.arith.conv#1.3) The specification of
>> usual arithmetic conversions does not have an "early exit" clause if
>> one operand is a pointer.
>>
>> Now, once you start following these "following rules", it becomes
>> clear that they are not applicable (or defective) if one operand is a
>> pointer. Firstly, the concept of "[integer conversion] rank" is not
>> applicable to pointer types. Secondly, (if we ignore the "firstly")
>> these rules ultimately require us to convert both operands to a common
>> integer type.
>>
>> Obviously, in pointer+bool contexts operands are NOT converted to a
>> common integer type. So, no, usual arithmetic conversions do not apply
>> here. As I already stated, the intent of the standard wording is to
>> say that usual arithmetic conversions apply only when _both_ operands
>> have integral or enum type.
>>
>
> Read the paragraphs in the standards, and follow the rules. When you
> write "p + b", with "p" being a pointer-to-int and "b" being a bool, you
> get the following chain:
>
> "7.6.6 Additive operators" says "The usual arithmetic conversions (7.4)
> are performed for operands of arithmetic or enumeration type." The
> pointer is not an arithmetic or enumeration type, but the boolean is.
>
> The "7.4 Usual arithmetic conversions" are primarily concerned about two
> operands, but the pattern-matching list of "Otherwise, if either operand
> is ..." can be applied to a single operand too. Since there are no
> floats, we hit "the integral promotions shall be performed on both
> operands" - in this case, just the one. None of the rules after that
> are triggered.
>
> (Perhaps the "usual arithmetic conversions" are actually applied to both
> operands. A pointer would return unscathed by "integral promotions" as
> it matches none of the rule triggers there.)
Given the potential ambiguity in standard conformant behavior, it's
probably better to make it explicit...
[going back to Andrey's initial post]
int *a = <whatever>;
bool b = true;
a + static_cast<int>(b);
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-08-15 13:59 -0700 |
| Message-ID | <tdec2o$3q32d$1@dont-email.me> |
| In reply to | #85944 |
On 8/15/2022 12:20 PM, David Brown wrote: >> >> Obviously, in pointer+bool contexts operands are NOT converted to a >> common integer type. So, no, usual arithmetic conversions do not apply >> here. As I already stated, the intent of the standard wording is to >> say that usual arithmetic conversions apply only when _both_ operands >> have integral or enum type. >> > > Read the paragraphs in the standards, and follow the rules. When you > write "p + b", with "p" being a pointer-to-int and "b" being a bool, you > get the following chain: That's exactly what I'm doing. > "7.6.6 Additive operators" says "The usual arithmetic conversions (7.4) > are performed for operands of arithmetic or enumeration type." The > pointer is not an arithmetic or enumeration type, but the boolean is. > > The "7.4 Usual arithmetic conversions" are primarily concerned about two > operands, but the pattern-matching list of "Otherwise, if either operand > is ..." can be applied to a single operand too. That does not mean that you can simply pluck that part out of the whole rule and nonchalantly discard the rest. (And I feel like I'm repeating myself.) > Since there are no > floats, we hit "the integral promotions shall be performed on both > operands" - in this case, just the one. None of the rules after that > are triggered. That's not true. And I already covered this above. Firstly, the "rules after that" attempt to apply the concept of integer conversion rank to both operands, which is not defined for pointer types. The C++ standard does not adhere to the principle that "if some rule is stated nonsensically then it is simply not triggered". Such rules would be hard defects. Secondly, in any case these rules cannot be brushed off under "not triggered" premise because the very last rule in the list is a "sink": it is not protected by a trigger at all, it is unconditional. If none of the previous rules are "triggered" then the last rule applies: http://eel.is/c++draft/expr.arith.conv#1.3.5 - Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. What do you expect this to do if one operand is a pointer? I thought that this problem would be obvious, but apparently I need to spell out every detail... So, it is is actually me who's telling you to "read the paragraphs in the standards, and follow the rules". > (Perhaps the "usual arithmetic conversions" are actually applied to both > operands. A pointer would return unscathed by "integral promotions" as > it matches none of the rule triggers there.) Yes, integral promotions are safe specifically because of this: every rule in integral promotions is protected by an "if barrier" and therefore it leaves pointers unchanged (assuming a pointer can get there legally). But the question is not about integral promotions. The question is about usual arithmetic conversions. Rules of usual arithmetic conversions do not implement this kind of protection. -- Best regards, Andrey
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-08-16 09:12 +0200 |
| Message-ID | <tdfg0k$dbm$1@dont-email.me> |
| In reply to | #85949 |
On 15/08/2022 22:59, Andrey Tarasevich wrote: > On 8/15/2022 12:20 PM, David Brown wrote: >>> >>> Obviously, in pointer+bool contexts operands are NOT converted to a >>> common integer type. So, no, usual arithmetic conversions do not >>> apply here. As I already stated, the intent of the standard wording >>> is to say that usual arithmetic conversions apply only when _both_ >>> operands have integral or enum type. >>> >> >> Read the paragraphs in the standards, and follow the rules. When you >> write "p + b", with "p" being a pointer-to-int and "b" being a bool, >> you get the following chain: > > That's exactly what I'm doing. > >> "7.6.6 Additive operators" says "The usual arithmetic conversions >> (7.4) are performed for operands of arithmetic or enumeration type." >> The pointer is not an arithmetic or enumeration type, but the boolean is. >> >> The "7.4 Usual arithmetic conversions" are primarily concerned about >> two operands, but the pattern-matching list of "Otherwise, if either >> operand is ..." can be applied to a single operand too. > > That does not mean that you can simply pluck that part out of the whole > rule and nonchalantly discard the rest. (And I feel like I'm repeating > myself.) Yes, you /can/. These sections are written as lists of "otherwise, if ..." rules. Once you've triggered such a rule, the others on the list /can/ be discarded. If none are triggered, then nothing happens - no promotions or conversions apply, nor is the code explicitly ruled valid or invalid. > >> Since there are no floats, we hit "the integral promotions shall be >> performed on both operands" - in this case, just the one. None of the >> rules after that are triggered. > > That's not true. And I already covered this above. I agree that "in pointer+bool contexts operands are NOT converted to a common integer type". But I disagree that this means the paragraphs about "usual arithmetic conversions" and "integral promotions" don't apply - the standards explicitly say they do. > > Firstly, the "rules after that" attempt to apply the concept of integer > conversion rank to both operands, which is not defined for pointer > types. The C++ standard does not adhere to the principle that "if some > rule is stated nonsensically then it is simply not triggered". Such > rules would be hard defects. SFINAE ? I think the way it is written /is/ defective - it is not clear enough how these rules apply. I am merely trying to explain how /I/ interpret them. My interpretation gives almost certainly the same results as the C++ committee intended, and it matches both the C standards (which are clearer here) and implementations. But that does not mean it is correct - there may be other explanations that give the same resulting behaviour, and it may be that the standard is defective and there are no consistent readings of the standard here. > > Secondly, in any case these rules cannot be brushed off under "not > triggered" premise because the very last rule in the list is a "sink": > it is not protected by a trigger at all, it is unconditional. If none of > the previous rules are "triggered" then the last rule applies: > > http://eel.is/c++draft/expr.arith.conv#1.3.5 > - Otherwise, both operands are converted to the unsigned integer type > corresponding to the type of the operand with signed integer type. > > What do you expect this to do if one operand is a pointer? It doesn't get that far. As I interpret this, only the bool gets the "usual arithmetic conversions" - thus references to "both operands" only apply to the single operand. After the integral promotions are performed (turning the bool into int), we get "If both operands have the same type, no further conversion is needed" and stop there. > > I thought that this problem would be obvious, but apparently I need to > spell out every detail... So, it is is actually me who's telling you to > "read the paragraphs in the standards, and follow the rules". I'm sorry - I thought it was /you/ who asked the original question, looking for help? And the thanks I get for going through the paragraphs and explaining as best I can how I read the standards, is to get my head bitten off? Maybe my understanding of the standards is not quite right. Maybe my explanation wasn't great. But if this is your idea of how to say "I don't see it that way, but thanks for trying", I'll leave you to figure things out some other way. Perhaps someone else will reply to you, and maybe give you a reading that you'd prefer. > >> (Perhaps the "usual arithmetic conversions" are actually applied to >> both operands. A pointer would return unscathed by "integral >> promotions" as it matches none of the rule triggers there.) > > Yes, integral promotions are safe specifically because of this: every > rule in integral promotions is protected by an "if barrier" and > therefore it leaves pointers unchanged (assuming a pointer can get there > legally). > > But the question is not about integral promotions. The question is about > usual arithmetic conversions. Rules of usual arithmetic conversions do > not implement this kind of protection. >
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-08-16 09:56 -0700 |
| Message-ID | <tdgi76$3p1q$1@dont-email.me> |
| In reply to | #85954 |
On 8/16/2022 12:12 AM, David Brown wrote: >> >> Secondly, in any case these rules cannot be brushed off under "not >> triggered" premise because the very last rule in the list is a "sink": >> it is not protected by a trigger at all, it is unconditional. If none >> of the previous rules are "triggered" then the last rule applies: >> >> http://eel.is/c++draft/expr.arith.conv#1.3.5 >> - Otherwise, both operands are converted to the unsigned integer >> type corresponding to the type of the operand with signed integer type. >> >> What do you expect this to do if one operand is a pointer? > > It doesn't get that far. As I interpret this, only the bool gets the > "usual arithmetic conversions" - thus references to "both operands" only > apply to the single operand. After the integral promotions are > performed (turning the bool into int), we get "If both operands have the > same type, no further conversion is needed" and stop there. > But... why? Why do we suddenly stop at "If both operands have the same type..."? We have a pointer and a bool. How is that "the same type", even if you promote the bool to an integer? > I'm sorry - I thought it was /you/ who asked the original question, looking for help? And the thanks I get for going through the paragraphs and explaining as best I can how I read the standards, is to get my head bitten off? > > Maybe my understanding of the standards is not quite right. Maybe my explanation wasn't great. But if this is your idea of how to say "I don't see it that way, but thanks for trying", I'll leave you to figure things out some other way. Perhaps someone else will reply to you, and maybe give you a reading that you'd prefer. Well, this was intended as a "language lawyer" kind of question. So, the help I was looking for does not allow for interpretations. I just needed a confirmation that what looks to me as a defect is indeed likely to be a defect. -- Best regards,
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-09-15 07:18 -0700 |
| Message-ID | <868rmkn2k7.fsf@linuxsc.com> |
| In reply to | #85955 |
Andrey Tarasevich <andreytarasevich@hotmail.com> writes: > On 8/16/2022 12:12 AM, David Brown wrote: > >>> Secondly, in any case these rules cannot be brushed off under "not >>> triggered" premise because the very last rule in the list is a >>> "sink": it is not protected by a trigger at all, it is >>> unconditional. If none of the previous rules are "triggered" then >>> the last rule applies: >>> >>> http://eel.is/c++draft/expr.arith.conv#1.3.5 >>> - Otherwise, both operands are converted to the unsigned integer >>> type corresponding to the type of the operand with signed integer >>> type. >>> >>> What do you expect this to do if one operand is a pointer? >> >> It doesn't get that far. As I interpret this, only the bool gets >> the "usual arithmetic conversions" - thus references to "both >> operands" only apply to the single operand. After the integral >> promotions are performed (turning the bool into int), we get "If >> both operands have the same type, no further conversion is needed" >> and stop there. > > But... why? Why do we suddenly stop at "If both operands have the > same type..."? We have a pointer and a bool. How is that "the > same type", even if you promote the bool to an integer? It occurs to me that the problem here is not with the description of additive operators (section 7.6.6) but with section 7.4, which defines the usual arithmetic conversions. What we have in the case of a pointer and a bool is not two operands but one operand, that is, just the bool (remember that 7.6.6 p1 says "The usual arithmetic conversions are performed for operands of arithmetic or enumeration type", which is just the bool operand in this case). Section 7.4 is written with the assumption that there will be two operands being treated, but in this case there is only one. Thus a solution is to revise 7.4 so it addresses the more general scenario of converting one or more operands. Here is a draft of a possible revision: Many operators that expect one or more 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: (1.1) -- If any operand is of scoped enumeration type no conversions are performed; if any other operand does not have the same type, the expression is ill-formed. (1.2) -- If any operand is of type long double, all other operands shall be converted to long double. (1.3) -- Otherwise, if any operand is double, all other operands shall be converted to double. (1.4) -- Otherwise, if any operand is float, all other operands shall be converted to float. (1.5) -- Otherwise, the integral promotions shall be performed on all operands. Then the following rules shall be applied to the promoted operands: (1.5.1) -- If all operands have the same type, no further conversion is needed. (1.5.2) -- Otherwise, if all operands have signed integer types or all operands have unsigned integer types, all operands with a type of lesser integer conversion rank shall be converted to an operand type having the greatest integer conversion rank. (1.5.3) -- Otherwise, if an operand that has unsigned integer type has an integer conversion rank that is greater than or equal to the rank of the type of all other operands, all other operands shall be converted to the type of the unsigned integer operand with the greatest integer conversion rank. (1.5.4) -- Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of all other operands, those operands shall be converted to the type of the signed integer operand with the greatest integer conversion rank. (1.5.5) -- Otherwise, all operands shall be converted to the unsigned integer type corresponding to the type of an operand with signed integer type having the greatest integer conversion rank. 2 If one operand is of enumeration type and any other operand is of a different enumeration type or a floating-point type, this behavior is deprecated. Taking this approach solves the problem for section 7.6.6 and also anticipates possible future additions to the language that have more than two operands.
[toc] | [prev] | [next] | [standalone]
| From | Language Lawyer <language.lawyer@gmail.com> |
|---|---|
| Date | 2022-09-19 03:28 -0700 |
| Message-ID | <b79ea01a-2cb1-4122-b335-14d0ca45c041n@googlegroups.com> |
| In reply to | #86337 |
> Section 7.4 is written with the assumption that there will be two operands being treated, but in this case there is only one. Thus a solution is to revise 7.4 so it addresses the more general scenario of converting one or more operands. Or explicitly say in [expr.add] that the promotion is performed on the integer or enumeration operand, as [expr.unary.op] does (https://timsong-cpp.github.io/cppwp/n4861/expr.unary.op#7.sentence-2, https://timsong-cpp.github.io/cppwp/n4861/expr.unary.op#8.sentence-2, https://timsong-cpp.github.io/cppwp/n4861/expr.unary.op#10.sentence-2)
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-10-02 12:37 -0700 |
| Message-ID | <86czbaj9th.fsf@linuxsc.com> |
| In reply to | #86420 |
Language Lawyer <language.lawyer@gmail.com> writes: >> Section 7.4 is written with the assumption that there will be two >> operands being treated, but in this case there is only one. Thus a >> solution is to revise 7.4 so it addresses the more general scenario >> of converting one or more operands. > > Or explicitly say in [expr.add] that the promotion is performed on > the integer or enumeration operand, Seems like a bandaid. I think it would be better to add a case to the usual arithmetic conversions that covers the case of a pointer and a non-pointer.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-08-15 14:36 -0700 |
| Message-ID | <86fshxur3q.fsf@linuxsc.com> |
| In reply to | #85937 |
Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
> Sound like a silly question (and it might just as well be), but
> nevertheless:
>
> int *a = <whatever>;
> bool b = true;
> a + b;
>
> How does the binary `+` work in this case? Its operands are an `int *`
> and a `bool`. `bool` is an integer type, so the requirements are met
> and the expression is valid. Naturally we expect that `bool` to be
> promoted to an integer value of 1, and the rest is clear.
>
> But where does it say in the standard that `bool` should get promoted
> in this context? There is no global rule requiring an unconditional
> promotion, i.e. each operator's specification mandates integral
> promotions individually and explicitly. And I don't see integral
> promotions mentioned anywhere in [expr.add].
>
> It does mention usual arithmetic conversions (UAC), of course, and UAC
> include integral promotions. But UAC are only applicable when _both_
> operands have enumeration or arithmetic type. UAC are not applied when
> one operand is a pointer. (The definition of UAC does not accommodate
> for such possibility.)
>
> So, how does pointer+bool addition work then? When does `true` turn
> into 1 here?
Just a few comments..
One, I think you are raising a good point.
Two, my guess is that this issue reflects an oversight on the part
of the C++ standards committee. At the very least, assuming there
is a provision in the C++ standard the gives this result, the
reasoning needed is obscure and deserves a note.
Three, an argument could be made (for C++20, n4860) that converting
'true' or 'false' to 1 or 0 is a consequence of the last sentence
of section 7.3 paragraph 1:
A standard conversion sequence will be applied to an expression
if necessary to convert it to a required destination type.
Granted, the reasoning is fraught with ambiguity, and that is never
good. But the 'if necessary' provision gives a lot of latitude.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2022-08-15 14:57 -0700 |
| Message-ID | <87lerpcgqj.fsf@nosuchdomain.example.com> |
| In reply to | #85950 |
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
>
>> Sound like a silly question (and it might just as well be), but
>> nevertheless:
>>
>> int *a = <whatever>;
>> bool b = true;
>> a + b;
>>
>> How does the binary `+` work in this case? Its operands are an `int *`
>> and a `bool`. `bool` is an integer type, so the requirements are met
>> and the expression is valid. Naturally we expect that `bool` to be
>> promoted to an integer value of 1, and the rest is clear.
>>
>> But where does it say in the standard that `bool` should get promoted
>> in this context? There is no global rule requiring an unconditional
>> promotion, i.e. each operator's specification mandates integral
>> promotions individually and explicitly. And I don't see integral
>> promotions mentioned anywhere in [expr.add].
>>
>> It does mention usual arithmetic conversions (UAC), of course, and UAC
>> include integral promotions. But UAC are only applicable when _both_
>> operands have enumeration or arithmetic type. UAC are not applied when
>> one operand is a pointer. (The definition of UAC does not accommodate
>> for such possibility.)
>>
>> So, how does pointer+bool addition work then? When does `true` turn
>> into 1 here?
>
> Just a few comments..
>
> One, I think you are raising a good point.
>
> Two, my guess is that this issue reflects an oversight on the part
> of the C++ standards committee. At the very least, assuming there
> is a provision in the C++ standard the gives this result, the
> reasoning needed is obscure and deserves a note.
>
> Three, an argument could be made (for C++20, n4860) that converting
> 'true' or 'false' to 1 or 0 is a consequence of the last sentence
> of section 7.3 paragraph 1:
>
> A standard conversion sequence will be applied to an expression
> if necessary to convert it to a required destination type.
>
> Granted, the reasoning is fraught with ambiguity, and that is never
> good. But the 'if necessary' provision gives a lot of latitude.
I think this is an oversight in the standard, and one that would be
fairly straightforward to correct.
The C standard, under "Additive operators", says:
If both operands have arithmetic type, the usual arithmetic
conversions are performed on them.
The corresponding wording in the C++ standard says:
The usual arithmetic conversions are performed for operands of
arithmetic or enumeration type.
The description of the "usual arithmetic conversions" is similar in both
standards, and assumes that both operands are of arithmetic type. I
can't think of any good reason why the "If both operands have arithmetic
type," wording *should* apply in C but not in C++.
It *should* say that if one operand is of pointer type, the other
operand should undergo the integral promotions (but *not* the usual
arithmetic conversions). So if you add a pointer and a bool, the bool
should be converted to int (0 or 1).
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach@gmail.com> |
|---|---|
| Date | 2022-08-16 21:13 +0200 |
| Message-ID | <tdgq81$4lkc$1@dont-email.me> |
| In reply to | #85937 |
On 15 Aug 2022 19:45, Andrey Tarasevich wrote: > Hello > > Sound like a silly question (and it might just as well be), but > nevertheless: > > int *a = <whatever>; > bool b = true; > a + b; > > How does the binary `+` work in this case? Its operands are an `int *` > and a `bool`. `bool` is an integer type, so the requirements are met and > the expression is valid. Naturally we expect that `bool` to be promoted > to an integer value of 1, and the rest is clear. > > But where does it say in the standard that `bool` should get promoted in > this context? There is no global rule requiring an unconditional > promotion, i.e. each operator's specification mandates integral > promotions individually and explicitly. And I don't see integral > promotions mentioned anywhere in [expr.add]. > > It does mention usual arithmetic conversions (UAC), of course, and UAC > include integral promotions. But UAC are only applicable when _both_ > operands have enumeration or arithmetic type. UAC are not applied when > one operand is a pointer. (The definition of UAC does not accommodate > for such possibility.) > > So, how does pointer+bool addition work then? When does `true` turn into > 1 here? > Looks like a little defect in the standard, including C++17 where there is contextual implicit conversion. cppreference lists the cases where that applies, <url: https://en.cppreference.com/w/cpp/language/implicit_conversion>. No, no `+` there. And as far as I can see the problem for `+` is not only `bool` but also unscoped enumeration arg. The `+` section (additive operators) states that if one arg is pointer then the other must be integral type or unscoped enumeration, but it then defines the effect only for integral type. Gah. It does invoke usual arithmetic conversions, but that leads down to a self-contradiction: it's assumed that if the operand types are different after promotion then they must be unsigned and signed integral. In short, it's a subtle mess, probably too unimportant for the committee to fix, or even an editorial fix. I guess Someone(tm) can check if there's a Defect Report for this. Maybe one was issued already for C++03. - Alf
[toc] | [prev] | [next] | [standalone]
| From | Language Lawyer <language.lawyer@gmail.com> |
|---|---|
| Date | 2022-08-17 09:08 -0700 |
| Message-ID | <808f24ee-8bf4-488d-85ce-dd2c1c0f8828n@googlegroups.com> |
| In reply to | #85937 |
https://github.com/cplusplus/draft/issues/5199
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web