Topic: Default values for n4191 fold expressions


Author: Edward Catmur <ed@catmur.co.uk>
Date: Wed, 15 Oct 2014 16:53:46 -0700 (PDT)
Raw View
N4191 provides that the fold of an empty parameter pack is defined for the =
binary operators + * & | && || , to 0 1 0 -1 false true void() respectively=
.. I am concerned that this may result in confusing or undefined behavior, e=
specially for types that overload these operators.

Consider string s =3D (to_string(args) + ...); if the 0 is the literal and =
so can be interpreted as a null pointer constant this results in undefined =
behavior, while if it is a prvalue int this gives a string of length 1 cont=
aining a nul character. Other types give different errors; std::chrono::dur=
ation fails as its constructor from int is explicit.=20

For binary * the library type valarray is unlikely to behave as desired; si=
milarly a square matrix type could give incorrect results. The binary bitwi=
se operators present a similar issue, and even for primitive types -1 is li=
kely to be of the wrong length and/or signedness (what happens when 32-bit =
-1 is promoted to uint64_t?)

I would therefore argue to disallow empty parameter pack fold expansions fo=
r the arithmetic and bitwise operators. The binary boolean operators and co=
mma operator can stay; they are far less often overloaded and the default v=
alues are simultaneously more obviously correct and unique, more difficult =
to remember, and require more typing than for the arithmetic and bitwise op=
erators.

Regards, Ed=20

PS. If we are doing bitwise operators, what about ^?

PPS. Is ~ really supposed to be in there?=20

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

.


Author: Richard Smith <richard@metafoo.co.uk>
Date: Wed, 15 Oct 2014 19:22:45 -0700
Raw View
--047d7b86d52083e784050580ecfc
Content-Type: text/plain; charset=UTF-8

On Wed, Oct 15, 2014 at 4:53 PM, Edward Catmur <ed@catmur.co.uk> wrote:

> N4191 provides that the fold of an empty parameter pack is defined for the
> binary operators + * & | && || , to 0 1 0 -1 false true void()
> respectively. I am concerned that this may result in confusing or undefined
> behavior, especially for types that overload these operators.
>
> Consider string s = (to_string(args) + ...); if the 0 is the literal and
> so can be interpreted as a null pointer constant this results in undefined
> behavior,


An empty pack fold-expression should never be considered to be a null
pointer literal; thanks for pointing that out.


> while if it is a prvalue int this gives a string of length 1 containing a
> nul character.


Yes, there's some risk this might happen accidentally. (If you anticipate
the problem, you can write "auto s = (to_string(args) + ... +
std::string());".) But it seems like a mistake that std::string implicitly
converts from an int in a surprising way, and fixing that might be a better
approach for this particular problem.


> Other types give different errors; std::chrono::duration fails as its
> constructor from int is explicit.
>

That's the same result you'd get with your proposed approach; I don't see a
good way to address that.

For binary * the library type valarray is unlikely to behave as desired;


That case will give an error; the conversion from size_t is explicit.


> similarly a square matrix type could give incorrect results. The binary
> bitwise operators present a similar issue, and even for primitive types -1
> is likely to be of the wrong length and/or signedness (what happens when
> 32-bit -1 is promoted to uint64_t?)
>

You get std::numeric_limits<uint64_t>::max(), which seems like the right
answer for this case.

I would therefore argue to disallow empty parameter pack fold expansions
> for the arithmetic and bitwise operators.


This is a tricky convenience/safety tradeoff. I don't think the choice is
obvious. We'll see what EWG thinks.

The binary boolean operators and comma operator can stay; they are far less
> often overloaded and the default values are simultaneously more obviously
> correct and unique, more difficult to remember, and require more typing
> than for the arithmetic and bitwise operators.
>
> Regards, Ed
>
> PS. If we are doing bitwise operators, what about ^?
>

