220 6112 <5e63fe81-ab33-4bbb-ab4c-305f8b90140a@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: Nicol Bolas <jmckesson@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: std::degenerate<> class template : primitive/enum
 types with a special "undefined" value
Date: Tue, 3 Sep 2013 05:47:43 -0700 (PDT)
Lines: 276
Approved: news@gmane.org
Message-ID: <5e63fe81-ab33-4bbb-ab4c-305f8b90140a@isocpp.org>
References: <18ab4801-260a-4228-8a7b-a71248b624e2@isocpp.org>
 <db1afcb0-7243-48f9-8b7b-fb0e9dbe99e6@isocpp.org>
 <77a1bdf8-1e0d-4294-b528-d08ba5403c98@isocpp.org>
 <023111c2-c983-407d-918f-39be42aa2949@isocpp.org>
 <cb3ab0e2-bea1-4741-997a-c3b3102cef7d@isocpp.org>
 <88ef15f1-6942-476e-b26c-6873ef6e6f0b@isocpp.org>
 <01900060-3aac-4645-a4a8-93b4e8760e42@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; 
	boundary="----=_Part_560_29383259.1378212463436"
X-Trace: ger.gmane.org 1378212469 6320 80.91.229.3 (3 Sep 2013 12:47:49 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Tue, 3 Sep 2013 12:47:49 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBCEKFTV6ZUMBB4NUS6IQKGQEHSALEGA@isocpp.org Tue Sep 03 14:47:52 2013
Return-path: <std-proposals+bncBCEKFTV6ZUMBB4NUS6IQKGQEHSALEGA@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-ie0-f199.google.com ([209.85.223.199])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBCEKFTV6ZUMBB4NUS6IQKGQEHSALEGA@isocpp.org>)
	id 1VGq1K-0001RY-GI
	for gclcip-std-proposals@m.gmane.org; Tue, 03 Sep 2013 14:47:46 +0200
Original-Received: by mail-ie0-f199.google.com with SMTP id 9sf23158215iec.10
        for <gclcip-std-proposals@m.gmane.org>; Tue, 03 Sep 2013 05:47:45 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        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
         :content-type;
        bh=4YGw+3Pyzw+ou6DjKFrCokZBpd3W2cbMAoHKLVXk7OI=;
        b=l7HzGZK1EISECiMWmXg82s9ABRtGrzo7v/iAAkUHLJ1zWcxoObCv+EqI9/dZQTbJ6u
         DjtIzEOfBmMrnqRG8OYUPRfx6b8wLzjY15Pp8+ttaDsw1icE0Ljddaj+WSZx3wqjU8ue
         cXv+ucKTk3E7LbND2K/YimjHLTGDvQxVmx8gqtq84IRg2HO8kwUQ7FwLD15cuMih73bY
         ovmPMIVSM21wj8YPH50YlDFEi4q35kL6YjOMOCBoTURhCfuQQq7Bf1CBIo7SRIU0o8Xl
         2hOmHBJ3hdGTR37fWQ9r4uA9yfaUipSr0tyvU9DEMC5dPGF3l+kpIWjzGltEMWZKPe3W
         eR8Q==
X-Received: by 10.42.137.1 with SMTP id w1mr14953187ict.8.1378212465550;
        Tue, 03 Sep 2013 05:47:45 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.50.23.17 with SMTP id i17ls2090694igf.8.canary; Tue, 03 Sep
 2013 05:47:44 -0700 (PDT)
X-Received: by 10.50.40.103 with SMTP id w7mr827405igk.7.1378212464886;
        Tue, 03 Sep 2013 05:47:44 -0700 (PDT)
In-Reply-To: <01900060-3aac-4645-a4a8-93b4e8760e42@isocpp.org>
X-Original-Sender: jmckesson@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: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:6112
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/6112>

------=_Part_560_29383259.1378212463436
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable



On Tuesday, September 3, 2013 5:18:04 AM UTC-7, the.ultim...@gmail.com=20
wrote:
>
>
> Enumerations are unfortunately not extensible
>>
>
> I think the problem is not in what you're saying here, but in the cause=
=20
> thereof. A variable of a C++ enumeration can have any encodable value, no=
t=20
> just the ones you list in the enum [class] definition. Therefore, they=20
> cannot be extensible.
>

I fail to see how those last two sentences have anything to do with one=20
another.

Are you legally allowed to cast an integer to a value of enum type? Yes,=20
assuming it fits into the underlying type. The set of integers that could=
=20
be stored in an enumeration have nothing to do with what the enumerator=20
values are.

So why does the fact that an enum type could take on values outside of the=
=20
enumerators have anything to do with whether or not the list of enumerators=
=20
for an enum type could partially come from another enum type?

