220 33042 <CADvuK0KjALZ7qeXqLxrdL_Kf2tc460noqLZ3feosCvdELsz_bQ@mail.gmail.com> article
Path: news.gmane.org!.POSTED!not-for-mail
From: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: std::optional - support for sentinel values
Date: Fri, 30 Jun 2017 10:24:28 -0700
Lines: 286
Approved: news@gmane.org
Message-ID: <CADvuK0KjALZ7qeXqLxrdL_Kf2tc460noqLZ3feosCvdELsz_bQ@mail.gmail.com>
References: <6e23864f-827a-4bdb-89de-a60d8f5be993@isocpp.org>
 <c44c5d09-9124-488f-aa92-f9ab59797268@isocpp.org> <c039c5e5-13d0-4052-89f7-b2af50f1e0fc@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="94eb2c0de4748b8b39055330b0e7"
X-Trace: blaine.gmane.org 1498843478 18589 195.159.176.226 (30 Jun 2017 17:24:38 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Fri, 30 Jun 2017 17:24:38 +0000 (UTC)
To: "ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDLZJYWNDQIM5EW2ZICRUBGVR3ECG@isocpp.org Fri Jun 30 19:24:26 2017
Return-path: <std-proposals+bncBDLZJYWNDQIM5EW2ZICRUBGVR3ECG@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-lf0-f72.google.com ([209.85.215.72])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDLZJYWNDQIM5EW2ZICRUBGVR3ECG@isocpp.org>)
	id 1dQzec-0004G0-54
	for gclcip-std-proposals@m.gmane.org; Fri, 30 Jun 2017 19:24:26 +0200
Original-Received: by mail-lf0-f72.google.com with SMTP id c199sf29610557lfg.8
        for <gclcip-std-proposals@m.gmane.org>; Fri, 30 Jun 2017 10:24:31 -0700 (PDT)
ARC-Seal: i=2; a=rsa-sha256; t=1498843471; cv=pass;
        d=google.com; s=arc-20160816;
        b=z1a/Dp3EYmocSiVVjelP3VQ/wnMaR70YHguXCCsngPKUgzz1Un5qegB8d9NTq5iD9P
         6pMF91s6Ic/RrG3s723Kw3645HFFIVot86bb/P5892n9IRU+/powNfEl+d2x2iPbCWhy
         ue3bvN4WCtM+cuv/dk6iCg6pcrEP/dbplZ9ePYOeoay9G0+qLR0Qn07ials7I2Oq0hnB
         +hgNX2g55rXa+NMfgRhVWzQKIDQU7O2LawtU3DDi+oJsWAxyLROqDp8jQ4Qr50bmoIX3
         IDIaOXsAEEkGuhiW2qM6KvGTbl49Pet26F5oQWFStD82OZXY9FvtBKX7PMBEGtanL7XZ
         IbQg==
ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post
         :list-id:mailing-list:precedence:reply-to:to:subject:message-id:date
         :from:references:in-reply-to:mime-version:arc-authentication-results
         :arc-message-signature:dkim-signature:arc-authentication-results;
        bh=0OAo0YFweMnTtYPW9079AMv74UgG6yjm75hSft+wwBY=;
        b=DDJuYcpOpCiE+Rw94wQft2L3lPw55uVrlQHAlkM3kzA3r78dYXHveyzjFOVO1sLbSX
         LhQpQv2KLIiVxJJAaxDU06UJyHjNPRo1i4ygpdOyfsclppxwaWZCCICmMFsDzhKJSWQ9
         q2z1cMAr6aBtn/SLW2Sg6NZ45njpOWeyGzoRUfOjARplmIAk+l5J/H2t9PMxQPcbNuZL
         PMWx3SbQiL1bvyG21yB7w2X5d8unKXe1zpYheBFIyy3L9AiUlp/mK/RC4bNs27I62vnV
         hUQ4hDSG+t0ig3y5NG+0w9xjRBs2jrDBMI+O4enbNdxXNVI1/JOTqa5UgokpowM/iy2u
         XbjQ==