The "simple" (no base case) forms exist for convenience, for types that act
like the primitive types. A fold over ^ for primitive types doesn't seem
likely to be useful in practice. But I wouldn't be opposed if there's a
desire for it.

PPS. Is ~ really supposed to be in there?


Oops, no, it's not.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--047d7b86d52083e784050580ecfc
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Oct 15, 2014 at 4:53 PM, Edward Catmur <span dir=3D"ltr">&lt;<a href=3D=
"mailto:ed@catmur.co.uk" target=3D"_blank">ed@catmur.co.uk</a>&gt;</span> w=
rote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex">N4191 provides that the fold of an empty paramete=
r pack is defined for the binary operators + * &amp; | &amp;&amp; || , to 0=
 1 0 -1 false true void() respectively. I am concerned that this may result=
 in confusing or undefined behavior, especially for types that overload the=
se operators.<br>
<br>
Consider string s =3D (to_string(args) + ...); if the 0 is the literal and =
so can be interpreted as a null pointer constant this results in undefined =
behavior,</blockquote><div><br></div><div><div>An empty pack fold-expressio=
n should never be considered to be a null pointer literal; thanks for point=
ing that out.</div><div>=C2=A0<br></div></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex">while if it =
is a prvalue int this gives a string of length 1 containing a nul character=
..</blockquote><div><br></div><div>Yes, there&#39;s some risk this might hap=
pen accidentally. (If you anticipate the problem, you can write &quot;auto =
s =3D (to_string(args) + ... + std::string());&quot;.) But it seems like a =
mistake that std::string implicitly converts from an int in a surprising wa=
y, and fixing that might be a better approach for this particular problem.<=
/div><div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex">Other types give different erro=
rs; std::chrono::duration fails as its constructor from int is explicit.<br=
></blockquote></div><div><br></div><div>That&#39;s the same result you&#39;=
d get with your proposed approach; I don&#39;t see a good way to address th=
at.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);b=
order-left-style:solid;padding-left:1ex">For binary * the library type vala=
rray is unlikely to behave as desired;</blockquote><div><br></div><div>That=
 case will give an error; the conversion from size_t is explicit.</div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-=
style:solid;padding-left:1ex">similarly a square matrix type could give inc=
orrect results. The binary bitwise operators present a similar issue, and e=
ven for primitive types -1 is likely to be of the wrong length and/or signe=
dness (what happens when 32-bit -1 is promoted to uint64_t?)<br></blockquot=
e><div><br></div><div>You get std::numeric_limits&lt;uint64_t&gt;::max(), w=
hich seems like the right answer for this case.</div><div><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex">
I would therefore argue to disallow empty parameter pack fold expansions fo=
r the arithmetic and bitwise operators.</blockquote><div><br></div><div>Thi=
s is a tricky convenience/safety tradeoff. I don&#39;t think the choice is =
obvious. We&#39;ll see what EWG thinks.</div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
">The binary boolean operators and comma operator can stay; they are far le=
ss often overloaded and the default values are simultaneously more obviousl=
y correct and unique, more difficult to remember, and require more typing t=
han for the arithmetic and bitwise operators.<br>
<br>
Regards, Ed<br>
<br>
PS. If we are doing bitwise operators, what about ^?<br></blockquote><div><=
br></div><div>The &quot;simple&quot; (no base case) forms exist for conveni=
ence, for types that act like the primitive types. A fold over ^ for primit=
ive types doesn&#39;t seem likely to be useful in practice. But I wouldn&#3=
9;t be opposed if there&#39;s a desire for it.</div><div><br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-l=
eft:1ex">
PPS. Is ~ really supposed to be in there?</blockquote><div><br></div><div>O=
ops, no, it&#39;s not.=C2=A0</div></div></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7b86d52083e784050580ecfc--

.


Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Fri, 17 Oct 2014 00:12:55 -0700 (PDT)
Raw View
------=_Part_634_147595737.1413529975909
Content-Type: text/plain; charset=UTF-8

