220 33037 <c039c5e5-13d0-4052-89f7-b2af50f1e0fc@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Igor Baidiuk <target.san@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: std::optional - support for sentinel values
Date: Fri, 30 Jun 2017 07:21:34 -0700 (PDT)
Lines: 242
Approved: news@gmane.org
Message-ID: <c039c5e5-13d0-4052-89f7-b2af50f1e0fc@isocpp.org>
References: <6e23864f-827a-4bdb-89de-a60d8f5be993@isocpp.org>
 <c44c5d09-9124-488f-aa92-f9ab59797268@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_354_625237961.1498832495025"
X-Trace: blaine.gmane.org 1498832502 32248 195.159.176.226 (30 Jun 2017 14:21:42 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Fri, 30 Jun 2017 14:21:42 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDK4F76SSIIBB5F43HFAKGQEASLOTVI@isocpp.org Fri Jun 30 16:21:37 2017
Return-path: <std-proposals+bncBDK4F76SSIIBB5F43HFAKGQEASLOTVI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-pg0-f72.google.com ([74.125.83.72])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDK4F76SSIIBB5F43HFAKGQEASLOTVI@isocpp.org>)
	id 1dQwnh-0007yv-4P
	for gclcip-std-proposals@m.gmane.org; Fri, 30 Jun 2017 16:21:37 +0200
Original-Received: by mail-pg0-f72.google.com with SMTP id u5sf122259929pgq.14
        for <gclcip-std-proposals@m.gmane.org>; Fri, 30 Jun 2017 07:21:42 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=XV48vlZE+eDdh/WDKEchWRTrYwlRxhROqrxUuM/f6y0=;
        b=R75b+CnVXE3+iuDbSEzb1IV3MVimB1gkkfxAF8u54x0iBBumR7l/WachL486kWt947
         4hBAQrpcudwZ+l638O5aL39JDmFDQHAgsQyBrJbn5Lvul+zuHfmaiANhbZZ3KTxQe3ZZ
         4bN97vufuTLpnJwlBOeQyMOVwmMrv2gs6bFvrqXJ1vlvD/vW7yC9Sxho7Is53o72ZYj5
         ySTxr3kojbFF/+/h2ovt7L58MvddM/PSuqNJGrddVFNAYkjZyibeUiN0zGtvfHxoYCaB
         o3HcRq62+V7ojPCgpN2FqjH9LVUS1RlVysFUeooj5dFiKY3ArV36YoldZZJNF4CQ2tEG
         bLpg==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=XV48vlZE+eDdh/WDKEchWRTrYwlRxhROqrxUuM/f6y0=;
        b=FYhmwMu3U4zrQk5CwgQYUwH/XaPhV2DxcSZt/5l3578hzlrsAzDtiN4cNUEUK+kZGP
         r5sFusPVvPvcWOmB8jYBYKJWIHABYI1lVm1mpC9Dpxs1h7oOzPkm19mQpkC6TFaJ2dve
         vOJ5VxVNQQxKwXQ01o94rzke0IMVhjRMytj4a6Ac4dpdwOat+gw9M3eldSfyD7oRDpAU
         PzmCbUnT7MUxFumM91CU+vEJKesB+FpfTmdvqpuYg9U2NgwLt7wjWqxe2ipRiITUoSgV
         QbwFea1Ct8eqYqbqxvBJOEGR6p2p/UMCNyG+SOElprungDpq+Js2Na9IIbBrr6+Wfkts
         58AQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:x-spam-checked-in-group:list-post:list-help
         :list-archive:list-subscribe:list-unsubscribe;
        bh=XV48vlZE+eDdh/WDKEchWRTrYwlRxhROqrxUuM/f6y0=;
        b=h/J9EGQy5sbZhQbXT0qe7J7qDEGLWMi5R1I3cWrQ6SMqvn5rnYCo4BGx3De4Eyo6wD
         dRCpR5/Yk4lOV+3c1YKLtgWWKgT2oYOhL2ZBVcKtD5F/Q1MGMKBHaPPX7yHLISbgTqUk
         7I4ulDOgdU5/RDomS5M6JyBciZfoUwUc2xl3RtA0P92fKcatTgDwSGQFmrw7jIk3959x
         r6w7sy3pRi9QbNRlyZGGjiNVsIPL0fCvKQ7Myj71XJVA9nMHWjTh5S/XADjEY4eKuBI1
         JhbNwnmZlGk+LggGd39uI5N22dpQyC/BGDlhi5Rke8ajC+ZIGBt6or/OPW5vgnCO5AnA
         ZCXw==
