Topic: std::optional - support for sentinel values
Author: Igor Baidiuk <target.san@gmail.com>
Date: Thu, 29 Jun 2017 02:51:18 -0700 (PDT)
Raw View
------=_Part_3421_1141031328.1498729878056
Content-Type: multipart/alternative;
boundary="----=_Part_3422_1661200324.1498729878057"
------=_Part_3422_1661200324.1498729878057
Content-Type: text/plain; charset="UTF-8"
At the moment, std::optional type, in the way it was accepted by committee,
always has storage block for its value and a flag field, which determines
if actual value is present.
Although, there are often safe wrapper types (like std::reference_wrapper,
or wrapper around OS handle, or a raw pointer) which have kind of
"impossible state" on their own. For such types, it's perfectly possible to
represent std::nullopt state as this "impossible" value:
- Allow to define optional sentinel value for a type. Current approach
in STL seems to be trait struct for the type and trait adaptor used in
std::optional to access values (similar to std::allocator<T> +
std::allocator_traits<Alloc>). There might be a requirement that sentinel
value should be constexpr.
- If type defines sentinel value, then std::optional's nullopt is
represented with that sentinel value, and there's no additional flag
There are several benefits coming with this approach:
- Space efficiency for types with "invalid value"
- Type safety. Sentinel value simply cannot be used the same way as
normal value. Roughly saying, no "null pointer dereference" issue
The other extension, orthogonal to first one, is to allow value to be
stored using alternate representation. As an example, reference type can be
stored as a pointer and simply presented as reference. This will also allow
to have cheap and relatively easy support for storing references in
std::optional, without need of completely separate type specialization.
Any thoughts on this?
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6e23864f-827a-4bdb-89de-a60d8f5be993%40isocpp.org.
------=_Part_3422_1661200324.1498729878057
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">At the moment, std::optional type, in the way it was accep=
ted by committee, always has storage block for its value and a flag field, =
which determines if actual value is present.<br>Although, there are often s=
afe wrapper types (like std::reference_wrapper, or wrapper around OS handle=
, or a raw pointer) which have kind of "impossible state" on thei=
r own. For such types, it's perfectly possible to represent std::nullop=
t state as this "impossible" value:<br><ul><li>Allow to define op=
tional sentinel value for a type. Current approach in STL seems to be trait=
struct for the type and trait adaptor used in std::optional to access valu=
es (similar to std::allocator<T> + std::allocator_traits<Alloc>=
). There might be a requirement that sentinel value should be constexpr.<br=
></li><li>If type defines sentinel value, then std::optional's nullopt =
is represented with that sentinel value, and there's no additional flag=
</li></ul><p>There are several benefits coming with this approach:</p><ul><=
li>Space efficiency for types with "invalid value"</li><li>Type s=
afety. Sentinel value simply cannot be used the same way as normal value. R=
oughly saying, no "null pointer dereference" issue</li></ul><p></=
p><p>The other extension, orthogonal to first one, is to allow value to be =
stored using alternate representation. As an example, reference type can be=
stored as a pointer and simply presented as reference. This will also allo=
w to have cheap and relatively easy support for storing references in std::=
optional, without need of completely separate type specialization.<br></p><=
p><br></p><p>Any thoughts on this?</p><p><br></p><p><br></p></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6e23864f-827a-4bdb-89de-a60d8f5be993%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6e23864f-827a-4bdb-89de-a60d8f5be993=
%40isocpp.org</a>.<br />
------=_Part_3422_1661200324.1498729878057--
------=_Part_3421_1141031328.1498729878056--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Thu, 29 Jun 2017 13:30:28 +0300
Raw View
On 29 June 2017 at 12:51, Igor Baidiuk <target.san@gmail.com> wrote:
> At the moment, std::optional type, in the way it was accepted by committee,
> always has storage block for its value and a flag field, which determines if
> actual value is present.
> Although, there are often safe wrapper types (like std::reference_wrapper,
> or wrapper around OS handle, or a raw pointer) which have kind of
> "impossible state" on their own. For such types, it's perfectly possible to
> represent std::nullopt state as this "impossible" value:
>
> Allow to define optional sentinel value for a type. Current approach in STL
> seems to be trait struct for the type and trait adaptor used in
> std::optional to access values (similar to std::allocator<T> +
> std::allocator_traits<Alloc>). There might be a requirement that sentinel
> value should be constexpr.
> If type defines sentinel value, then std::optional's nullopt is represented
> with that sentinel value, and there's no additional flag
>
> There are several benefits coming with this approach:
>
> Space efficiency for types with "invalid value"
> Type safety. Sentinel value simply cannot be used the same way as normal
> value. Roughly saying, no "null pointer dereference" issue
>
> The other extension, orthogonal to first one, is to allow value to be stored
> using alternate representation. As an example, reference type can be stored
> as a pointer and simply presented as reference. This will also allow to have
> cheap and relatively easy support for storing references in std::optional,
> without need of completely separate type specialization.
>
>
> Any thoughts on this?
That's a type different from optional. And optional-with-sentinel that
considers a certain raw
pointer value to be the sentinel value is not the same thing as an
optional that adds a nullopt
state. The latter can't be made to act like the former the way you
suggest, because once a trait
is present, it can't be removed, or we have an odr violation.
You need a new type.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUbRhek%2Buf3sjX9o8dugGMLbTMxEpLjqB43gEMOhNfirhg%40mail.gmail.com.
.
Author: Igor Baidiuk <target.san@gmail.com>
Date: Thu, 29 Jun 2017 03:47:51 -0700 (PDT)
Raw View
------=_Part_2127_992683124.1498733271198
Content-Type: multipart/alternative;
boundary="----=_Part_2128_1301472801.1498733271198"
------=_Part_2128_1301472801.1498733271198
Content-Type: text/plain; charset="UTF-8"
Okay, this may be a new type. I doubt it'll be possible to alter
std::optional definition, even with default tempate parameter. It's sad
that includes still give us sticks in a wheel.
Although, I think the whole idea is worth discussing, as it allows more
tools for safe programming.
On Thursday, June 29, 2017 at 1:30:31 PM UTC+3, Ville Voutilainen wrote:
>
>
> You need a new type.
>
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9f81f2b9-958c-4018-9f78-a6ac2e425899%40isocpp.org.
------=_Part_2128_1301472801.1498733271198
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Okay, this may be a new type. I doubt it'll be possibl=
e to alter std::optional definition, even with default tempate parameter. I=
t's sad that includes still give us sticks in a wheel.<br>Although, I t=
hink the whole idea is worth discussing, as it allows more tools for safe p=
rogramming.<br><br>On Thursday, June 29, 2017 at 1:30:31 PM UTC+3, Ville Vo=
utilainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><br>You need a=
new type.
<br></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9f81f2b9-958c-4018-9f78-a6ac2e425899%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9f81f2b9-958c-4018-9f78-a6ac2e425899=
%40isocpp.org</a>.<br />
------=_Part_2128_1301472801.1498733271198--
------=_Part_2127_992683124.1498733271198--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Thu, 29 Jun 2017 13:55:53 +0300
Raw View
On 29 June 2017 at 13:47, Igor Baidiuk <target.san@gmail.com> wrote:
> Okay, this may be a new type. I doubt it'll be possible to alter
> std::optional definition, even with default tempate parameter. It's sad that
> includes still give us sticks in a wheel.
It has nothing to do with includes. Altering the definition of
optional to conditionally use
a trait would be remotely feasible, but it would also be an abi-breaking change.
> Although, I think the whole idea is worth discussing, as it allows more
> tools for safe programming.
Sure.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUa6KjAGsdr2-%3D490s%2BRNzYWFF%2B9W%3DFyiU29ScDR%2B2CJrg%40mail.gmail.com.
.
Author: Igor Baidiuk <target.san@gmail.com>
Date: Thu, 29 Jun 2017 04:09:16 -0700 (PDT)
Raw View
------=_Part_3153_349885063.1498734556507
Content-Type: multipart/alternative;
boundary="----=_Part_3154_1588380217.1498734556507"
------=_Part_3154_1588380217.1498734556507
Content-Type: text/plain; charset="UTF-8"
On Thursday, June 29, 2017 at 1:55:56 PM UTC+3, Ville Voutilainen wrote:
>
>
> It has nothing to do with includes. Altering the definition of
> optional to conditionally use
> a trait would be remotely feasible, but it would also be an abi-breaking
> change.
>
>
Maybe I didn't express it well enough. I meant the case when someone
declares such "sentinel" locally for module, and then return that option to
unit where sentinel is not known.
Then I realized this is well-possible even if new optional would have trait
parameter.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/730d0077-5a80-4dce-8250-19be62b1a23b%40isocpp.org.
------=_Part_3154_1588380217.1498734556507
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, June 29, 2017 at 1:55:56 PM UTC+3, Vi=
lle Voutilainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><br>It h=
as nothing to do with includes. Altering the definition of
<br>optional to conditionally use
<br>a trait would be remotely feasible, but it would also be an abi-breakin=
g change.
<br>
<br></blockquote><div><br>Maybe I didn't express it well enough. I mean=
t the case when someone declares such "sentinel" locally for modu=
le, and then return that option to unit where sentinel is not known.<br>The=
n I realized this is well-possible even if new optional would have trait pa=
rameter. <br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/730d0077-5a80-4dce-8250-19be62b1a23b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/730d0077-5a80-4dce-8250-19be62b1a23b=
%40isocpp.org</a>.<br />
------=_Part_3154_1588380217.1498734556507--
------=_Part_3153_349885063.1498734556507--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Thu, 29 Jun 2017 14:13:07 +0300
Raw View
On 29 June 2017 at 14:09, Igor Baidiuk <target.san@gmail.com> wrote:
>> It has nothing to do with includes. Altering the definition of
>> optional to conditionally use
>> a trait would be remotely feasible, but it would also be an abi-breaking
>> change.
>>
>
> Maybe I didn't express it well enough. I meant the case when someone
> declares such "sentinel" locally for module, and then return that option to
> unit where sentinel is not known.
> Then I realized this is well-possible even if new optional would have trait
> parameter.
Right; multiple translation units must agree, which makes it an odr-problem, not
an include-problem. The trait-approach might still work, it just
requires that the trait
gives the same result in every TU, but injecting such a trait-approach
into the current
optional is an abi break.
Going for a separate type is safe from that abi break, which
automatically removes some
automatic opposition from the picture.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUaVNMX9ktdTTTZywzmmOh6zJVShRcnL_ppJeFnFDpm0nw%40mail.gmail.com.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Thu, 29 Jun 2017 07:16:49 -0400
Raw View
std::optional<std::opt_sentineled<int,-1>>
Sent=C2=A0from=C2=A0my=C2=A0BlackBerry=C2=A0portable=C2=A0Babbage=C2=A0Devi=
ce
=C2=A0 Original Message =C2=A0
From: Ville Voutilainen
Sent: Thursday, June 29, 2017 7:13 AM
To: ISO C++ Standard - Future Proposals
Reply To: std-proposals@isocpp.org
Subject: Re: [std-proposals] std::optional - support for sentinel values
On 29 June 2017 at 14:09, Igor Baidiuk <target.san@gmail.com> wrote:
>> It has nothing to do with includes. Altering the definition of
>> optional to conditionally use
>> a trait would be remotely feasible, but it would also be an abi-breaking
>> change.
>>
>
> Maybe I didn't express it well enough. I meant the case when someone
> declares such "sentinel" locally for module, and then return that option =
to
> unit where sentinel is not known.
> Then I realized this is well-possible even if new optional would have tra=
it
> parameter.
Right; multiple translation units must agree, which makes it an odr-problem=
, not
an include-problem. The trait-approach might still work, it just
requires that the trait
gives the same result in every TU, but injecting such a trait-approach
into the current
optional is an abi break.
Going for a separate type is safe from that abi break, which
automatically removes some
automatic opposition from the picture.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAFk2RUaVNMX9ktdTTTZywzmmOh6zJVShRcnL_ppJeFnFDpm=
0nw%40mail.gmail.com.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/20170629111649.5132370.85419.32148%40gmail.com.
.
Author: Igor Baidiuk <target.san@gmail.com>
Date: Thu, 29 Jun 2017 04:50:11 -0700 (PDT)
Raw View
------=_Part_3254_1280160015.1498737011346
Content-Type: multipart/alternative;
boundary="----=_Part_3255_1838034707.1498737011346"
------=_Part_3255_1838034707.1498737011346
Content-Type: text/plain; charset="UTF-8"
If we introduce such "special wrapper", we'll lose in ergonomics, even if
this will save us from ABI breakage.
As for ABI, major compilers like MSVC or GCC do ABI breakage on major
version bump anyway.
Though I'd rather put that particular question aside for now. Let's imagine
we're up to a new type.
On Thursday, June 29, 2017 at 2:16:52 PM UTC+3, Tony V E wrote:
>
> std::optional<std::opt_sentineled<int,-1>>
>
>
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/caf31531-e7f3-4446-93b4-b1dcca612a99%40isocpp.org.
------=_Part_3255_1838034707.1498737011346
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">If we introduce such "special wrapper", we'l=
l lose in ergonomics, even if this will save us from ABI breakage.<br>As fo=
r ABI, major compilers like MSVC or GCC do ABI breakage on major version bu=
mp anyway.<br>Though I'd rather put that particular question aside for =
now. Let's imagine we're up to a new type. <br><br>On Thursday, Jun=
e 29, 2017 at 2:16:52 PM UTC+3, Tony V E wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;">std::optional<std::opt_<wbr>sentineled<int,-1>>=
;
<br>
<br></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/caf31531-e7f3-4446-93b4-b1dcca612a99%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/caf31531-e7f3-4446-93b4-b1dcca612a99=
%40isocpp.org</a>.<br />
------=_Part_3255_1838034707.1498737011346--
------=_Part_3254_1280160015.1498737011346--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Thu, 29 Jun 2017 15:04:32 +0300
Raw View
On 29 June 2017 at 14:50, Igor Baidiuk <target.san@gmail.com> wrote:
> If we introduce such "special wrapper", we'll lose in ergonomics, even if
> this will save us from ABI breakage.
> As for ABI, major compilers like MSVC or GCC do ABI breakage on major
> version bump anyway.
That's becoming less correct for msvc and is not at all correct for libstdc++.
> Though I'd rather put that particular question aside for now. Let's imagine
> we're up to a new type.
The type is certainly useful, because it's more compact than
std::optional is. I think it's worth
having in the standard, but I can imagine some saying "too many types"
without quantifying how
many is too many and what the deciding factor is for that. :)
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUYVCw7dbHThw-X4bRACiNQ6mim8jQWJFEu7U-C7zddgnQ%40mail.gmail.com.
.
Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Thu, 29 Jun 2017 16:05:35 -0700 (PDT)
Raw View
------=_Part_62_495229850.1498777535282
Content-Type: multipart/alternative;
boundary="----=_Part_63_851790441.1498777535282"
------=_Part_63_851790441.1498777535282
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Thursday, June 29, 2017 at 2:51:18 AM UTC-7, Igor Baidiuk wrote:
>
> At the moment, std::optional type, in the way it was accepted by=20
> committee, always has storage block for its value and a flag field, which=
=20
> determines if actual value is present.
> Although, there are often safe wrapper types (like std::reference_wrapper=
,=20
> or wrapper around OS handle, or a raw pointer) which have kind of=20
> "impossible state" on their own. For such types, it's perfectly possible =
to=20
> represent std::nullopt state as this "impossible" value:
>
> - Allow to define optional sentinel value for a type. Current approach=
=20
> in STL seems to be trait struct for the type and trait adaptor used in=
=20
> std::optional to access values (similar to std::allocator<T> +=20
> std::allocator_traits<Alloc>). There might be a requirement that senti=
nel=20
> value should be constexpr.
> - If type defines sentinel value, then std::optional's nullopt is=20
> represented with that sentinel value, and there's no additional flag
>
> There are several benefits coming with this approach:
>
> - Space efficiency for types with "invalid value"
> - Type safety. Sentinel value simply cannot be used the same way as=20
> normal value. Roughly saying, no "null pointer dereference" issue
>
>
Mark Zeren's C++Now talk on strings=20
<https://www.youtube.com/watch?v=3DOMbwbXZWtDM> will be interesting to you.=
=20
Following that talk, I implemented his ideas for a "nullable trait" in my=
=20
"STL From Scratch" under the name std::tombstone_traits<T>.
https://github.com/Quuxplusone/from-scratch/blob/master/include/scratch/bit=
s/traits-classes/tombstone-traits.h
https://github.com/Quuxplusone/from-scratch/blob/master/include/scratch/bit=
s/optional/tombstone-traits.h
https://github.com/Quuxplusone/from-scratch/blob/master/include/scratch/bit=
s/optional/optional-storage.h
However, it hit some obstacles.
Here are the problems with *your* approach:
- Using a sentinel value of the type T is philosophically incorrect w.r.t.=
=20
lifetime management. If I construct a disengaged optional, and then destroy=
=20
it, I *must not* call the destructor of T. If I copy a disengaged optional,=
=20
I *must not* call the copy constructor of T. If you unconditionally=20
construct a T no matter whether the optional is engaged or disengaged, then=
=20
what you have is philosophically not an optional<T>; it is literally a T.=
=20
If that's what you want, just write T.
- Using a sentinel value of type T is technically impossible if the type T=
=20
has no "available" value; for example, bool. However, it is common for=20
there to be "available" *bit-patterns* that are distinguishable from any=20
possible value of T. You raised the example of a reference_wrapper<T> in=
=20
the all-bits-zero state. For another example, there's std::vector in the=
=20
state "ptr=3Dnull, size=3D42, capacity=3D0" =E2=80=94 that's a bit-pattern =
that does not=20
correspond to any value of type std::vector.
- In fact, if you can enumerate the available bit-patterns, you can store a=
=20
*lot* of extra information in the unused bits of a T. My STL uses this fact=
=20
to make sizeof(optional<optional<optional<bool>>>) =3D=3D 1. Your approach=
=20
would be completely unable to optimize this; you'd have to use at least 4=
=20
bytes.
Okay, now for the problems with *my* approach:
- The implementation of tombstone_traits<T> might need to be a friend of T,=
=20
and certainly needs to be kept in sync with the implementation details of=
=20
T, which is too bad, but not fatal.
- Because this approach relies on a kind of type-punning =E2=80=94 a safe k=
ind,=20
AFAIK, but a kind =E2=80=94 therefore it cannot be done constexpr, which me=
ans=20
std::optional<T> is no longer usable in constexpr contexts. IMO this is=20
absolutely fatal for pursuing this approach in the STL. (Unless someone=20
can come up with a way of doing it constexpr that I didn't think of...)
=20
> The other extension, orthogonal to first one, is to allow value to be=20
> stored using alternate representation. As an example, reference type can =
be=20
> stored as a pointer and simply presented as reference. This will also all=
ow=20
> to have cheap and relatively easy support for storing references in=20
> std::optional, without need of completely separate type specialization.
>
This is optional<reference_wrapper<T>>.
As for why optional<T&> is a terrible, horrible, no-good, very bad idea,=20
please see Matt Calabrese's talk=20
<https://www.youtube.com/watch?v=3DhKIYbf1fsLw> from C++Now.
HTH,
Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/c44c5d09-9124-488f-aa92-f9ab59797268%40isocpp.or=
g.
------=_Part_63_851790441.1498777535282
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, June 29, 2017 at 2:51:18 AM UTC-7, Igor Baidi=
uk 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">At t=
he moment, std::optional type, in the way it was accepted by committee, alw=
ays has storage block for its value and a flag field, which determines if a=
ctual value is present.<br>Although, there are often safe wrapper types (li=
ke std::reference_wrapper, or wrapper around OS handle, or a raw pointer) w=
hich have kind of "impossible state" on their own. For such types=
, it's perfectly possible to represent std::nullopt state as this "=
;impossible" value:<br><ul><li>Allow to define optional sentinel value=
for a type. Current approach in STL seems to be trait struct for the type =
and trait adaptor used in std::optional to access values (similar to std::a=
llocator<T> + std::allocator_traits<Alloc>). There might be a r=
equirement that sentinel value should be constexpr.<br></li><li>If type def=
ines sentinel value, then std::optional's nullopt is represented with t=
hat sentinel value, and there's no additional flag</li></ul><p>There ar=
e several benefits coming with this approach:</p><ul><li>Space efficiency f=
or types with "invalid value"</li><li>Type safety. Sentinel value=
simply cannot be used the same way as normal value. Roughly saying, no &qu=
ot;null pointer dereference" issue</li></ul><p></p><p></p></div></bloc=
kquote><div><br></div><div><a href=3D"https://www.youtube.com/watch?v=3DOMb=
wbXZWtDM">Mark Zeren's C++Now talk on strings</a> will be interesting t=
o you. Following that talk, I implemented his ideas for a "nullable tr=
ait" in my "STL From Scratch" under the name std::tombstone_=
traits<T>.</div><div><a href=3D"https://github.com/Quuxplusone/from-s=
cratch/blob/master/include/scratch/bits/traits-classes/tombstone-traits.h">=
https://github.com/Quuxplusone/from-scratch/blob/master/include/scratch/bit=
s/traits-classes/tombstone-traits.h</a><br></div><div><a href=3D"https://gi=
thub.com/Quuxplusone/from-scratch/blob/master/include/scratch/bits/optional=
/tombstone-traits.h">https://github.com/Quuxplusone/from-scratch/blob/maste=
r/include/scratch/bits/optional/tombstone-traits.h</a><br></div><div><a hre=
f=3D"https://github.com/Quuxplusone/from-scratch/blob/master/include/scratc=
h/bits/optional/optional-storage.h">https://github.com/Quuxplusone/from-scr=
atch/blob/master/include/scratch/bits/optional/optional-storage.h</a><br></=
div><div>However, it hit some obstacles.<br></div><div><br></div><div>Here =
are the problems with <i>your</i> approach:</div><div>- Using a sentinel va=
lue of the type T is philosophically incorrect w.r.t. lifetime management. =
If I construct a disengaged optional, and then destroy it, I <i>must not</i=
> call the destructor of T. If I copy a disengaged optional, I <i>must not<=
/i> call the copy constructor of T. If you unconditionally construct a T no=
matter whether the optional is engaged or disengaged, then what you have i=
s philosophically not an optional<T>; it is literally a T. =C2=A0If t=
hat's what you want, just write T.</div><div>- Using a sentinel value o=
f type T is technically impossible if the type T has no "available&quo=
t; value; for example, <font face=3D"courier new, monospace">bool</font>. H=
owever, it is common for there to be "available" <i>bit-patterns<=
/i> that are distinguishable from any possible value of T. =C2=A0You raised=
the example of a reference_wrapper<T> in the all-bits-zero state. =
=C2=A0For another example, there's std::vector in the state "ptr=
=3Dnull, size=3D42, capacity=3D0" =E2=80=94 that's a bit-pattern t=
hat does not correspond to any value of type std::vector.</div><div>- In fa=
ct, if you can enumerate the available bit-patterns, you can store a <i>lot=
</i> of extra information in the unused bits of a T. My STL uses this fact =
to make <font face=3D"courier new, monospace">sizeof(optional<optional&l=
t;optional<bool>>>) =3D=3D 1</font>. Your approach would be com=
pletely unable to optimize this; you'd have to use at least 4 bytes.</d=
iv><div><br></div><div>Okay, now for the problems with <i>my</i> approach:<=
/div><div>- The implementation of tombstone_traits<T> might need to b=
e a friend of T, and certainly needs to be kept in sync with the implementa=
tion details of T, which is too bad, but not fatal.</div><div>- Because thi=
s approach relies on a kind of type-punning =E2=80=94 a safe kind, AFAIK, b=
ut a kind =E2=80=94 therefore it cannot be done constexpr, which means std:=
:optional<T> is no longer usable in constexpr contexts. IMO this is a=
bsolutely fatal for pursuing this approach in the STL. =C2=A0(Unless someon=
e can come up with a way of doing it constexpr that I didn't think of..=
..)</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><p>The other extension, orthogonal to first one,=
is to allow value to be stored using alternate representation. As an examp=
le, reference type can be stored as a pointer and simply presented as refer=
ence. This will also allow to have cheap and relatively easy support for st=
oring references in std::optional, without need of completely separate type=
specialization.<br></p></div></blockquote><div><br></div><div>This is opti=
onal<reference_wrapper<T>>.</div><div>As for why optional<T&=
amp;> is a terrible, horrible, no-good, very bad idea, please see <a hre=
f=3D"https://www.youtube.com/watch?v=3DhKIYbf1fsLw">Matt Calabrese's ta=
lk</a> from C++Now.</div><div><br></div><div>HTH,</div><div>Arthur</div></d=
iv>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/c44c5d09-9124-488f-aa92-f9ab59797268%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c44c5d09-9124-488f-aa92-f9ab59797268=
%40isocpp.org</a>.<br />
------=_Part_63_851790441.1498777535282--
------=_Part_62_495229850.1498777535282--
.
Author: Igor Baidiuk <target.san@gmail.com>
Date: Fri, 30 Jun 2017 07:21:34 -0700 (PDT)
Raw View
------=_Part_354_625237961.1498832495025
Content-Type: multipart/alternative;
boundary="----=_Part_355_431318467.1498832495026"
------=_Part_355_431318467.1498832495026
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'Dwyer wrote:
>
> Mark Zeren's C++Now talk on strings=20
> <https://www.youtube.com/watch?v=3DOMbwbXZWtDM> will be interesting to yo=
u.=20
> Following that talk, I implemented his ideas for a "nullable trait" in my=
=20
> "STL From Scratch" under the name std::tombstone_traits<T>.
>
Thanks, will check it.
=20
> Here are the problems with *your* approach:
> - Using a sentinel value of the type T is philosophically incorrect w.r.t=
..=20
> lifetime management. If I construct a disengaged optional, and then destr=
oy=20
> it, I *must not* call the destructor of T. If I copy a disengaged=20
> optional, I *must not* call the copy constructor of T. If you=20
> unconditionally construct a T no matter whether the optional is engaged o=
r=20
> disengaged, then what you have is philosophically not an optional<T>; it =
is=20
> literally a T. If that's what you want, just write T.
>
I disagree.
Following your thought, C++ is already incorrect w.r.t. lifetimes - some=20
value, which is moved out, is still accessible and requires destructor call=
..
Next, I'm thinking more from correctness and usability points of view.
The values used for sentinels are usually "invalid" type states. The=20
closest example is what remains of value if it's moved out. In such case=20
destructor is trivial.
Next, such "invalid" state simply cannot be used in place of normal value.=
=20
Null pointer cannot be used to access object. In fact, pointers should have=
=20
never been allowed to be dereferenced, from philosophical correctness point=
=20
of view. Typed pointer is kind of abomination - it can be rebound to=20
arbitrary location via simple arithmetic operations, and it can be used to=
=20
access data like reference.
The approach with sentinel values is exactly for this purpose - it allows=
=20
to reuse effective representation (the "free" bits you mention below) and=
=20
provide safe interface to it - there can be normal value, or no sensible=20
value at all.
=20
> - Using a sentinel value of type T is technically impossible if the type =
T=20
> has no "available" value; for example, bool. However, it is common for=20
> there to be "available" *bit-patterns* that are distinguishable from any=
=20
> possible value of T. You raised the example of a reference_wrapper<T> in=
=20
> the all-bits-zero state. For another example, there's std::vector in the=
=20
> state "ptr=3Dnull, size=3D42, capacity=3D0" =E2=80=94 that's a bit-patter=
n that does not=20
> correspond to any value of type std::vector.
>
Of course, sentinel values don't exist for all the types on the table. And=
=20
for vector, which you mention, empty state is perfectly valid - we don't=20
care how it's represented, we simply shouldn't violate its contract.
=20
> - In fact, if you can enumerate the available bit-patterns, you can store=
=20
> a *lot* of extra information in the unused bits of a T. My STL uses this=
=20
> fact to make sizeof(optional<optional<optional<bool>>>) =3D=3D 1. Your=20
> approach would be completely unable to optimize this; you'd have to use a=
t=20
> least 4 bytes.
>
Let's imagine someone tries to take reference to doubly-optional bool from=
=20
your triple-optional bool. And assign it some value. Also note that=20
Some(Some(Some(false))), Some(Some(None)), Some(None) are three different=
=20
state of your triply-optional bool. Even with space compression, you'll=20
need at least 2 bytes.
=20
> =20
>>
>> The other extension, orthogonal to first one, is to allow value to be=20
>> stored using alternate representation. As an example, reference type can=
be=20
>> stored as a pointer and simply presented as reference. This will also al=
low=20
>> to have cheap and relatively easy support for storing references in=20
>> std::optional, without need of completely separate type specialization.
>>
>
> This is optional<reference_wrapper<T>>.
> As for why optional<T&> is a terrible, horrible, no-good, very bad idea,=
=20
> please see Matt Calabrese's talk=20
> <https://www.youtube.com/watch?v=3DhKIYbf1fsLw> from C++Now.
>
This is disputable, true. I just remembered how some folks complained that=
=20
optional<T&> isn't possible.
=20
>
> HTH,
> Arthur
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/c039c5e5-13d0-4052-89f7-b2af50f1e0fc%40isocpp.or=
g.
------=_Part_355_431318467.1498832495026
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'=
;Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<a href=3D"https://www.youtube.com/watch?v=3DOMbwbXZWtDM" target=3D"_blank"=
rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.youtube.com/w=
atch?v\x3dOMbwbXZWtDM';return true;" onclick=3D"this.href=3D'https:=
//www.youtube.com/watch?v\x3dOMbwbXZWtDM';return true;">Mark Zeren'=
s C++Now talk on strings</a> will be interesting to you. Following that tal=
k, I implemented his ideas for a "nullable trait" in my "STL=
From Scratch" under the name std::tombstone_traits<T>.</div></b=
lockquote><div>Thanks, will check it.<br><br>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Here are the problems wit=
h <i>your</i> approach:</div><div>- Using a sentinel value of the type T is=
philosophically incorrect w.r.t. lifetime management. If I construct a dis=
engaged optional, and then destroy it, I <i>must not</i> call the destructo=
r of T. If I copy a disengaged optional, I <i>must not</i> call the copy co=
nstructor of T. If you unconditionally construct a T no matter whether the =
optional is engaged or disengaged, then what you have is philosophically no=
t an optional<T>; it is literally a T. =C2=A0If that's what you w=
ant, just write T.</div></div></blockquote><div><br>I disagree.<br>Followin=
g your thought, C++ is already incorrect w.r.t. lifetimes - some value, whi=
ch is moved out, is still accessible and requires destructor call.<br>Next,=
I'm thinking more from correctness and usability points of view.<br>Th=
e values used for sentinels are usually "invalid" type states. Th=
e closest example is what remains of value if it's moved out. In such c=
ase destructor is trivial.<br>Next, such "invalid" state simply c=
annot be used in place of normal value. Null pointer cannot be used to acce=
ss object. In fact, pointers should have never been allowed to be dereferen=
ced, from philosophical correctness point of view. Typed pointer is kind of=
abomination - it can be rebound to arbitrary location via simple arithmeti=
c operations, and it can be used to access data like reference.<br>The appr=
oach with sentinel values is exactly for this purpose - it allows to reuse =
effective representation (the "free" bits you mention below) and =
provide safe interface to it - there can be normal value, or no sensible va=
lue at all.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><div>- Using a sentinel value of type T is technically imposs=
ible if the type T has no "available" value; for example, <font f=
ace=3D"courier new, monospace">bool</font>. However, it is common for there=
to be "available" <i>bit-patterns</i> that are distinguishable f=
rom any possible value of T. =C2=A0You raised the example of a reference_wr=
apper<T> in the all-bits-zero state. =C2=A0For another example, there=
's std::vector in the state "ptr=3Dnull, size=3D42, capacity=3D0&q=
uot; =E2=80=94 that's a bit-pattern that does not correspond to any val=
ue of type std::vector.</div></div></blockquote><div>Of course, sentinel va=
lues don't exist for all the types on the table. And for vector, which =
you mention, empty state is perfectly valid - we don't care how it'=
s represented, we simply shouldn't violate its contract.<br>=C2=A0</div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>- In fa=
ct, if you can enumerate the available bit-patterns, you can store a <i>lot=
</i> of extra information in the unused bits of a T. My STL uses this fact =
to make <font face=3D"courier new, monospace">sizeof(optional<optional&l=
t;<wbr>optional<bool>>>) =3D=3D 1</font>. Your approach would b=
e completely unable to optimize this; you'd have to use at least 4 byte=
s.</div></div></blockquote><div>Let's imagine someone tries to take ref=
erence to doubly-optional bool from your triple-optional bool. And assign i=
t some value. Also note that Some(Some(Some(false))), Some(Some(None)), Som=
e(None) are three different state of your triply-optional bool. Even with s=
pace compression, you'll need at least 2 bytes.<br>=C2=A0</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=C2=A0<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><p>The other extension, orthogona=
l to first one, is to allow value to be stored using alternate representati=
on. As an example, reference type can be stored as a pointer and simply pre=
sented as reference. This will also allow to have cheap and relatively easy=
support for storing references in std::optional, without need of completel=
y separate type specialization.<br></p></div></blockquote><div><br></div><d=
iv>This is optional<reference_wrapper<T>><wbr>.</div><div>As fo=
r why optional<T&> is a terrible, horrible, no-good, very bad ide=
a, please see <a href=3D"https://www.youtube.com/watch?v=3DhKIYbf1fsLw" tar=
get=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www=
..youtube.com/watch?v\x3dhKIYbf1fsLw';return true;" onclick=3D"this.href=
=3D'https://www.youtube.com/watch?v\x3dhKIYbf1fsLw';return true;">M=
att Calabrese's talk</a> from C++Now.</div></div></blockquote><div>This=
is disputable, true. I just remembered how some folks complained that opti=
onal<T&> isn't possible.<br>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>HTH,</div><div=
>Arthur</div></div></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/c039c5e5-13d0-4052-89f7-b2af50f1e0fc%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c039c5e5-13d0-4052-89f7-b2af50f1e0fc=
%40isocpp.org</a>.<br />
------=_Part_355_431318467.1498832495026--
------=_Part_354_625237961.1498832495025--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 30 Jun 2017 11:44:51 -0400
Raw View
On 2017-06-30 10:21, Igor Baidiuk wrote:
> On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'Dwyer wrote:
>> - In fact, if you can enumerate the available bit-patterns, you can store
>> a *lot* of extra information in the unused bits of a T. My STL uses this
>> fact to make sizeof(optional<optional<optional<bool>>>) == 1. Your
>> approach would be completely unable to optimize this; you'd have to use at
>> least 4 bytes.
>
> Let's imagine someone tries to take reference to doubly-optional bool from
> your triple-optional bool. And assign it some value.
I can imagine ways this can still work. (The complexity will depend on
what happens when you assign `true` to the inner-most `bool`, i.e. if it
stores 1 (0x1) or -1 (0xff).)
> Also note that
> Some(Some(Some(false))), Some(Some(None)), Some(None) are three different
> state of your triply-optional bool. Even with space compression, you'll
> need at least 2 bytes.
Er... why?
An `optional<T>` needs `bitsof(T)+1` bits of storage. A `bool` has two
legal states, so `bitsof(bool) == 1`. Thus, an `optional<bool>` needs 2
bits of storage.
Applying this recursively:
bitsof(optional<bool>) == 2
bitsof(optional<optional<bool>>) == 3
bitsof(optional<optional<optional<bool>>>) == 4
Last I checked, there are (probably / at least) 8 bits in a byte. I
hardly need *16* bits to store optional^3<bool>. In fact, I could
(theoretically) store up to optional^7<bool> in *one* byte.
--
Matthew
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0dd0a5ae-5fc2-020f-73a9-f5c7959fed0f%40gmail.com.
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Fri, 30 Jun 2017 09:49:54 -0700
Raw View
--f403045c0cb4eaae420553303448
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Fri, Jun 30, 2017 at 8:44 AM, Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 2017-06-30 10:21, Igor Baidiuk wrote:
> > On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'Dwyer wrote:
> >> - In fact, if you can enumerate the available bit-patterns, you can
> store
> >> a *lot* of extra information in the unused bits of a T. My STL uses th=
is
> >> fact to make sizeof(optional<optional<optional<bool>>>) =3D=3D 1. Your
> >> approach would be completely unable to optimize this; you'd have to us=
e
> at
> >> least 4 bytes.
> >
> > Let's imagine someone tries to take reference to doubly-optional bool
> from
> > your triple-optional bool. And assign it some value.
>
> I can imagine ways this can still work. (The complexity will depend on
> what happens when you assign `true` to the inner-most `bool`, i.e. if it
> stores 1 (0x1) or -1 (0xff).)
>
Correct; and you mean "complexity" in the lines-of-code sense, not in the
big-O sense, just so we're all on the same page. :)
My tombstone_traits doesn't care what the value-carrying representations
are; all it needs to know is how many *non-*value-carrying representations
it has to play with.
> > Also note that
> > Some(Some(Some(false))), Some(Some(None)), Some(None) are three differe=
nt
> > state of your triply-optional bool. Even with space compression, you'll
> > need at least 2 bytes.
>
> Er... why?
>
> An `optional<T>` needs `bitsof(T)+1` bits of storage. A `bool` has two
> legal states, so `bitsof(bool) =3D=3D 1`. Thus, an `optional<bool>` needs=
2
> bits of storage.
>
> Applying this recursively:
>
> bitsof(optional<bool>) =3D=3D 2
> bitsof(optional<optional<bool>>) =3D=3D 3
> bitsof(optional<optional<optional<bool>>>) =3D=3D 4
>
You can do better (and I do).
With a single byte, we have 256 representations to play with.
2 of those representations are value-carrying: 0x00 means "false" and 0x01
means "true". (If you let "true" be represented by 0xff, that's also fine;
nothing changes.) So that leaves representations 0x02 through 0xFF
available for tombstones.
My std::optional<T> asks std::tombstone_traits<T> for the count of
available tombstone representations. If T is int, then
tombstone_traits<int>::spare_representations =3D=3D 0, and so
std::optional<int> will be composed of an int and a bool.
If T is bool, then tombstone_traits<int>::spare_representations =3D=3D 254,=
and
so std::optional<bool> will be composed of a single bool (which may or may
not be constructed). Iff the optional is engaged, the contained bool's
representation will be 0x00 or 0x01. Iff the optional is disengaged, the
contained bool's representation (which is not a value-carrying
representation) will be 0x02. Representations 0x03 through 0xFF remain
"spare", and this is reflected in
std::tombstone_traits<std::optional<bool>>.
So now consider std::optional<std::optional<bool>>. That's
std::optional<U> where std::tombstone_traits<U>::spare_representations =3D=
=3D
253. And so again, std::optional<std::optional<bool>> will be composed of
a single std::optional<bool> (that is, represented by a single byte) (which
may or may not be constructed). Iff the inner optional<bool> is engaged,
the bool's representation will be 0x00 or 0x01. Iff the inner
optional<bool> is disengaged, the bool's representation will be 0x02. And
otherwise the inner optional<bool> must not exist, which is to say, the
outer optional<bool> must be disengaged; we borrow representation 0x03 for
*that*. Representations 0x04 through 0xFF remain "spare", and this is
reflected in std::tombstone_traits<std::optional<std::optional<bool>>>.
This all works, btw; you can clone my from-scratch repo and play with it if
you want. The fatal problem with it is that optional<T> becomes
non-constexpr.
> Last I checked, there are (probably / at least) 8 bits in a byte. I
> hardly need *16* bits to store optional^3<bool>. In fact, I could
> (theoretically) store up to optional^7<bool> in *one* byte.
>
Try optional^254<bool>. :)
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0%2BUJ0TZooo2NTkDXU2Y0goG30HOrcnLwB8FWoQ7z=
QpeYw%40mail.gmail.com.
--f403045c0cb4eaae420553303448
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Fri, Jun 30, 2017 at 8:44 AM, Matthew Woehlke <span dir=
=3D"ltr"><<a href=3D"mailto:mwoehlke.floss@gmail.com" target=3D"_blank">=
mwoehlke.floss@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra=
"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,2=
04);border-left-style:solid;padding-left:1ex"><span class=3D"gmail-">On 201=
7-06-30 10:21, Igor Baidiuk wrote:<br>
> On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'Dwyer wrote=
:<br>
</span><span class=3D"gmail-">>> - In fact, if you can enumerate the =
available bit-patterns, you can store<br>
</span>>> a *lot* of extra information in the unused bits of a T. My =
STL uses this<br>
<span class=3D"gmail-">>> fact to make sizeof(optional<optional<=
;<wbr>optional<bool>>>) =3D=3D 1. Your<br>
>> approach would be completely unable to optimize this; you'd ha=
ve to use at<br>
>> least 4 bytes.<br>
><br>
> Let's imagine someone tries to take reference to doubly-optional b=
ool from<br>
> your triple-optional bool. And assign it some value.<br>
<br>
</span>I can imagine ways this can still work. (The complexity will depend =
on<br>
what happens when you assign `true` to the inner-most `bool`, i.e. if it<br=
>
stores 1 (0x1) or -1 (0xff).)<br></blockquote><div><br></div><div>Correct; =
and you mean "complexity" in the lines-of-code sense, not in the =
big-O sense, just so we're all on the same page. :)</div><div>My tombst=
one_traits doesn't care what the value-carrying representations are; al=
l it needs to know is how many <i>non-</i>value-carrying representations it=
has to play with.</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:r=
gb(204,204,204);border-left-style:solid;padding-left:1ex"><span class=3D"gm=
ail-">> Also note that<br>
> Some(Some(Some(false))), Some(Some(None)), Some(None) are three differ=
ent<br>
> state of your triply-optional bool. Even with space compression, you&#=
39;ll<br>
> need at least 2 bytes.<br>
<br>
</span>Er... why?<br>
<br>
An `optional<T>` needs `bitsof(T)+1` bits of storage. A `bool` has tw=
o<br>
legal states, so `bitsof(bool) =3D=3D 1`. Thus, an `optional<bool>` n=
eeds 2<br>
bits of storage.<br>
<br>
Applying this recursively:<br>
<br>
=C2=A0 bitsof(optional<bool>) =3D=3D 2<br>
=C2=A0 bitsof(optional<optional<bool><wbr>>) =3D=3D 3<br>
=C2=A0 bitsof(optional<optional<<wbr>optional<bool>>>) =
=3D=3D 4<br></blockquote><div><br></div><div>You can do better (and I do).<=
/div><div>With a single byte, we have 256 representations to play with.</di=
v><div>2 of those representations are value-carrying: 0x00 means "fals=
e" and 0x01 means "true". =C2=A0(If you let "true"=
be represented by 0xff, that's also fine; nothing changes.) =C2=A0So t=
hat leaves representations 0x02 through 0xFF available for tombstones.</div=
><div><br></div><div>My std::optional<T> asks std::tombstone_traits&l=
t;T> for the count of available tombstone representations. If T is int, =
then tombstone_traits<int>::spare_representations =3D=3D 0, and so st=
d::optional<int> will be composed of an int and a bool.</div><div><br=
></div><div>If T is bool, then tombstone_traits<int>::spare_represent=
ations =3D=3D 254, and so std::optional<bool> will be composed of a s=
ingle bool (which may or may not be constructed). Iff the optional is engag=
ed, the contained bool's representation will be 0x00 or 0x01. Iff the o=
ptional is disengaged, the contained bool's representation (which is no=
t a value-carrying representation) will be 0x02.=C2=A0 Representations 0x03=
through 0xFF remain "spare", and this is reflected in std::tombs=
tone_traits<std::optional<bool>>.</div><div><br></div><div>So n=
ow consider std::optional<std::optional<bool>>.=C2=A0 That'=
s std::optional<U> where std::tombstone_traits<U>::spare_repres=
entations =3D=3D 253.=C2=A0 And so again, std::optional<std::optional<=
;bool>> will be composed of a single std::optional<bool> (that =
is, represented by a single byte) (which may or may not be constructed). If=
f the inner optional<bool> is engaged, the bool's representation =
will be 0x00 or 0x01. Iff the inner optional<bool> is disengaged, the=
bool's representation will be 0x02. And otherwise the inner optional&l=
t;bool> must not exist, which is to say, the outer optional<bool> =
must be disengaged; we borrow representation 0x03 for <i>that</i>.=C2=A0 Re=
presentations 0x04 through 0xFF remain "spare", and this is refle=
cted in std::tombstone_traits<std::optional<std::optional<bool>=
>>.</div><div><br></div><div>This all works, btw; you can clone my fr=
om-scratch repo and play with it if you want.=C2=A0 The fatal problem with =
it is that optional<T> becomes non-constexpr.</div><div><br></div><di=
v>=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">Last I checked, there are (probably / at lea=
st) 8 bits in a byte. I<br>
hardly need *16* bits to store optional^3<bool>. In fact, I could<br>
(theoretically) store up to optional^7<bool> in *one* byte.<br></bloc=
kquote><div><br></div><div>Try optional^254<bool>. :)</div><div><br><=
/div><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2BUJ0TZooo2NTkDXU2Y0goG30HOrc=
nLwB8FWoQ7zQpeYw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2BUJ0TZ=
ooo2NTkDXU2Y0goG30HOrcnLwB8FWoQ7zQpeYw%40mail.gmail.com</a>.<br />
--f403045c0cb4eaae420553303448--
.
Author: inkwizytoryankes@gmail.com
Date: Fri, 30 Jun 2017 10:24:04 -0700 (PDT)
Raw View
------=_Part_468_1176146734.1498843444502
Content-Type: multipart/alternative;
boundary="----=_Part_469_1199741472.1498843444502"
------=_Part_469_1199741472.1498843444502
Content-Type: text/plain; charset="UTF-8"
On Friday, June 30, 2017 at 5:44:57 PM UTC+2, Matthew Woehlke wrote:
>
> On 2017-06-30 10:21, Igor Baidiuk wrote:
> > On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'Dwyer wrote:
> >> - In fact, if you can enumerate the available bit-patterns, you can
> store
> >> a *lot* of extra information in the unused bits of a T. My STL uses
> this
> >> fact to make sizeof(optional<optional<optional<bool>>>) == 1. Your
> >> approach would be completely unable to optimize this; you'd have to use
> at
> >> least 4 bytes.
> >
> > Let's imagine someone tries to take reference to doubly-optional bool
> from
> > your triple-optional bool. And assign it some value.
>
> I can imagine ways this can still work. (The complexity will depend on
> what happens when you assign `true` to the inner-most `bool`, i.e. if it
> stores 1 (0x1) or -1 (0xff).)
>
> > Also note that
> > Some(Some(Some(false))), Some(Some(None)), Some(None) are three
> different
> > state of your triply-optional bool. Even with space compression, you'll
> > need at least 2 bytes.
>
> Er... why?
>
> An `optional<T>` needs `bitsof(T)+1` bits of storage. A `bool` has two
> legal states, so `bitsof(bool) == 1`. Thus, an `optional<bool>` needs 2
> bits of storage.
>
> Applying this recursively:
>
> bitsof(optional<bool>) == 2
> bitsof(optional<optional<bool>>) == 3
> bitsof(optional<optional<optional<bool>>>) == 4
>
> Last I checked, there are (probably / at least) 8 bits in a byte. I
> hardly need *16* bits to store optional^3<bool>. In fact, I could
> (theoretically) store up to optional^7<bool> in *one* byte.
>
> --
> Matthew
>
16 because you need full byte object in optional otherwise you will get
`std::vector<bool>` mk2.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cebea1ab-9c29-4c7d-acea-9d3ff6b4062c%40isocpp.org.
------=_Part_469_1199741472.1498843444502
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, June 30, 2017 at 5:44:57 PM UTC+2, Matt=
hew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2017-06-3=
0 10:21, Igor Baidiuk wrote:
<br>> On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'Dwyer w=
rote:
<br>>> - In fact, if you can enumerate the available bit-patterns, yo=
u can store=20
<br>>> a *lot* of extra information in the unused bits of a T. My STL=
uses this=20
<br>>> fact to make sizeof(optional<optional<<wbr>optional<b=
ool>>>) =3D=3D 1. Your=20
<br>>> approach would be completely unable to optimize this; you'=
d have to use at=20
<br>>> least 4 bytes.
<br>>
<br>> Let's imagine someone tries to take reference to doubly-option=
al bool from=20
<br>> your triple-optional bool. And assign it some value.
<br>
<br>I can imagine ways this can still work. (The complexity will depend on
<br>what happens when you assign `true` to the inner-most `bool`, i.e. if i=
t
<br>stores 1 (0x1) or -1 (0xff).)
<br>
<br>> Also note that=20
<br>> Some(Some(Some(false))), Some(Some(None)), Some(None) are three di=
fferent=20
<br>> state of your triply-optional bool. Even with space compression, y=
ou'll=20
<br>> need at least 2 bytes.
<br>
<br>Er... why?
<br>
<br>An `optional<T>` needs `bitsof(T)+1` bits of storage. A `bool` ha=
s two
<br>legal states, so `bitsof(bool) =3D=3D 1`. Thus, an `optional<bool>=
;` needs 2
<br>bits of storage.
<br>
<br>Applying this recursively:
<br>
<br>=C2=A0 bitsof(optional<bool>) =3D=3D 2
<br>=C2=A0 bitsof(optional<optional<bool><wbr>>) =3D=3D 3
<br>=C2=A0 bitsof(optional<optional<<wbr>optional<bool>>>=
) =3D=3D 4
<br>
<br>Last I checked, there are (probably / at least) 8 bits in a byte. I
<br>hardly need *16* bits to store optional^3<bool>. In fact, I could
<br>(theoretically) store up to optional^7<bool> in *one* byte.
<br>
<br>--=20
<br>Matthew
<br></blockquote><div><br>16 because you need full byte object in optional =
otherwise you will get `std::vector<bool>` mk2.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/cebea1ab-9c29-4c7d-acea-9d3ff6b4062c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cebea1ab-9c29-4c7d-acea-9d3ff6b4062c=
%40isocpp.org</a>.<br />
------=_Part_469_1199741472.1498843444502--
------=_Part_468_1176146734.1498843444502--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Fri, 30 Jun 2017 10:24:28 -0700
Raw View
--94eb2c0de4748b8b39055330b0e7
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Fri, Jun 30, 2017 at 7:21 AM, Igor Baidiuk <target.san@gmail.com> wrote:
> On Friday, June 30, 2017 at 2:05:35 AM UTC+3, Arthur O'Dwyer wrote:
>>
>> Mark Zeren's C++Now talk on strings
>> <https://www.youtube.com/watch?v=3DOMbwbXZWtDM> will be interesting to
>> you. Following that talk, I implemented his ideas for a "nullable trait"=
in
>> my "STL From Scratch" under the name std::tombstone_traits<T>.
>>
> Thanks, will check it.
>
>
>
>> Here are the problems with *your* approach:
>> - Using a sentinel value of the type T is philosophically incorrect
>> w.r.t. lifetime management. If I construct a disengaged optional, and th=
en
>> destroy it, I *must not* call the destructor of T. If I copy a
>> disengaged optional, I *must not* call the copy constructor of T. If you
>> unconditionally construct a T no matter whether the optional is engaged =
or
>> disengaged, then what you have is philosophically not an optional<T>; it=
is
>> literally a T. If that's what you want, just write T.
>>
>
> I disagree.
> Following your thought, C++ is already incorrect w.r.t. lifetimes - some
> value, which is moved out, is still accessible and requires destructor ca=
ll.
>
Nope. An object of type T, even in a "moved-from state", still has a value
of type T. That value might be unspecified; it might even have unusual
restrictions on what you can do with it (although this is exceedingly
rare); the most common case is that the object's value is some variety of
"trivial value" (e.g. the empty std::string) or some variety of "empty
value" (e.g. a std::future which is not valid(), or a std::function whose
target_type() is typeid(void)).
The way you can tell that the object still has a value (and therefore is
still of type T) is that you're required to call the destructor ~T() on it
(usually implicitly). Every object of type T must be destroyed by calling
its destructor; and vice versa, you're only ever allowed to call ~T() on an
object that really *is* of type T.
> Next, I'm thinking more from correctness and usability points of view.
> The values used for sentinels are usually "invalid" type states. The
> closest example is what remains of value if it's moved out. In such case
> destructor is trivial.
>
Well, that's just false. Go look at the destructor of std::unique_lock
sometime, or std::future, or std::string, or std::shared_ptr. What happens
if you move-out-of such an object? Does its destructor magically become
trivial?
> Next, such "invalid" state simply cannot be used in place of normal value=
..
> Null pointer cannot be used to access object. In fact, pointers should ha=
ve
> never been allowed to be dereferenced, from philosophical correctness poi=
nt
> of view. Typed pointer is kind of abomination - it can be rebound to
> arbitrary location via simple arithmetic operations, and it can be used t=
o
> access data like reference.
>
Here, I agree with you. Nullable pointers *are* the "billion-dollar
mistake". And C++ gives us-the-user the power to correct that mistake!
Let's make a non-nullable pointer type:
class int_ptr {
int *p_;
public:
int_ptr() =3D delete;
int_ptr(int *p) { REQUIRE(p); p_ =3D p; ASSERT(p_); }
int_ptr(const int_ptr& rhs) { ASSERT(rhs.p_); p_ =3D rhs.p_; }
int_ptr& operator=3D(const int_ptr& rhs) { ASSERT(p_ && rhs.p_); p_ =3D
rhs.p_; }
~int_ptr() { ASSERT(p_); }
int& operator*() const noexcept { return *p_; }
};
The copy operations and deleted zero-argument constructor are technically
unnecessary, but I put them in so that we'd be able to talk sensibly about
the invariants of this class type.
I claim that the invariant of this type is "It is never NULL, and therefore
it is always safe to dereference with operator*()." We have one "narrow
contract" entrypoint that checks its arguments and throws (via the REQUIRE
macro) if there's no way to build a legal (invariant-satisfying) int_ptr
value out of those arguments.
Okay. So now I have a non-nullable pointer type where NULL is actually
excluded from the domain of values of this type.
*Show me how you'd build a space-efficient std::optional<int_ptr> using
your mechanism.* I claim that you won't be able to do it, because, again, =
*by
definition*, every legal value of int_ptr is a legal value of int_ptr.
You're never going to find a legal value of int_ptr that is "available" for
your use, just like you couldn't find one for bool. A type always totally
covers its domain, by definition: The domain of a type *is the set of all
possible values* of that type.
Similarly, I claim that if you tried to build a std::optional<int *> =E2=80=
=94 an
optional that could hold a nullable pointer or else be disengaged =E2=80=94=
using
your mechanism, you'd find it impossible to distinguish between
std::optional<int*> o1 =3D std::nullopt; // this optional is disengage=
d
std::optional<int*> o2 =3D nullptr; // this optional is engaged, and
holds a nullable pointer with value NULL
If that's true, then what you've built isn't optional<int*>, because it
can't hold "a nullable pointer *or* disengaged." What you've built is
equivalent to either optional<int_ptr> (because it can hold "a non-nullable
pointer *or* disengaged") or simply int* (because it can hold "a
non-nullable pointer *or* null", which is to say, it can hold "a nullable
pointer"). This is why I said in my original response:=E2=80=94 If you mea=
n "T",
just *say* "T". Don't use the phrase "optional<T>" to mean "T"; that's just
going to confuse people.
I've addressed your comments about tombstone_traits in my response to
Matthew Woehlke. Hopefully that will help you see how it's implemented. The
code is still available too.
<https://github.com/Quuxplusone/from-scratch/commit/36110e4be4fac79d5e6f90e=
4bf3f8057bcbe2cab>
:)
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0KjALZ7qeXqLxrdL_Kf2tc460noqLZ3feosCvdELsz=
_bQ%40mail.gmail.com.
--94eb2c0de4748b8b39055330b0e7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Fri, Jun 30, 2017 at 7:21 AM, Igor Baidiuk <span dir=3D=
"ltr"><<a href=3D"mailto:target.san@gmail.com" target=3D"_blank">target.=
san@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div clas=
s=3D"gmail_quote"><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"><div dir=3D"ltr">On Friday, June 30, 201=
7 at 2:05:35 AM UTC+3, Arthur O'Dwyer wrote:<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"><div dir=
=3D"ltr"><a href=3D"https://www.youtube.com/watch?v=3DOMbwbXZWtDM" rel=3D"n=
ofollow" target=3D"_blank">Mark Zeren's C++Now talk on strings</a> will=
be interesting to you. Following that talk, I implemented his ideas for a =
"nullable trait" in my "STL From Scratch" under the nam=
e std::tombstone_traits<T>.</div></blockquote><div>Thanks, will check=
it.<br><br>=C2=A0</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"><div dir=3D"ltr"><div>Here are the=
problems with <i>your</i> approach:</div><div>- Using a sentinel value of =
the type T is philosophically incorrect w.r.t. lifetime management. If I co=
nstruct a disengaged optional, and then destroy it, I <i>must not</i> call =
the destructor of T. If I copy a disengaged optional, I <i>must not</i> cal=
l the copy constructor of T. If you unconditionally construct a T no matter=
whether the optional is engaged or disengaged, then what you have is philo=
sophically not an optional<T>; it is literally a T.=C2=A0 If that'=
;s what you want, just write T.</div></div></blockquote><div><br>I disagree=
..<br>Following your thought, C++ is already incorrect w.r.t. lifetimes - so=
me value, which is moved out, is still accessible and requires destructor c=
all.<br></div></div></blockquote><div><br></div><div>Nope.=C2=A0 An object =
of type T, even in a "moved-from state", still has a value of typ=
e T.=C2=A0 That value might be unspecified; it might even have unusual rest=
rictions on what you can do with it (although this is exceedingly rare); th=
e most common case is that the object's value is some variety of "=
trivial value" (e.g. the empty std::string) or some variety of "e=
mpty value" (e.g. a std::future which is not valid(), or a std::functi=
on whose target_type() is typeid(void)).</div><div><br></div><div>The way y=
ou can tell that the object still has a value (and therefore is still of ty=
pe T) is that you're required to call the destructor ~T() on it (usuall=
y implicitly). Every object of type T must be destroyed by calling its dest=
ructor; and vice versa, you're only ever allowed to call ~T() on an obj=
ect that really <i>is</i> of type T.</div><div><br></div><div>=C2=A0<br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:soli=
d;padding-left:1ex"><div dir=3D"ltr"><div>Next, I'm thinking more from =
correctness and usability points of view.<br>The values used for sentinels =
are usually "invalid" type states. The closest example is what re=
mains of value if it's moved out. In such case destructor is trivial.<b=
r></div></div></blockquote><div><br></div><div>Well, that's just false.=
Go look at the destructor of std::unique_lock sometime, or std::future, or=
std::string, or std::shared_ptr. What happens if you move-out-of such an o=
bject? Does its destructor magically become trivial?</div><div><br></div><d=
iv>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>Next, such "inva=
lid" state simply cannot be used in place of normal value. Null pointe=
r cannot be used to access object. In fact, pointers should have never been=
allowed to be dereferenced, from philosophical correctness point of view. =
Typed pointer is kind of abomination - it can be rebound to arbitrary locat=
ion via simple arithmetic operations, and it can be used to access data lik=
e reference.<br></div></div></blockquote><div><br></div><div>Here, I agree =
with you.=C2=A0 Nullable pointers <i>are</i> the "billion-dollar mista=
ke".=C2=A0 And C++ gives us-the-user the power to correct that mistake=
!=C2=A0 Let's make a non-nullable pointer type:</div><div><br></div><di=
v>class int_ptr {<br></div><div>=C2=A0 =C2=A0 int *p_;</div><div>public:</d=
iv><div>=C2=A0 =C2=A0 int_ptr() =3D delete;</div><div>=C2=A0 =C2=A0 int_ptr=
(int *p) { REQUIRE(p); p_ =3D p; ASSERT(p_); }</div><div>=C2=A0 =C2=A0 int_=
ptr(const int_ptr& rhs) { ASSERT(rhs.p_); p_ =3D rhs.p_; }</div><div>=
=C2=A0 =C2=A0 int_ptr& operator=3D(const int_ptr& rhs) { ASSERT(p_ =
&& rhs.p_); p_ =3D rhs.p_; }</div><div>=C2=A0 =C2=A0 ~int_ptr() { A=
SSERT(p_); }</div><div>=C2=A0 =C2=A0 int& operator*() const noexcept { =
return *p_; }</div><div>};</div><div><br></div><div>The copy operations and=
deleted zero-argument constructor are technically unnecessary, but I put t=
hem in so that we'd be able to talk sensibly about the invariants of th=
is class type.</div><div>I claim that the invariant of this type is "I=
t is never NULL, and therefore it is always safe to dereference with operat=
or*()." =C2=A0We have one "narrow contract" entrypoint that =
checks its arguments and throws (via the REQUIRE macro) if there's no w=
ay to build a legal (invariant-satisfying) int_ptr value out of those argum=
ents.</div><div>Okay. So now I have a non-nullable pointer type where NULL =
is actually excluded from the domain of values of this type.</div><div><br>=
</div><div><b>Show me how you'd build a space-efficient std::optional&l=
t;int_ptr> using your mechanism.</b> =C2=A0I claim that you won't be=
able to do it, because, again, <i>by definition</i>, every legal value of =
int_ptr is a legal value of int_ptr. You're never going to find a legal=
value of int_ptr that is "available" for your use, just like you=
couldn't find one for bool.=C2=A0 A type always totally covers its dom=
ain, by definition: The domain of a type <i>is the set of all possible valu=
es</i> of that type.</div><div><br></div><div>Similarly, I claim that if yo=
u tried to build a std::optional<int *> =E2=80=94 an optional that co=
uld hold a nullable pointer or else be disengaged =E2=80=94 using your mech=
anism, you'd find it impossible to distinguish between</div><div><br></=
div><div>=C2=A0 =C2=A0 std::optional<int*> o1 =3D std::nullopt; =C2=
=A0// this optional is disengaged</div><div><div>=C2=A0 =C2=A0 std::optiona=
l<int*> o2 =3D nullptr; =C2=A0// this optional is engaged, and holds =
a nullable pointer with value NULL</div></div><div><br></div><div>If that&#=
39;s true, then what you've built isn't optional<int*>, becau=
se it can't hold "a nullable pointer=C2=A0<i>or</i> disengaged.&qu=
ot; What you've built is equivalent to either optional<int_ptr> (=
because it can hold "a non-nullable pointer <i>or</i> disengaged"=
) or simply int* (because it can hold "a non-nullable pointer <i>or</i=
> null", which is to say, it can hold "a nullable pointer").=
=C2=A0 This is why I said in my original response:=E2=80=94 If you mean &qu=
ot;T", just <i>say</i>=C2=A0"T". Don't use the phrase &q=
uot;optional<T>" to mean "T"; that's just going to=
confuse people.</div><div><br></div><div>I've addressed your comments =
about tombstone_traits in my response to Matthew Woehlke. Hopefully that wi=
ll help you see how it's implemented. <a href=3D"https://github.com/Quu=
xplusone/from-scratch/commit/36110e4be4fac79d5e6f90e4bf3f8057bcbe2cab">The =
code is still available too.</a> :)</div><div><br></div><div>=E2=80=93Arthu=
r</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0KjALZ7qeXqLxrdL_Kf2tc460noqLZ3=
feosCvdELsz_bQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0KjALZ7qeXq=
LxrdL_Kf2tc460noqLZ3feosCvdELsz_bQ%40mail.gmail.com</a>.<br />
--94eb2c0de4748b8b39055330b0e7--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Fri, 30 Jun 2017 10:32:01 -0700
Raw View
--94eb2c1cca7887ffe8055330cb00
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Fri, Jun 30, 2017 at 10:24 AM, <inkwizytoryankes@gmail.com> wrote:
>
> 16 because you need full byte object in optional otherwise you will get
> `std::vector<bool>` mk2.
>
I hate vector<bool> as much as you do, I promise. :) The analogy doesn't
work here. vector<bool> is terrible because it *purports* to expose
accessors returning bool& but its in-memory representation doesn't contain
a full-byte bool anywhere, so it has to cheat and use proxy iterators and
just generally mess things up.
In the case of std::optional<std::optional<bool>>, it purports to expose
accessors returning bool& *if and only if* both the outer and inner
optionals are engaged. When either optional is disengaged, the bool member
does not exist and therefore there is no need to keep it around in memory
(in fact, we are required by the Standard to destroy it[1]). Which means
that we have a whole unused byte to play around with. We just need to make
sure that when the optionals *are* engaged, the bool really truly exists =
=E2=80=94
and I do make sure of that.
Notice that I left out the case where "both optionals are disengaged."
That's because no such state exists. When the outer optional is
disengaged, *there
is no inner optional* =E2=80=94 the inner optional is not in any state at a=
ll =E2=80=94 it
has been destroyed, and will not reappear until you engage the outer
optional again.
*An optional<T> which is disengaged does not hold a T.*
=E2=80=93Arthur
[1] modulo the as-if rule
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0JfnhrRMS1VM1MGz73kgrYRHoRdG_%3DT6N9Z%2Boh=
BSoD5%3Dw%40mail.gmail.com.
--94eb2c1cca7887ffe8055330cb00
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Fri, Jun 30, 2017 at 10:24 AM, <span dir=3D"ltr"><<=
a href=3D"mailto:inkwizytoryankes@gmail.com" target=3D"_blank">inkwizytorya=
nkes@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><di=
v class=3D"h5"><br></div></div><div>16 because you need full byte object in=
optional otherwise you will get `std::vector<bool>` mk2.<br></div></=
div></blockquote><div><br></div><div>I hate vector<bool> as much as y=
ou do, I promise. :) =C2=A0The analogy doesn't work here. vector<boo=
l> is terrible because it <i>purports</i> to expose accessors returning =
bool& but its in-memory representation doesn't contain a full-byte =
bool anywhere, so it has to cheat and use proxy iterators and just generall=
y mess things up.</div><div><br></div><div>In the case of std::optional<=
std::optional<bool>>, it purports to expose accessors returning bo=
ol& <i><b>if and only if</b></i> both the outer and inner optionals are=
engaged. When either optional is disengaged, the bool member does not exis=
t and therefore there is no need to keep it around in memory (in fact, we a=
re required by the Standard to destroy it[1]). Which means that we have a w=
hole unused byte to play around with. We just need to make sure that when t=
he optionals <i>are</i> engaged, the bool really truly exists =E2=80=94 and=
I do make sure of that.</div><div><br></div><div>Notice that I left out th=
e case where "both optionals are disengaged." That's because =
no such state exists. When the outer optional is disengaged, <i>there is no=
inner optional</i> =E2=80=94 the inner optional is not in any state at all=
=E2=80=94 it has been destroyed, and will not reappear until you engage th=
e outer optional again.</div><div><br></div><div><b>An optional<T> wh=
ich is disengaged does not hold a T.</b></div><div><br></div><div>=E2=80=93=
Arthur</div><div><br></div><div>[1] modulo the as-if rule</div><div><br></d=
iv></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0JfnhrRMS1VM1MGz73kgrYRHoRdG_%3=
DT6N9Z%2BohBSoD5%3Dw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0Jfnh=
rRMS1VM1MGz73kgrYRHoRdG_%3DT6N9Z%2BohBSoD5%3Dw%40mail.gmail.com</a>.<br />
--94eb2c1cca7887ffe8055330cb00--
.
Author: inkwizytoryankes@gmail.com
Date: Fri, 30 Jun 2017 11:03:31 -0700 (PDT)
Raw View
------=_Part_549_836996001.1498845811432
Content-Type: multipart/alternative;
boundary="----=_Part_550_1825476278.1498845811432"
------=_Part_550_1825476278.1498845811432
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Friday, June 30, 2017 at 7:32:03 PM UTC+2, Arthur O'Dwyer wrote:
>
> On Fri, Jun 30, 2017 at 10:24 AM, <inkwizyt...@gmail.com <javascript:>>=
=20
> wrote:
>
>>
>> 16 because you need full byte object in optional otherwise you will get=
=20
>> `std::vector<bool>` mk2.
>>
>
> I hate vector<bool> as much as you do, I promise. :) The analogy doesn't=
=20
> work here. vector<bool> is terrible because it *purports* to expose=20
> accessors returning bool& but its in-memory representation doesn't contai=
n=20
> a full-byte bool anywhere, so it has to cheat and use proxy iterators and=
=20
> just generally mess things up.
>
> In the case of std::optional<std::optional<bool>>, it purports to expose=
=20
> accessors returning bool& *if and only if* both the outer and inner=20
> optionals are engaged. When either optional is disengaged, the bool membe=
r=20
> does not exist and therefore there is no need to keep it around in memory=
=20
> (in fact, we are required by the Standard to destroy it[1]). Which means=
=20
> that we have a whole unused byte to play around with. We just need to mak=
e=20
> sure that when the optionals *are* engaged, the bool really truly exists=
=20
> =E2=80=94 and I do make sure of that.
>
> Notice that I left out the case where "both optionals are disengaged."=20
> That's because no such state exists. When the outer optional is disengage=
d, *there=20
> is no inner optional* =E2=80=94 the inner optional is not in any state at=
all =E2=80=94=20
> it has been destroyed, and will not reappear until you engage the outer=
=20
> optional again.
>
> *An optional<T> which is disengaged does not hold a T.*
>
> =E2=80=93Arthur
>
> [1] modulo the as-if rule
>
>
How you exactly check what state is now without UB? You need poke bytes=20
that could be `bool` or `byte` that store "engaged" levels.
Only way I see that could made this work is (but still this could be UB):
struct optional
{
union { bool v; char i; };
bool isSet()
{
bool t =3D true, f =3D false;
return memcmp(this, &t, 1) || memcmp(this, &f, 1);
}
}
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/b2977aad-1723-42b6-ae4e-5724ad7cbf17%40isocpp.or=
g.
------=_Part_550_1825476278.1498845811432
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, June 30, 2017 at 7:32:03 PM UTC+2, Arth=
ur O'Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Fri, Jun 30, 2017 at 10:24 AM, <span dir=3D"ltr"><<a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"hzzQwUfgAAAJ" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return tru=
e;" onclick=3D"this.href=3D'javascript:';return true;">inkwizyt...@=
gmail.com</a>></span> wrote:<br><div><div class=3D"gmail_quote"><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div><div><br></div></div><div>16 b=
ecause you need full byte object in optional otherwise you will get `std::v=
ector<bool>` mk2.<br></div></div></blockquote><div><br></div><div>I h=
ate vector<bool> as much as you do, I promise. :) =C2=A0The analogy d=
oesn't work here. vector<bool> is terrible because it <i>purports=
</i> to expose accessors returning bool& but its in-memory representati=
on doesn't contain a full-byte bool anywhere, so it has to cheat and us=
e proxy iterators and just generally mess things up.</div><div><br></div><d=
iv>In the case of std::optional<std::optional<<wbr>bool>>, it p=
urports to expose accessors returning bool& <i><b>if and only if</b></i=
> both the outer and inner optionals are engaged. When either optional is d=
isengaged, the bool member does not exist and therefore there is no need to=
keep it around in memory (in fact, we are required by the Standard to dest=
roy it[1]). Which means that we have a whole unused byte to play around wit=
h. We just need to make sure that when the optionals <i>are</i> engaged, th=
e bool really truly exists =E2=80=94 and I do make sure of that.</div><div>=
<br></div><div>Notice that I left out the case where "both optionals a=
re disengaged." That's because no such state exists. When the oute=
r optional is disengaged, <i>there is no inner optional</i> =E2=80=94 the i=
nner optional is not in any state at all =E2=80=94 it has been destroyed, a=
nd will not reappear until you engage the outer optional again.</div><div><=
br></div><div><b>An optional<T> which is disengaged does not hold a T=
..</b></div><div><br></div><div>=E2=80=93Arthur</div><div><br></div><div>[1]=
modulo the as-if rule</div><div><br></div></div></div></div></blockquote><=
div><br>How you exactly check what state is now without UB? You need poke b=
ytes that could be `bool` or `byte` that store "engaged" levels.<=
br>Only way I see that could made this work is (but still this could be UB)=
:<br><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb(=
187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: brea=
k-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">str=
uct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> option=
al<br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">uni=
on</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">bool</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> v</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">char</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> i</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> isSet</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> t </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">true</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> f </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">false</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ret=
urn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> memcmp=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">this</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">t</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">=
1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">||</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> memcmp</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">this</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>f</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br><br></span></div></code></div><br><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b2977aad-1723-42b6-ae4e-5724ad7cbf17%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b2977aad-1723-42b6-ae4e-5724ad7cbf17=
%40isocpp.org</a>.<br />
------=_Part_550_1825476278.1498845811432--
------=_Part_549_836996001.1498845811432--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Fri, 30 Jun 2017 11:29:08 -0700
Raw View
--94eb2c0de474d5c90a055331975c
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
See the repository, please. Basically, access the bytes as (unsigned char)
to avoid UB.
On Fri, Jun 30, 2017 at 11:03 AM, <inkwizytoryankes@gmail.com> wrote:
>
>
> On Friday, June 30, 2017 at 7:32:03 PM UTC+2, Arthur O'Dwyer wrote:
>>
>> On Fri, Jun 30, 2017 at 10:24 AM, <inkwizyt...@gmail.com> wrote:
>>
>>>
>>> 16 because you need full byte object in optional otherwise you will get
>>> `std::vector<bool>` mk2.
>>>
>>
>> I hate vector<bool> as much as you do, I promise. :) The analogy doesn'=
t
>> work here. vector<bool> is terrible because it *purports* to expose
>> accessors returning bool& but its in-memory representation doesn't conta=
in
>> a full-byte bool anywhere, so it has to cheat and use proxy iterators an=
d
>> just generally mess things up.
>>
>> In the case of std::optional<std::optional<bool>>, it purports to expose
>> accessors returning bool& *if and only if* both the outer and inner
>> optionals are engaged. When either optional is disengaged, the bool memb=
er
>> does not exist and therefore there is no need to keep it around in memor=
y
>> (in fact, we are required by the Standard to destroy it[1]). Which means
>> that we have a whole unused byte to play around with. We just need to ma=
ke
>> sure that when the optionals *are* engaged, the bool really truly exists
>> =E2=80=94 and I do make sure of that.
>>
>> Notice that I left out the case where "both optionals are disengaged."
>> That's because no such state exists. When the outer optional is disengag=
ed, *there
>> is no inner optional* =E2=80=94 the inner optional is not in any state a=
t all =E2=80=94
>> it has been destroyed, and will not reappear until you engage the outer
>> optional again.
>>
>> *An optional<T> which is disengaged does not hold a T.*
>>
>> =E2=80=93Arthur
>>
>> [1] modulo the as-if rule
>>
>>
> How you exactly check what state is now without UB? You need poke bytes
> that could be `bool` or `byte` that store "engaged" levels.
> Only way I see that could made this work is (but still this could be UB):
> struct optional
> {
> union { bool v; char i; };
> bool isSet()
> {
> bool t =3D true, f =3D false;
> return memcmp(this, &t, 1) || memcmp(this, &f, 1);
> }
> }
>
>
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/
> isocpp.org/d/topic/std-proposals/fghaQHk8oe8/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/b2977aad-1723-42b6-
> ae4e-5724ad7cbf17%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b2977aad-17=
23-42b6-ae4e-5724ad7cbf17%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0J1Y3%3Dq6kRyRE7bBjF44gYUuFM-zyk%2Bf2dJU3Q=
gKeStTA%40mail.gmail.com.
--94eb2c0de474d5c90a055331975c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">See the repository, please.=C2=A0 Basically, access the by=
tes as (unsigned char) to avoid UB.</div><div class=3D"gmail_extra"><br><di=
v class=3D"gmail_quote">On Fri, Jun 30, 2017 at 11:03 AM, <span dir=3D"ltr=
"><<a href=3D"mailto:inkwizytoryankes@gmail.com" target=3D"_blank">inkwi=
zytoryankes@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_q=
uote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><br><br>On Friday, June 30, 2017 at 7:32:03 PM UTC+2, A=
rthur O'Dwyer wrote:<span class=3D""><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">On Fri, Jun 30, 2017 at 10:24 AM, <span dir=3D"ltr"=
><<a rel=3D"nofollow">inkwizyt...@gmail.com</a>></span> wrote:<br><di=
v><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div><div><br></div></div><div>16 because you need full byte object in op=
tional otherwise you will get `std::vector<bool>` mk2.<br></div></div=
></blockquote><div><br></div><div>I hate vector<bool> as much as you =
do, I promise. :) =C2=A0The analogy doesn't work here. vector<bool&g=
t; is terrible because it <i>purports</i> to expose accessors returning boo=
l& but its in-memory representation doesn't contain a full-byte boo=
l anywhere, so it has to cheat and use proxy iterators and just generally m=
ess things up.</div><div><br></div><div>In the case of std::optional<std=
::optional<bo<wbr>ol>>, it purports to expose accessors returning =
bool& <i><b>if and only if</b></i> both the outer and inner optionals a=
re engaged. When either optional is disengaged, the bool member does not ex=
ist and therefore there is no need to keep it around in memory (in fact, we=
are required by the Standard to destroy it[1]). Which means that we have a=
whole unused byte to play around with. We just need to make sure that when=
the optionals <i>are</i> engaged, the bool really truly exists =E2=80=94 a=
nd I do make sure of that.</div><div><br></div><div>Notice that I left out =
the case where "both optionals are disengaged." That's becaus=
e no such state exists. When the outer optional is disengaged, <i>there is =
no inner optional</i> =E2=80=94 the inner optional is not in any state at a=
ll =E2=80=94 it has been destroyed, and will not reappear until you engage =
the outer optional again.</div><div><br></div><div><b>An optional<T> =
which is disengaged does not hold a T.</b></div><div><br></div><div>=E2=80=
=93Arthur</div><div><br></div><div>[1] modulo the as-if rule</div><div><br>=
</div></div></div></div></blockquote></span><div><br>How you exactly check =
what state is now without UB? You need poke bytes that could be `bool` or `=
byte` that store "engaged" levels.<br>Only way I see that could m=
ade this work is (but still this could be UB):<br><div style=3D"background-=
color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bor=
der-width:1px" class=3D"m_-7050741152234903482prettyprint"><code class=3D"m=
_-7050741152234903482prettyprint"><div class=3D"m_-7050741152234903482subpr=
ettyprint"><span style=3D"color:#008" class=3D"m_-7050741152234903482styled=
-by-prettify">struct</span><span style=3D"color:#000" class=3D"m_-705074115=
2234903482styled-by-prettify"> optional<br></span><span style=3D"color:#660=
" class=3D"m_-7050741152234903482styled-by-prettify">{</span><span style=3D=
"color:#000" class=3D"m_-7050741152234903482styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008" class=3D"m_-7050741152234903482sty=
led-by-prettify">union</span><span style=3D"color:#000" class=3D"m_-7050741=
152234903482styled-by-prettify"> </span><span style=3D"color:#660" class=3D=
"m_-7050741152234903482styled-by-prettify">{</span><span style=3D"color:#00=
0" class=3D"m_-7050741152234903482styled-by-prettify"> </span><span style=
=3D"color:#008" class=3D"m_-7050741152234903482styled-by-prettify">bool</sp=
an><span style=3D"color:#000" class=3D"m_-7050741152234903482styled-by-pret=
tify"> v</span><span style=3D"color:#660" class=3D"m_-7050741152234903482st=
yled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_-7050741152=
234903482styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_=
-7050741152234903482styled-by-prettify">char</span><span style=3D"color:#00=
0" class=3D"m_-7050741152234903482styled-by-prettify"> i</span><span style=
=3D"color:#660" class=3D"m_-7050741152234903482styled-by-prettify">;</span>=
<span style=3D"color:#000" class=3D"m_-7050741152234903482styled-by-prettif=
y"> </span><span style=3D"color:#660" class=3D"m_-7050741152234903482styled=
-by-prettify">};</span><span style=3D"color:#000" class=3D"m_-7050741152234=
903482styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#00=
8" class=3D"m_-7050741152234903482styled-by-prettify">bool</span><span styl=
e=3D"color:#000" class=3D"m_-7050741152234903482styled-by-prettify"> isSet<=
/span><span style=3D"color:#660" class=3D"m_-7050741152234903482styled-by-p=
rettify">()</span><span style=3D"color:#000" class=3D"m_-705074115223490348=
2styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660" cl=
ass=3D"m_-7050741152234903482styled-by-prettify">{</span><span style=3D"col=
or:#000" class=3D"m_-7050741152234903482styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008" class=3D"m_-70507411522=
34903482styled-by-prettify">bool</span><span style=3D"color:#000" class=3D"=
m_-7050741152234903482styled-by-prettify"> t </span><span style=3D"color:#6=
60" class=3D"m_-7050741152234903482styled-by-prettify">=3D</span><span styl=
e=3D"color:#000" class=3D"m_-7050741152234903482styled-by-prettify"> </span=
><span style=3D"color:#008" class=3D"m_-7050741152234903482styled-by-pretti=
fy">true</span><span style=3D"color:#660" class=3D"m_-7050741152234903482st=
yled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-7050741152=
234903482styled-by-prettify"> f </span><span style=3D"color:#660" class=3D"=
m_-7050741152234903482styled-by-prettify">=3D</span><span style=3D"color:#0=
00" class=3D"m_-7050741152234903482styled-by-prettify"> </span><span style=
=3D"color:#008" class=3D"m_-7050741152234903482styled-by-prettify">false</s=
pan><span style=3D"color:#660" class=3D"m_-7050741152234903482styled-by-pre=
ttify">;</span><span style=3D"color:#000" class=3D"m_-7050741152234903482st=
yled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#008" class=3D"m_-7050741152234903482styled-by-prettify">return</span><s=
pan style=3D"color:#000" class=3D"m_-7050741152234903482styled-by-prettify"=
> memcmp</span><span style=3D"color:#660" class=3D"m_-7050741152234903482st=
yled-by-prettify">(</span><span style=3D"color:#008" class=3D"m_-7050741152=
234903482styled-by-prettify">this</span><span style=3D"color:#660" class=3D=
"m_-7050741152234903482styled-by-prettify">,</span><span style=3D"color:#00=
0" class=3D"m_-7050741152234903482styled-by-prettify"> </span><span style=
=3D"color:#660" class=3D"m_-7050741152234903482styled-by-prettify">&</s=
pan><span style=3D"color:#000" class=3D"m_-7050741152234903482styled-by-pre=
ttify">t</span><span style=3D"color:#660" class=3D"m_-7050741152234903482st=
yled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-7050741152=
234903482styled-by-prettify"> </span><span style=3D"color:#066" class=3D"m_=
-7050741152234903482styled-by-prettify">1</span><span style=3D"color:#660" =
class=3D"m_-7050741152234903482styled-by-prettify">)</span><span style=3D"c=
olor:#000" class=3D"m_-7050741152234903482styled-by-prettify"> </span><span=
style=3D"color:#660" class=3D"m_-7050741152234903482styled-by-prettify">||=
</span><span style=3D"color:#000" class=3D"m_-7050741152234903482styled-by-=
prettify"> memcmp</span><span style=3D"color:#660" class=3D"m_-705074115223=
4903482styled-by-prettify">(</span><span style=3D"color:#008" class=3D"m_-7=
050741152234903482styled-by-prettify">this</span><span style=3D"color:#660"=
class=3D"m_-7050741152234903482styled-by-prettify">,</span><span style=3D"=
color:#000" class=3D"m_-7050741152234903482styled-by-prettify"> </span><spa=
n style=3D"color:#660" class=3D"m_-7050741152234903482styled-by-prettify">&=
amp;</span><span style=3D"color:#000" class=3D"m_-7050741152234903482styled=
-by-prettify">f</span><span style=3D"color:#660" class=3D"m_-70507411522349=
03482styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-705=
0741152234903482styled-by-prettify"> </span><span style=3D"color:#066" clas=
s=3D"m_-7050741152234903482styled-by-prettify">1</span><span style=3D"color=
:#660" class=3D"m_-7050741152234903482styled-by-prettify">);</span><span st=
yle=3D"color:#000" class=3D"m_-7050741152234903482styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#660" class=3D"m_-705074115223490=
3482styled-by-prettify">}</span><span style=3D"color:#000" class=3D"m_-7050=
741152234903482styled-by-prettify"><br></span><span style=3D"color:#660" cl=
ass=3D"m_-7050741152234903482styled-by-prettify">}</span><span style=3D"col=
or:#000" class=3D"m_-7050741152234903482styled-by-prettify"><br><br></span>=
</div></code></div><br><br></div></div><span class=3D"">
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/fghaQHk8oe8/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/<wbr>isocpp.org/d/topic/std-<wbr>proposals/f=
ghaQHk8oe8/<wbr>unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b2977aad-1723-42b6-ae4e-5724ad7cbf17%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/b297=
7aad-1723-42b6-<wbr>ae4e-5724ad7cbf17%40isocpp.org</a><wbr>.<br>
</blockquote></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0J1Y3%3Dq6kRyRE7bBjF44gYUuFM-zy=
k%2Bf2dJU3QgKeStTA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0J1Y3%3=
Dq6kRyRE7bBjF44gYUuFM-zyk%2Bf2dJU3QgKeStTA%40mail.gmail.com</a>.<br />
--94eb2c0de474d5c90a055331975c--
.
Author: Barry Revzin <barry.revzin@gmail.com>
Date: Fri, 30 Jun 2017 12:28:12 -0700 (PDT)
Raw View
------=_Part_593_15458201.1498850892787
Content-Type: multipart/alternative;
boundary="----=_Part_594_530934191.1498850892787"
------=_Part_594_530934191.1498850892787
Content-Type: text/plain; charset="UTF-8"
>
>
> This is optional<reference_wrapper<T>>.
> As for why optional<T&> is a terrible, horrible, no-good, very bad idea,
> please see Matt Calabrese's talk
> <https://www.youtube.com/watch?v=hKIYbf1fsLw> from C++Now.
>
>
That's not at all the impression I got from that talk. One of the things he
specifically mentions as a good idea is to support references for
optional/variant, but internally wrap the references so that they behave as
regular types (that is, like pointers. so operator= would rebind
references, not assign through them).
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2991b2b2-2f62-42e2-83d1-f42dae9c32c1%40isocpp.org.
------=_Part_594_530934191.1498850892787
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><br></div><div>This is optional<reference_wrapper<T>><=
wbr>.</div><div>As for why optional<T&> is a terrible, horrible, =
no-good, very bad idea, please see <a href=3D"https://www.youtube.com/watch=
?v=3DhKIYbf1fsLw" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'https://www.youtube.com/watch?v\x3dhKIYbf1fsLw';return true;"=
onclick=3D"this.href=3D'https://www.youtube.com/watch?v\x3dhKIYbf1fsLw=
';return true;">Matt Calabrese's talk</a> from C++Now.</div><div><b=
r></div></div></blockquote><div><br></div><div>That's not at all the im=
pression I got from that talk. One of the things he specifically mentions a=
s a good idea is to support references for optional/variant, but internally=
wrap the references so that they behave as regular types (that is, like po=
inters. so operator=3D would rebind references, not assign through them).</=
div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/2991b2b2-2f62-42e2-83d1-f42dae9c32c1%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2991b2b2-2f62-42e2-83d1-f42dae9c32c1=
%40isocpp.org</a>.<br />
------=_Part_594_530934191.1498850892787--
------=_Part_593_15458201.1498850892787--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Fri, 30 Jun 2017 12:42:25 -0700
Raw View
--94eb2c0de474e2fb670553329d12
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Fri, Jun 30, 2017 at 12:28 PM, Barry Revzin <barry.revzin@gmail.com>
wrote:
>
>> This is optional<reference_wrapper<T>>.
>> As for why optional<T&> is a terrible, horrible, no-good, very bad idea,
>> please see Matt Calabrese's talk
>> <https://www.youtube.com/watch?v=3DhKIYbf1fsLw> from C++Now.
>>
>
> That's not at all the impression I got from that talk. One of the things
> he specifically mentions as a good idea is to support references for
> optional/variant, but internally wrap the references so that they behave =
as
> regular types (that is, like pointers. so operator=3D would rebind
> references, not assign through them).
>
I'll have to re-watch it, then. I would say that "an optional of a regular
type that behaves like a pointer" is a good idea, but *that* one is spelled
optional<T*>. Notice that part of behaving like a regular type is making
sure that the semantics of operator=3D=3D match the semantics of your
copy-constructor: a copy of a value should compare =3D=3D to the original
value, and modifying the copy should not modify the original. I'm pretty
sure Matt talks about *that* pretty extensively.
The places where we put "foo<T&>" into the standard are either places where
the rebinding question never comes up (e.g. std::promise<T&>) or places
where the rebinding question *does* come up and the answer is "oh crap,
maybe that was a bad idea" (e.g. std::tuple<T&>). I said as much during
Matt's talk (hence why I haven't watched the video). IMO, if C++11 had had
proper multiple-assignment, then it wouldn't have needed assign-throughable
std::tie, and if it didn't have std::tie, then it wouldn't have had
std::tuple<T&>. For the cases where we use std::tie and
std::forward_as_tuple today, we could equally well be using a
"std::forwarding_tuple<T>" with perfect-forwarding read-through semantics
and no operator=3D at all. But, hindsight is 20/20.
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0JexAJBZn1LsAPcZnabCJ4pz3J3HUahGeX_FEW8HBP=
Ctw%40mail.gmail.com.
--94eb2c0de474e2fb670553329d12
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Fri, Jun 30, 2017 at 12:28 PM, Barry Revzin <span dir=
=3D"ltr"><<a href=3D"mailto:barry.revzin@gmail.com" target=3D"_blank">ba=
rry.revzin@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><d=
iv class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div>=
This is optional<reference_wrapper<T>><wbr>.</div><div>As for w=
hy optional<T&> is a terrible, horrible, no-good, very bad idea, =
please see <a href=3D"https://www.youtube.com/watch?v=3DhKIYbf1fsLw" rel=3D=
"nofollow" target=3D"_blank">Matt Calabrese's talk</a> from C++Now.</di=
v></div></blockquote><div><br></div><div>That's not at all the impressi=
on I got from that talk. One of the things he specifically mentions as a go=
od idea is to support references for optional/variant, but internally wrap =
the references so that they behave as regular types (that is, like pointers=
.. so operator=3D would rebind references, not assign through them).</div></=
div></blockquote><div><br></div><div>I'll have to re-watch it, then. I =
would say that "an optional of a regular type that behaves like a poin=
ter" is a good idea, but <i>that</i> one is spelled optional<T*>=
..=C2=A0 Notice that part of behaving like a regular type is making sure tha=
t the semantics of operator=3D=3D match the semantics of your copy-construc=
tor: a copy of a value should compare =3D=3D to the original value, and mod=
ifying the copy should not modify the original.=C2=A0 I'm pretty sure M=
att talks about <i>that</i> pretty extensively.</div><div><br></div><div>Th=
e places where we put "foo<T&>" into the standard are e=
ither places where the rebinding question never comes up (e.g. std::promise=
<T&>) or places where the rebinding question <i>does</i> come up =
and the answer is "oh crap, maybe that was a bad idea" (e.g. std:=
:tuple<T&>).=C2=A0 I said as much during Matt's talk (hence w=
hy I haven't watched the video).=C2=A0 IMO, if C++11 had had proper mul=
tiple-assignment, then it wouldn't have needed assign-throughable std::=
tie, and if it didn't have std::tie, then it wouldn't have had std:=
:tuple<T&>.=C2=A0 For the cases where we use std::tie and std::fo=
rward_as_tuple today, we could equally well be using a "std::forwardin=
g_tuple<T>" with perfect-forwarding read-through semantics and n=
o operator=3D at all.=C2=A0 But, hindsight is 20/20.</div><div><br></div><d=
iv>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0JexAJBZn1LsAPcZnabCJ4pz3J3HUah=
GeX_FEW8HBPCtw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0JexAJBZn1L=
sAPcZnabCJ4pz3J3HUahGeX_FEW8HBPCtw%40mail.gmail.com</a>.<br />
--94eb2c0de474e2fb670553329d12--
.
Author: Marc Mutz <marc.mutz@kdab.com>
Date: Sat, 01 Jul 2017 20:01:01 +0200
Raw View
On 2017-06-30 01:05, Arthur O'Dwyer wrote:
[...]
> Okay, now for the problems with _my_ approach:
> - The implementation of tombstone_traits<T> might need to be a friend
> of T, and certainly needs to be kept in sync with the implementation
> details of T, which is too bad, but not fatal.
For a library-only solution, this is true. But a solution for the=20
standard could use compiler hooks to identify fixed-value bits (e.g.=20
LSBs of a sizeof(T) > 1 T*, MSBs of T*s which are outside the target=20
architecture's physical address space, ...) or corresponding bits of=20
objects containing such T*s) into which to stuff side information.
> - Because this approach relies on a kind of type-punning =E2=80=94 a safe
> kind, AFAIK, but a kind =E2=80=94 therefore it cannot be done constexpr,
> which means std::optional<T> is no longer usable in constexpr
> contexts. IMO this is absolutely fatal for pursuing this approach in
> the STL. (Unless someone can come up with a way of doing it constexpr
> that I didn't think of...)
Again, for a library-only solution, this is true (modulo your last=20
qualification). But as a std library feature, we could just *define*=20
constexpr functions that extract the side information from a type, to be=20
implemented as compiler hooks, if necessary (GCC seems to allow type=20
punning in constexpr functions already as an extension, so there it=20
would be library-only):
constexpr const T &get_object(const T &) noexcept;
constexpr T &get_object(T &) noexcept;
constexpr sideband<T> get_sideband(const T &) noexcept;
where sideband<T> is some kind of integral type that maps the=20
information that can be stored in the fixed-value bits of T into an=20
integer range [0, N[, get_object launders its argument from the sideband=20
information (masks the sideband bits of a T*), and get_sideband launders=20
its argument from the type's value-representing bits.
This exposes the sideband information storable in any T to library=20
writers (not just std::optional, but std::variant, too, and even Boost=20
and Qt).
Thanks,
Marc
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/6b453c7a835d7f85108e614d3f9404ac%40kdab.com.
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Sat, 1 Jul 2017 15:51:47 -0700
Raw View
--f403045c1e18f6c9e605534960a3
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Sat, Jul 1, 2017 at 11:01 AM, Marc Mutz <marc.mutz@kdab.com> wrote:
> On 2017-06-30 01:05, Arthur O'Dwyer wrote:
> [...]
>
>> Okay, now for the problems with _my_ approach:
>> - The implementation of tombstone_traits<T> might need to be a friend
>> of T, and certainly needs to be kept in sync with the implementation
>> details of T, which is too bad, but not fatal.
>>
>
> For a library-only solution, this is true. But a solution for the standar=
d
> could use compiler hooks to identify fixed-value bits (e.g. LSBs of a
> sizeof(T) > 1 T*, MSBs of T*s which are outside the target architecture's
> physical address space, ...) or corresponding bits of objects containing
> such T*s) into which to stuff side information.
>
I can see we're trying to solve the same problem here, but I think you'll
run into trouble distinguishing "pre-punned" and "post-punned" pointer
types, for example. I mean if you have a user-defined class with the layou=
t
struct TaggedPointer {
int *p;
};
how is the compiler supposed to deduce how many bits of the "p" field are
available for punning? And if the answer is "it can't", then we're back to
square one =E2=80=94 you haven't made any dent in the problem.
>
> - Because this approach relies on a kind of type-punning =E2=80=94 a safe
>> kind, AFAIK, but a kind =E2=80=94 therefore it cannot be done constexpr,
>> which means std::optional<T> is no longer usable in constexpr
>> contexts. IMO this is absolutely fatal for pursuing this approach in
>> the STL. (Unless someone can come up with a way of doing it constexpr
>> that I didn't think of...)
>>
>
> Again, for a library-only solution, this is true (modulo your last
> qualification). But as a std library feature, we could just *define*
> constexpr functions that extract the side information from a type, to be
> implemented as compiler hooks, if necessary (GCC seems to allow type
> punning in constexpr functions already as an extension, so there it would
> be library-only):
>
> constexpr const T &get_object(const T &) noexcept;
> constexpr T &get_object(T &) noexcept;
> constexpr sideband<T> get_sideband(const T &) noexcept;
>
> where sideband<T> is some kind of integral type that maps the information
> that can be stored in the fixed-value bits of T into an integer range [0,
> N[, get_object launders its argument from the sideband information (masks
> the sideband bits of a T*), and get_sideband launders its argument from t=
he
> type's value-representing bits.
>
Notice that my tombstone_traits doesn't store any data in "the padding
bits" of a type; it actually counts the available representations and uses
those. This is why I can store optional^254<bool> in a single byte, as
opposed to just optional^7<bool>.
This is important because for example std::string has zero "padding bits":
struct string {
char *p;
int size;
int cap;
};
but it does have approximately 8 billion billion "spare representations"
(those where size > cap). And fitting std::optional<std::string> in 16
bytes instead of 24 bytes would be a nice win.
This exposes the sideband information storable in any T to library writers
> (not just std::optional, but std::variant, too, and even Boost and Qt).
>
That's already my intention with tombstone_traits<T>: that it be
exploitable by std::optional and also whoever else wants to use it. (One of
my examples is an open-addressed hash table, although I haven't bothered to
implement it yet. The hash table needs two spare representations: one for
"empty" and one for "tombstone".)
Your "use by std::variant" idea is interesting. I thought about that a tiny
bit a while back, but I couldn't see how to "take the intersection of" the
spare representations of two different types. Of course taking the
intersection is easy if you're dealing only in "padding bits", but if you
deal in "padding bits" then you can't optimize std::optional<std::string>.
In fact I can't think of any run-of-the-mill types that have "padding bits"
except for bool, whereas I can't think of any run-of-the-mill non-scalar
types that *don't* have "spare representations".
Using tombstone_traits<T> with the partial specialization std::variant<T,
monostate, monostate...> would be possible. I wonder if that's interesting.
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0%2By0ryim%3DKsV2jUxxY2vpmfYr4m4%2BkBCRqKo=
2gSPFLpUg%40mail.gmail.com.
--f403045c1e18f6c9e605534960a3
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sat, Jul 1, 2017 at 11:01 AM, Marc Mutz <span dir=3D"lt=
r"><<a href=3D"mailto:marc.mutz@kdab.com" target=3D"_blank">marc.mutz@kd=
ab.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gm=
ail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex">On 2017-06-30 01:05, Arthur O'=
;Dwyer wrote:<br>
[...]<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Okay, now for the problems with _my_ approach:<br>
- The implementation of tombstone_traits<T> might need to be a friend=
<br>
of T, and certainly needs to be kept in sync with the implementation<br>
details of T, which is too bad, but not fatal.<br>
</blockquote>
<br>
For a library-only solution, this is true. But a solution for the standard =
could use compiler hooks to identify fixed-value bits (e.g. LSBs of a sizeo=
f(T) > 1 T*, MSBs of T*s which are outside the target architecture's=
physical address space, ...) or corresponding bits of objects containing s=
uch T*s) into which to stuff side information.<br></blockquote><div><br></d=
iv><div>I can see we're trying to solve the same problem here, but I th=
ink you'll run into trouble distinguishing "pre-punned" and &=
quot;post-punned" pointer types, for example.=C2=A0 I mean if you have=
a user-defined class with the layout</div><div><br></div><div>struct Tagge=
dPointer {</div><div>=C2=A0 =C2=A0 int *p;</div><div>};</div><div><br></div=
><div>how is the compiler supposed to deduce how many bits of the "p&q=
uot; field are available for punning? And if the answer is "it can'=
;t", then we're back to square one =E2=80=94 you haven't made =
any dent in the problem.</div><div><br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex">
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
- Because this approach relies on a kind of type-punning =E2=80=94 a safe<b=
r>
kind, AFAIK, but a kind =E2=80=94 therefore it cannot be done constexpr,<br=
>
which means std::optional<T> is no longer usable in constexpr<br>
contexts. IMO this is absolutely fatal for pursuing this approach in<br>
the STL.=C2=A0 (Unless someone can come up with a way of doing it constexpr=
<br>
that I didn't think of...)<br>
</blockquote>
<br>
Again, for a library-only solution, this is true (modulo your last qualific=
ation). But as a std library feature, we could just *define* constexpr func=
tions that extract the side information from a type, to be implemented as c=
ompiler hooks, if necessary (GCC seems to allow type punning in constexpr f=
unctions already as an extension, so there it would be library-only):<br>
<br>
=C2=A0 =C2=A0constexpr const T &get_object(const T &) noexcept;<br>
=C2=A0 =C2=A0constexpr T &get_object(T &) noexcept;<br>
=C2=A0 =C2=A0constexpr sideband<T> get_sideband(const T &) noexce=
pt;<br>
<br>
where sideband<T> is some kind of integral type that maps the informa=
tion that can be stored in the fixed-value bits of T into an integer range =
[0, N[, get_object launders its argument from the sideband information (mas=
ks the sideband bits of a T*), and get_sideband launders its argument from =
the type's value-representing bits.<br></blockquote><div><br></div><div=
>Notice that my tombstone_traits doesn't store any data in "the pa=
dding bits" of a type; it actually counts the available representation=
s and uses those. This is why I can store optional^254<bool> in a sin=
gle byte, as opposed to just optional^7<bool>.</div><div>This is impo=
rtant because for example std::string has zero "padding bits":</d=
iv><div><br></div><div>struct string {</div><div>=C2=A0 =C2=A0 char *p;</di=
v><div>=C2=A0 =C2=A0 int size;</div><div>=C2=A0 =C2=A0 int cap;</div><div>}=
;</div><div><br></div><div>but it does have approximately 8 billion billion=
"spare representations" (those where size > cap).=C2=A0 And f=
itting std::optional<std::string> in 16 bytes instead of 24 bytes wou=
ld be a nice win.</div><div><br></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This e=
xposes the sideband information storable in any T to library writers (not j=
ust std::optional, but std::variant, too, and even Boost and Qt).<br></bloc=
kquote><div><br></div><div>That's already my intention with tombstone_t=
raits<T>: that it be exploitable by std::optional and also whoever el=
se wants to use it. (One of my examples is an open-addressed hash table, al=
though I haven't bothered to implement it yet. The hash table needs two=
spare representations: one for "empty" and one for "tombsto=
ne".)</div><div><br></div><div>Your "use by std::variant" id=
ea is interesting. I thought about that a tiny bit a while back, but I coul=
dn't see how to "take the intersection of" the spare represen=
tations of two different types. Of course taking the intersection is easy i=
f you're dealing only in "padding bits", but if you deal in &=
quot;padding bits" then you can't optimize std::optional<std::s=
tring>.=C2=A0 In fact I can't think of any run-of-the-mill types tha=
t have "padding bits" except for bool, whereas I can't think =
of any run-of-the-mill non-scalar types that <i>don't</i> have "sp=
are representations".</div><div><br></div><div>Using tombstone_traits&=
lt;T> with the partial specialization std::variant<T, monostate, mono=
state...> would be possible. I wonder if that's interesting.</div><d=
iv><br></div><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2By0ryim%3DKsV2jUxxY2vpmfYr4m=
4%2BkBCRqKo2gSPFLpUg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2By=
0ryim%3DKsV2jUxxY2vpmfYr4m4%2BkBCRqKo2gSPFLpUg%40mail.gmail.com</a>.<br />
--f403045c1e18f6c9e605534960a3--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 5 Jul 2017 10:24:24 -0400
Raw View
--94eb2c049632d2168f055392c11c
Content-Type: text/plain; charset="UTF-8"
On Thu, Jun 29, 2017 at 7:05 PM, Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
wrote:
> The other extension, orthogonal to first one, is to allow value to be
>> stored using alternate representation. As an example, reference type can be
>> stored as a pointer and simply presented as reference. This will also allow
>> to have cheap and relatively easy support for storing references in
>> std::optional, without need of completely separate type specialization.
>>
>
> This is optional<reference_wrapper<T>>.
> As for why optional<T&> is a terrible, horrible, no-good, very bad idea,
> please see Matt Calabrese's talk
> <https://www.youtube.com/watch?v=hKIYbf1fsLw> from C++Now.
>
Erm, that's not what I said in my talk. In fact, quite the opposite. I
advocate support for optional<T&>
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANh8DEkc-u4-60q121uG7moPVHBuAcQJTjpM2Bo9kXx%3Dxn4KYQ%40mail.gmail.com.
--94eb2c049632d2168f055392c11c
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 T=
hu, Jun 29, 2017 at 7:05 PM, Arthur O'Dwyer <span dir=3D"ltr"><<a hr=
ef=3D"mailto:arthur.j.odwyer@gmail.com" target=3D"_blank">arthur.j.odwyer@g=
mail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><span class=3D""><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"><p>The other extension, orthogonal to first one, is to allow value=
to be stored using alternate representation. As an example, reference type=
can be stored as a pointer and simply presented as reference. This will al=
so allow to have cheap and relatively easy support for storing references i=
n std::optional, without need of completely separate type specialization.<b=
r></p></div></blockquote><div><br></div></span><div>This is optional<ref=
erence_wrapper<T>><wbr>.</div><div>As for why optional<T&&g=
t; is a terrible, horrible, no-good, very bad idea, please see <a href=3D"h=
ttps://www.youtube.com/watch?v=3DhKIYbf1fsLw" target=3D"_blank">Matt Calabr=
ese's talk</a> from C++Now.</div></div></blockquote><div><br></div><div=
>Erm, that's not what I said in my talk. In fact, quite the opposite. I=
advocate support for optional<T&>=C2=A0</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CANh8DEkc-u4-60q121uG7moPVHBuAcQJTjpM=
2Bo9kXx%3Dxn4KYQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANh8DEkc-u4-60=
q121uG7moPVHBuAcQJTjpM2Bo9kXx%3Dxn4KYQ%40mail.gmail.com</a>.<br />
--94eb2c049632d2168f055392c11c--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Wed, 5 Jul 2017 14:47:25 -0700
Raw View
--089e08221614266ea9055398f228
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wed, Jul 5, 2017 at 7:24 AM, Matt Calabrese wrote:
> On Thu, Jun 29, 2017 at 7:05 PM, Arthur O'Dwyer <arthur.j.odwyer@gmail.co=
m
> > wrote:
>
>> The other extension, orthogonal to first one, is to allow value to be
>>> stored using alternate representation. As an example, reference type ca=
n be
>>> stored as a pointer and simply presented as reference. This will also a=
llow
>>> to have cheap and relatively easy support for storing references in
>>> std::optional, without need of completely separate type specialization.
>>>
>> This is optional<reference_wrapper<T>>.
>> As for why optional<T&> is a terrible, horrible, no-good, very bad idea,
>> please see Matt Calabrese's talk
>> <https://www.youtube.com/watch?v=3DhKIYbf1fsLw> from C++Now.
>>
>
> Erm, that's not what I said in my talk. In fact, quite the opposite. I
> advocate support for optional<T&>
>
Huh! Well, you fooled me. What I took away from your talk was mostly the
many examples of why value semantics and regular types are a good thing,
and the subtlety of what it really means to be a "regular" type (for
example, that copying ought to produce an identical, substitutable
duplicate of the original, which implies that you can't be "regular"
without supporting operator=3D=3D). I also remember the examples of how to
mess things up by injecting "assign-through" types into generic
value-semantic contexts, e.g.
https://wandbox.org/permlink/gmmqCF4d1eSvutZC
int main() {
int i=3D3, j=3D2, k=3D1;
using assign_through =3D std::tuple<int&>;
std::vector<assign_through> v =3D { {i}, {j}, {k} };
std::sort(v.begin(), v.end());
printf("%d %d %d\n", i, j, k); // "3 3 3"
}
I thought you were holding up assign_through as a "bad", "irregular" type,
not as a model.
I also recall (more hazily) discussion of the sins of vector<bool>,
although that might have been a different talk.
Anyway, it sounds like I've misrepresented Matt's opinion. Let me backtrack
and just say that *I personally* wouldn't support the addition of a type to
the library which was (A) irregular and (B) spelled as if it were a
specialization of an existing type that *is* regular.
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0LWcmzL5ofmFEB8-eYdwbhvOjNizjoEMFqGGCH0FzS=
ztg%40mail.gmail.com.
--089e08221614266ea9055398f228
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wed, Jul 5, 2017 at 7:24 AM, Matt Calabrese<span dir=3D=
"ltr">=C2=A0</span>wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail=
_quote"><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"><div dir=3D"ltr"><div class=3D"gmail_extra"><div c=
lass=3D"gmail_quote">On Thu, Jun 29, 2017 at 7:05 PM, Arthur O'Dwyer <s=
pan dir=3D"ltr"><<a href=3D"mailto:arthur.j.odwyer@gmail.com" target=3D"=
_blank">arthur.j.odwyer@gmail.com</a>></span> wrote:<br><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;b=
order-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"=
><div dir=3D"ltr"><span><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"><div dir=3D"ltr"><p>The other exte=
nsion, orthogonal to first one, is to allow value to be stored using altern=
ate representation. As an example, reference type can be stored as a pointe=
r and simply presented as reference. This will also allow to have cheap and=
relatively easy support for storing references in std::optional, without n=
eed of completely separate type specialization.</p></div></blockquote></spa=
n><span class=3D"gmail-"><div>This is optional<reference_wrapper<T>=
;><wbr>.</div><div>As for why optional<T&> is a terrible, horr=
ible, no-good, very bad idea, please see <a href=3D"https://www.youtube.com=
/watch?v=3DhKIYbf1fsLw" target=3D"_blank">Matt Calabrese's talk</a> fro=
m C++Now.</div></span></div></blockquote><div><br></div><div>Erm, that'=
s not what I said in my talk. In fact, quite the opposite. I advocate suppo=
rt for optional<T&>=C2=A0</div></div></div></div></blockquote><di=
v><br></div><div>Huh!=C2=A0 Well, you fooled me.=C2=A0 What I took away fro=
m your talk was mostly the many examples of why value semantics and regular=
types are a good thing, and the subtlety of what it really means to be a &=
quot;regular" type (for example, that copying ought to produce an iden=
tical, substitutable duplicate of the original, which implies that you can&=
#39;t be "regular" without supporting operator=3D=3D).=C2=A0 I al=
so remember the examples of how to mess things up by injecting "assign=
-through" types into generic value-semantic contexts, e.g.</div><div><=
br></div><div><a href=3D"https://wandbox.org/permlink/gmmqCF4d1eSvutZC">htt=
ps://wandbox.org/permlink/gmmqCF4d1eSvutZC<br></a></div><div><div><br></div=
><div><font face=3D"monospace, monospace">int main() {</font></div><div><fo=
nt face=3D"monospace, monospace">=C2=A0 =C2=A0 int i=3D3, j=3D2, k=3D1;</fo=
nt></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 using assig=
n_through =3D std::tuple<int&>;</font></div><div><font face=3D"mo=
nospace, monospace">=C2=A0 =C2=A0 std::vector<assign_through> v =3D {=
{i}, {j}, {k} };</font></div><div><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0 std::sort(v.begin(), v.end());</font></div><div><font face=3D"mo=
nospace, monospace">=C2=A0 =C2=A0 printf("%d %d %d\n", i, j, k); =
=C2=A0// "3 3 3"</font></div><div><font face=3D"monospace, monosp=
ace">}</font></div></div><div><br></div><div>I thought you were holding up=
=C2=A0<font face=3D"monospace, monospace">assign_through</font>=C2=A0as a &=
quot;bad", "irregular" type, not as a model.</div><div><br><=
/div><div>I also recall (more hazily) discussion of the sins of <font face=
=3D"monospace, monospace">vector<bool></font>, although that might ha=
ve been a different talk.</div><div><br></div><div>Anyway, it sounds like I=
've misrepresented Matt's opinion. Let me backtrack and just say th=
at <i>I personally</i> wouldn't support the addition of a type to the l=
ibrary which was (A) irregular and (B) spelled as if it were a specializati=
on of an existing type that <i>is</i>=C2=A0regular.</div><div><br></div><di=
v>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0LWcmzL5ofmFEB8-eYdwbhvOjNizjoE=
MFqGGCH0FzSztg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0LWcmzL5ofm=
FEB8-eYdwbhvOjNizjoEMFqGGCH0FzSztg%40mail.gmail.com</a>.<br />
--089e08221614266ea9055398f228--
.