On Wednesday, October 15, 2014 7:22:47 PM UTC-7, Richard Smith wrote:
>
> while if it is a prvalue int this gives a string of length 1 containing a
>> nul character.
>
>
> Yes, there's some risk this might happen accidentally. (If you anticipate
> the problem, you can write "auto s = (to_string(args) + ... +
> std::string());".) But it seems like a mistake that std::string implicitly
> converts from an int in a surprising way, and fixing that might be a better
> approach for this particular problem.
>

Can it be fixed without breaking user code?

>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_634_147595737.1413529975909
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, October 15, 2014 7:22:47 PM UTC-7, Richard S=
mith wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><d=
iv><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,=
204);border-left-style:solid;padding-left:1ex">while if it is a prvalue int=
 this gives a string of length 1 containing a nul character.</blockquote><d=
iv><br></div><div>Yes, there's some risk this might happen accidentally. (I=
f you anticipate the problem, you can write "auto s =3D (to_string(args) + =
.... + std::string());".) But it seems like a mistake that std::string impli=
citly converts from an int in a surprising way, and fixing that might be a =
better approach for this particular problem.</div></div></div></div></block=
quote><div><br></div><div>Can it be fixed without breaking user code?</div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;">
</blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_634_147595737.1413529975909--

.


Author: Jens Maurer <Jens.Maurer@gmx.net>
Date: Fri, 17 Oct 2014 17:53:02 +0200
Raw View
On 10/17/2014 09:12 AM, Sean Middleditch wrote:
> On Wednesday, October 15, 2014 7:22:47 PM UTC-7, Richard Smith wrote:
>=20
>         while if it is a prvalue int this gives a string of length 1 cont=
aining a nul character.
>=20
>=20
>     Yes, there's some risk this might happen accidentally. (If you antici=
pate the problem, you can write "auto s =3D (to_string(args) + ... + std::s=
tring());".) But it seems like a mistake that std::string implicitly conver=
ts from an int in a surprising way, and fixing that might be a better appro=
ach for this particular problem.
>=20
>=20
> Can it be fixed without breaking user code?

That's probably hard.

We could have a
   std::string(int) =3D delete

constructor overload that catches literal "0", but

  std::string(const char *)

is certainly in widespread use.

Jens

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Fri, 17 Oct 2014 22:14:22 +0300
Raw View
On 17 October 2014 18:53, Jens Maurer <Jens.Maurer@gmx.net> wrote:
> On 10/17/2014 09:12 AM, Sean Middleditch wrote:
>> On Wednesday, October 15, 2014 7:22:47 PM UTC-7, Richard Smith wrote:
>>
>>         while if it is a prvalue int this gives a string of length 1 con=
taining a nul character.
>>
>>
>>     Yes, there's some risk this might happen accidentally. (If you antic=
ipate the problem, you can write "auto s =3D (to_string(args) + ... + std::=
string());".) But it seems like a mistake that std::string implicitly conve=
rts from an int in a surprising way, and fixing that might be a better appr=
oach for this particular problem.
>>
>>
>> Can it be fixed without breaking user code?
>
> That's probably hard.
>
> We could have a
>    std::string(int) =3D delete
>
> constructor overload that catches literal "0", but
>
>   std::string(const char *)
>
> is certainly in widespread use.

See
https://groups.google.com/a/isocpp.org/d/msg/std-discussion/ZD0aGGkZjPk/cyo=
ND1x4VfUJ

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

.


Author: David Krauss <potswa@gmail.com>
Date: Sat, 18 Oct 2014 06:12:48 +0800
Raw View
On 2014-10-18, at 3:14 AM, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:

> See
> https://groups.google.com/a/isocpp.org/d/msg/std-discussion/ZD0aGGkZjPk/cyoND1x4VfUJ

Or https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/PGdx39Iy8pg/9FtjaRI-9ZcJ

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.