X-Gm-Message-State: AKS2vOwyWoVPdhXS8MxlaznYPv32f+L4ltkGIq5eklkSN5DZtxNN39vQ
	ZU4/y5JhO72z5dv3
X-Received: by 10.99.96.8 with SMTP id u8mr12936191pgb.142.1498832501847;
        Fri, 30 Jun 2017 07:21:41 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.36.23.10 with SMTP id 10ls2697253ith.8.gmail; Fri, 30 Jun 2017
 07:21:40 -0700 (PDT)
X-Received: by 10.36.26.85 with SMTP id 82mr494798iti.6.1498832495644;
        Fri, 30 Jun 2017 07:21:35 -0700 (PDT)
In-Reply-To: <c44c5d09-9124-488f-aa92-f9ab59797268@isocpp.org>
X-Original-Sender: target.san@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:33037
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/33037>

------=_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&#39=
;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&#39;https://www.youtube.com/w=
atch?v\x3dOMbwbXZWtDM&#39;;return true;" onclick=3D"this.href=3D&#39;https:=
//www.youtube.com/watch?v\x3dOMbwbXZWtDM&#39;;return true;">Mark Zeren&#39;=
s C++Now talk on strings</a> will be interesting to you. Following that tal=
k, I implemented his ideas for a &quot;nullable trait&quot; in my &quot;STL=
 From Scratch&quot; under the name std::tombstone_traits&lt;T&gt;.</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&lt;T&gt;; it is literally a T. =C2=A0If that&#39;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&#39;m thinking more from correctness and usability points of view.<br>Th=
e values used for sentinels are usually &quot;invalid&quot; type states. Th=
e closest example is what remains of value if it&#39;s moved out. In such c=
ase destructor is trivial.<br>Next, such &quot;invalid&quot; 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 &quot;free&quot; 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 &quot;available&quot; value; for example, <font f=
ace=3D"courier new, monospace">bool</font>. However, it is common for there=
 to be &quot;available&quot; <i>bit-patterns</i> that are distinguishable f=
rom any possible value of T. =C2=A0You raised the example of a reference_wr=
apper&lt;T&gt; in the all-bits-zero state. =C2=A0For another example, there=
&#39;s std::vector in the state &quot;ptr=3Dnull, size=3D42, capacity=3D0&q=
uot; =E2=80=94 that&#39;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&#39;t exist for all the types on the table. And for vector, which =
you mention, empty state is perfectly valid - we don&#39;t care how it&#39;=
s represented, we simply shouldn&#39;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&lt;optional&l=
t;<wbr>optional&lt;bool&gt;&gt;&gt;) =3D=3D 1</font>. Your approach would b=
e completely unable to optimize this; you&#39;d have to use at least 4 byte=
s.</div></div></blockquote><div>Let&#39;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&#39;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&lt;reference_wrapper&lt;T&gt;&gt;<wbr>.</div><div>As fo=
r why optional&lt;T&amp;&gt; 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&#39;https://www=
..youtube.com/watch?v\x3dhKIYbf1fsLw&#39;;return true;" onclick=3D"this.href=
=3D&#39;https://www.youtube.com/watch?v\x3dhKIYbf1fsLw&#39;;return true;">M=
att Calabrese&#39;s talk</a> from C++Now.</div></div></blockquote><div>This=
 is disputable, true. I just remembered how some folks complained that opti=
onal&lt;T&amp;&gt; isn&#39;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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
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--

.