3. You make it explicit in the type that you are abusing one of the values,=
=20
> instead of littering your code with a symbolic constant.
>

If that symbolic constant were actually *part* of the enumeration, it=20
wouldn't be "abusing" anything. You're only abusing it because you have no=
=20
other way to achieve what you want.
=20

> I can understand the value of an optimized optional.
>>
>
> So do I, but only Vicente said that it was an optimized optional.
>

Whether you want to admit it or not, it serves the same functional purpose=
=20
as optional. It creates a type which may or may not be considered to have a=
=20
valid value of some specific type. It has a value which is considered to be=
=20
"not a real value". It has value semantics. And so forth.

Indeed, I would go so far as to say that the (unnecessary) differences in=
=20
interface between your class and `optional` are *detriments* of your class,=
=20
not strengths. It's a half-finished optional that lacks many of the traits=
=20
of the real class.

I said that it should be a "drop-in replacement" for it. degenerate<T,v>act=
ually implements an equivalent of std::optional<T=20
> - {v}>, in the case of when you're not using all the values of a type.
> =20
>
>> But that should be approached as a question of how to let the user=20
>> specify to std::optional that the optimization should apply. Then there=
=20
>> is no new interface. (And, IMO, the optimization should apply to=20
>> floating-point types as well, whose values cannot be passed as template=
=20
>> non-type parameters.)
>>
>
> It is impossible to steal a value from a type whose set of values take up=
=20
> all the storage space allocated to the type, and still implement the righ=
t=20
> semantics for optional<T>.
>

How do you figure that?

If you're making a space-optimized `optional` variation, then by definition=
=20
it would *not* be the same type as `optional<T>`. It could use the same=20
name: `optional<T, ...>`, where ... is whatever you do to denote the value=
=20
that represents "not a value". It could be some kind of functor, a type=20
that provides constexpr functions, or whatever.

The point is that `optional<T>` would have no more relation to `optional<T,=
=20
....>` than it would to `optional<U>`. So there would be no problem with=20
stealing a value for `optional<T>` because that's not how an `optional<T>`=
=20
would ever work. Only the optimized form would "steal a value".

Another approach could look like struct without_value< E, T =3D E::type > {=
=20
>> typedef T type; =85 }; where T is either a numeric type or has a member=
=20
>> type which is numeric, and E::value is the excluded value. (Such a=20
>> definition would support a single std::integral_constant argument.) This=
=20
>> could assert to a container or algorithm that the given value will not b=
e=20
>> used, and the given type should be allocated. It would be a template fla=
g=20
>> rather than a proxy with tricky conversion semantics =97 without_valuewo=
uld not be ODR-used, but ODR-use would be the inevitable result of=20
>> passing it somewhere it's not supported. It would support floating-point=
=20
>> types and NaN. And it would actually be a numeric invariant; the concept=
=20
>> could extend to other hints such as that an argument must be in a numeri=
c=20
>> range. A generic way to pass numeric hints to algorithms and containers =
is=20
>> something currently lacking, but probably helpful to scientific=20
>> applications.
>>
>
> These are too few words for such a lot of thinking :) If I may summarize,=
=20
> would you say that C++ lacks the ability to easily create "sparse" types.=
=20
> (with the above ad hoc definition of "sparse") and as such cannot reason =
on=20
> the "actually used set of values of types"?
>

I see no reason why one should lead to the other. A type is whatever you=20
want it to be. If you want to create a type that behaves like an `int`, but=
=20
considers the number -1 to be "not a real value", you can. And you can=20
"reason" about such types just fine.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_560_29383259.1378212463436
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, September 3, 2013 5:18:04 AM UTC-7, th=
e.ultim...@gmail.com wrote:<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"><br><blockquote class=3D"gmail_quote" style=3D"margin:0pt 0pt=
 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div di=
r=3D"ltr"><div>Enumerations are unfortunately not extensible</div></div></b=
lockquote><div><br>I think the problem is not in what you're saying here, b=
ut in the cause thereof. A variable of a C++ enumeration can have any encod=
able value, not just the ones you list in the enum [class] definition. Ther=
efore, they cannot be extensible.</div></div></blockquote><div><br>I fail t=
o see how those last two sentences have anything to do with one another.<br=
><br>Are
 you legally allowed to cast an integer to a value of enum type? Yes,=20
assuming it fits into the underlying type. The set of integers that=20
could be stored in an enumeration have nothing to do with what the=20
enumerator values are.<br><br>So why does the fact that=20
an enum type could take on values outside of the enumerators have=20
anything to do with whether or not the list of enumerators for an enum=20
type could partially come from another enum type?<br><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>3. You ma=
ke it explicit in the type that you are abusing one of the values, instead =
of littering your code with a symbolic constant.<br></div></div></blockquot=
e><div><br>If that symbolic constant were actually <i>part</i> of the enume=
ration, it wouldn't be "abusing" anything. You're only abusing it because y=
ou have no other way to achieve what you want.<br>&nbsp;</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
 #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0pt 0pt 0pt 0.8ex;border-left:1px solid =
rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>I can understand t=
he value of an optimized <span style=3D"font-family:courier new,monospace">=
optional</span>.<br></div></div></blockquote><div><br>So do I, but only Vic=
ente said that it was an optimized optional.</div></div></blockquote><div><=
br>Whether you want to admit it or not, it serves the same functional purpo=
se as optional. It creates a type which may or may not be considered to hav=
e a valid value of some specific type. It has a value which is considered t=
o be "not a real value". It has value semantics. And so forth.<br><br>Indee=
d, I would go so far as to say that the (unnecessary) differences in interf=
ace between your class and `optional` are <i>detriments</i> of your class, =
not strengths. It's a half-finished optional that lacks many of the traits =
of the real class.<br><br></div><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"><div>I said that it should be a "drop-in replacement" fo=
r it. <span style=3D"font-family:courier new,monospace">degenerate&lt;T,v&g=
t;</span> actually implements an equivalent of <span style=3D"font-family:c=
ourier new,monospace">std::optional&lt;T - {v}&gt;</span>, in the case of w=
hen you're not using all the values of a type.<br>&nbsp;</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0pt 0pt 0pt 0.8ex;border-left:1px soli=
d rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>But that should =
be approached as a question of how to let the user specify to <span style=
=3D"font-family:courier new,monospace">std::optional</span> that the optimi=
zation should apply. Then there is no new interface. (And, IMO, the optimiz=
ation should apply to floating-point types as well, whose values cannot be =
passed as template non-type parameters.)<br></div></div></blockquote><div><=
br>It is impossible to steal a value from a type whose set of values take u=
p all the storage space allocated to the type, and still implement the righ=
t semantics for optional&lt;T&gt;.</div></div></blockquote><div><br>How do =
you figure that?<br><br>If you're making a space-optimized `optional` varia=
tion, then by definition it would <i>not</i> be the same type as `optional&=
lt;T&gt;`. It could use the same name: `optional&lt;T, ...&gt;`, where ... =
is whatever you do to denote the value that represents "not a value". It co=
uld be some kind of functor, a type that provides constexpr functions, or w=
hatever.<br><br>The point is that `optional&lt;T&gt;` would have no more re=
lation to `optional&lt;T, ...&gt;` than it would to `optional&lt;U&gt;`. So=
 there would be no problem with stealing a value for `optional&lt;T&gt;` be=
cause that's not how an `optional&lt;T&gt;` would ever work. Only the optim=
ized form would "steal a value".<br><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204)=
;padding-left:1ex"><div dir=3D"ltr"><div>Another approach could look like <=
span style=3D"font-family:courier new,monospace">struct without_value&lt; E=
, T =3D E::type &gt; { typedef T type; =85 };</span><font face=3D"arial,san=
s-serif"> where T is either </font>a numeric type or has a member <span sty=
le=3D"font-family:courier new,monospace">type</span> which is numeric, and =
<span style=3D"font-family:courier new,monospace">E::value</span> is the ex=
cluded value. (Such a definition would support a single <span style=3D"font=
-family:courier new,monospace">std::integral_constant</span> argument.) Thi=
s could assert to a container or algorithm that the given value will not be=
 used, and the given type should be allocated. It would be a template flag =
rather than a proxy with tricky conversion semantics =97 <span style=3D"fon=
t-family:courier new,monospace">without_value</span> would not be ODR-used,=
 but ODR-use would be the inevitable result of passing it somewhere it's no=
t supported. It would support floating-point types and <span style=3D"font-=
family:courier new,monospace">NaN</span>. And it would actually be a numeri=
c invariant; the concept could extend to other hints such as that an argume=
nt must be in a numeric range. A generic way to pass numeric hints to algor=
ithms and containers is something currently lacking, but probably helpful t=
o scientific applications.<br></div></div></blockquote><div><br>These are t=
oo few words for such a lot of thinking :) If I may summarize, would you sa=
y that C++ lacks the ability to easily create "sparse" types. (with the abo=
ve ad hoc definition of "sparse") and as such cannot reason on the "actuall=
y used set of values of types"?<br></div></div></blockquote><div><br>I see =
no reason why one should lead to the other. A type is whatever you want it =
to be. If you want to create a type that behaves like an `int`, but conside=
rs the number -1 to be "not a real value", you can. And you can "reason" ab=
out such types just fine.<br></div></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_560_29383259.1378212463436--

.