ARC-Authentication-Results: i=2; mx.google.com;
       dkim=pass header.i=@gmail.com header.b=NV5dNQtf;
       spf=pass (google.com: domain of arthur.j.odwyer@gmail.com designates 2a00:1450:400c:c09::22a as permitted sender) smtp.mailfrom=arthur.j.odwyer@gmail.com;
       dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=mime-version:in-reply-to:references:from:date:message-id:subject:to
         :x-original-sender:x-original-authentication-results:reply-to
         :precedence:mailing-list:list-id:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=0OAo0YFweMnTtYPW9079AMv74UgG6yjm75hSft+wwBY=;
        b=EXm5OczWs0QZmIpVXv50gi9niG0lZnoyvO8B0VrXOeQvm83o404j9cAiD2IOKo84Tf
         z6LxUFOC/PhbXQ0sRx8CkrOcl7oteWjG0o9R/n2tc/VhUMyEwjyHnCbwTaxkXmPDczHq
         MBmzeVWLVXx2MkGIWVlrQRxj/vTbu4L8cRx3FyrJuMfoOYVpW0Q3BVBqGIuTg8s22ef7
         TgbIbwzUQ7a2VaEZrJwLTu47JyNB2g6fw45QWm2dtu5lVPRFtdqWDJDyVZ8J4PVy315G
         U3+VFxCErxMenSMf+IzMeEQgb9yz19V+69sVDnzsubd6oK5S1VuuvcqrextXkGSJlYTN
         Tx2w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:mime-version:in-reply-to:references:from:date
         :message-id:subject:to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=0OAo0YFweMnTtYPW9079AMv74UgG6yjm75hSft+wwBY=;
        b=Un0nxC4sZz98+InzI9a5xuDF2OvessjSkhyhj1x/BfPgCIXckENflr+IPs+SOhagYd
         dflvrMENi9NAOQhCSq0wVIhOfCStxzR4H9p6y9sD2dSH/YvnmwLvZrzrdRspwRlDEDiP
         rfWYkhwTKYsV+OjtmZd27GNrh1sv/EBmSAdjBurbN/v7TsXY25ansQXvHf5Oz6aXhCiT
         hiLV6TBx53c7Dv+Hcd1iTwgcuzNKZBl/U43kkdgwxSaIimnZ7bhV0RcK93wsRXcK9kYx
         /h9xaGZBk/bAYMVPSIdkV4yqNdNPQIpJGn74cPlfxPsFs6DBZPUyzxyMXRswb++egegq
         /ETw==
X-Gm-Message-State: AKS2vOwKarftDeZGWG36jcZQogGBgphSytuyH2VQgLr79p9guwvcD1Zn
	wFt8EVRzcO2XuDp6
X-Received: by 10.46.80.18 with SMTP id e18mr4316527ljb.10.1498843471485;
        Fri, 30 Jun 2017 10:24:31 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.28.153.140 with SMTP id b134ls762897wme.23.gmail; Fri, 30 Jun
 2017 10:24:29 -0700 (PDT)
X-Received: by 10.28.113.142 with SMTP id d14mr7183914wmi.10.1498843469756;
        Fri, 30 Jun 2017 10:24:29 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1498843469; cv=none;
        d=google.com; s=arc-20160816;
        b=G2ThKxv29F/spwYaMdW+npliw38beP0tjpcqDe+iDxlD1zobcOAj6nuBnRUJiL7OIx
         hN4R1Qq7jMi70E3fvE+Py+4U4Z02nRzLobSOzAsRdndv3U/NNPPL3SmzMTdhmImdip6a
         yEwR3AkyzdG5b4xGRY+rnGe+shPI751v5SG9GA9wq+durH2e6iFi3+tXOlNGGhEZGUBT
         kQ1lMbFZc/33ovuuqlNew+c+/pcgwzU/zNBITXumfkGe8fB6itaXfR4JLsMUFN76pzkN
         S1WAkOGPt3A5o1XomEz+V1LNKxU9C3pbGoFN1R/uXPiIzNmMH8ZRxgCQOdIPAQDLO6VR
         FUmA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=to:subject:message-id:date:from:references:in-reply-to:mime-version
         :dkim-signature:arc-authentication-results;
        bh=uTFW5Bch0CXdquJbeTsodfcTEgid55zkOjFsI+cPybo=;
        b=LzIqC6OiQsIyXJFmtArOE4rbEJNUIRz3cuCpTuSIN0pZOY3qkYqb2DqXPs6e+cEQ1t
         xDbjdDnwaLH694u+mkDjhfSPJvzqSdd0nS3rHeQAiAYi9+m29dkZnKnZ4w+Vb7uGhKIn
         Secjhc53iUdM75TER2I5mJ/ra0/5lL9lZkPlzMm6g0ZZM1aZe7njPxAQ3xbEiIiOhrRM
         MRMWoqqAarhdMawbGmtNsYs4JoTCfDfdznA1Q6a+duc8Pbeh+Gl6wb5oz0yZQ0ulMqqe
         2I7xoFwA+hsC1wE+khLEC2zTLB3TyEkRiCBILdV1gE9auVT4L/2eJbJK6e7dUdMdqAO/
         IQ2A==
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=pass header.i=@gmail.com header.b=NV5dNQtf;
       spf=pass (google.com: domain of arthur.j.odwyer@gmail.com designates 2a00:1450:400c:c09::22a as permitted sender) smtp.mailfrom=arthur.j.odwyer@gmail.com;
       dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com
Original-Received: from mail-wm0-x22a.google.com (mail-wm0-x22a.google.com. [2a00:1450:400c:c09::22a])
        by mx.google.com with ESMTPS id v29si5773346wra.109.2017.06.30.10.24.29
        for <std-proposals@isocpp.org>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Fri, 30 Jun 2017 10:24:29 -0700 (PDT)
Received-SPF: pass (google.com: domain of arthur.j.odwyer@gmail.com designates 2a00:1450:400c:c09::22a as permitted sender) client-ip=2a00:1450:400c:c09::22a;
Original-Received: by mail-wm0-x22a.google.com with SMTP id b184so52694889wme.1
        for <std-proposals@isocpp.org>; Fri, 30 Jun 2017 10:24:29 -0700 (PDT)
X-Received: by 10.80.146.79 with SMTP id j15mr6259191eda.17.1498843469022;
 Fri, 30 Jun 2017 10:24:29 -0700 (PDT)
Original-Received: by 10.80.173.204 with HTTP; Fri, 30 Jun 2017 10:24:28 -0700 (PDT)
In-Reply-To: <c039c5e5-13d0-4052-89f7-b2af50f1e0fc@isocpp.org>
X-Original-Sender: arthur.j.odwyer@gmail.com
X-Original-Authentication-Results: mx.google.com;       dkim=pass
 header.i=@gmail.com header.b=NV5dNQtf;       spf=pass (google.com: domain of
 arthur.j.odwyer@gmail.com designates 2a00:1450:400c:c09::22a as permitted
 sender) smtp.mailfrom=arthur.j.odwyer@gmail.com;       dmarc=pass (p=NONE
 sp=NONE dis=NONE) header.from=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:33042
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/33042>

--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">&lt;<a href=3D"mailto:target.san@gmail.com" target=3D"_blank">target.=
san@gmail.com</a>&gt;</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&#39;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&#39;s C++Now talk on strings</a> will=
 be interesting to you. Following that talk, I implemented his ideas for a =
&quot;nullable trait&quot; in my &quot;STL From Scratch&quot; under the nam=
e std::tombstone_traits&lt;T&gt;.</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&lt;T&gt;; it is literally a T.=C2=A0 If that&#39=
;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 &quot;moved-from state&quot;, 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&#39;s value is some variety of &quot;=
trivial value&quot; (e.g. the empty std::string) or some variety of &quot;e=
mpty value&quot; (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&#39;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&#39;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&#39;m thinking more from =
correctness and usability points of view.<br>The values used for sentinels =
are usually &quot;invalid&quot; type states. The closest example is what re=
mains of value if it&#39;s moved out. In such case destructor is trivial.<b=
r></div></div></blockquote><div><br></div><div>Well, that&#39;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 &quot;inva=
lid&quot; 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 &quot;billion-dollar mista=
ke&quot;.=C2=A0 And C++ gives us-the-user the power to correct that mistake=
!=C2=A0 Let&#39;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&amp; rhs) { ASSERT(rhs.p_); p_ =3D rhs.p_; }</div><div>=
=C2=A0 =C2=A0 int_ptr&amp; operator=3D(const int_ptr&amp; rhs) { ASSERT(p_ =
&amp;&amp; rhs.p_); p_ =3D rhs.p_; }</div><div>=C2=A0 =C2=A0 ~int_ptr() { A=
SSERT(p_); }</div><div>=C2=A0 =C2=A0 int&amp; 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&#39;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 &quot;I=
t is never NULL, and therefore it is always safe to dereference with operat=
or*().&quot; =C2=A0We have one &quot;narrow contract&quot; entrypoint that =
checks its arguments and throws (via the REQUIRE macro) if there&#39;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&#39;d build a space-efficient std::optional&l=
t;int_ptr&gt; using your mechanism.</b> =C2=A0I claim that you won&#39;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&#39;re never going to find a legal=
 value of int_ptr that is &quot;available&quot; for your use, just like you=
 couldn&#39;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&lt;int *&gt; =E2=80=94 an optional that co=
uld hold a nullable pointer or else be disengaged =E2=80=94 using your mech=
anism, you&#39;d find it impossible to distinguish between</div><div><br></=
div><div>=C2=A0 =C2=A0 std::optional&lt;int*&gt; o1 =3D std::nullopt; =C2=
=A0// this optional is disengaged</div><div><div>=C2=A0 =C2=A0 std::optiona=
l&lt;int*&gt; 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&#39;ve built isn&#39;t optional&lt;int*&gt;, becau=
se it can&#39;t hold &quot;a nullable pointer=C2=A0<i>or</i> disengaged.&qu=
ot; What you&#39;ve built is equivalent to either optional&lt;int_ptr&gt; (=
because it can hold &quot;a non-nullable pointer <i>or</i> disengaged&quot;=
) or simply int* (because it can hold &quot;a non-nullable pointer <i>or</i=
> null&quot;, which is to say, it can hold &quot;a nullable pointer&quot;).=
=C2=A0 This is why I said in my original response:=E2=80=94 If you mean &qu=
ot;T&quot;, just <i>say</i>=C2=A0&quot;T&quot;. Don&#39;t use the phrase &q=
uot;optional&lt;T&gt;&quot; to mean &quot;T&quot;; that&#39;s just going to=
 confuse people.</div><div><br></div><div>I&#39;ve addressed your comments =
about tombstone_traits in my response to Matthew Woehlke. Hopefully that wi=
ll help you see how it&#39;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&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/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--

.
