Topic: Thoughts on N4542 std::variant
Author: Markus Grech <markus.grech@gmail.com>
Date: Fri, 5 Jun 2015 01:17:51 -0700 (PDT)
Raw View
------=_Part_112_1589013200.1433492271652
Content-Type: multipart/alternative;
boundary="----=_Part_113_438218308.1433492271652"
------=_Part_113_438218308.1433492271652
Content-Type: text/plain; charset=UTF-8
Hi everyone,
I would like to voice my concerns about default construction of
std::variant and std::monostate. The proposal did not make clear to me why
default constructed empty state is such a big issue in the first place and
the current alternative suffers from significant drawbacks:
- To me it is very surprising that variant tries to default-construct
the first type. Why not the 2nd, 5th type? I'd rather have variant have no
default constructor than some arbitrary decision.
- It is yet another special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember "Oh, I have to use
this std::monostate workaround if my type is not default constructible!".
*Hacks* (another spelling for 'workaround') are *bad*.
- It does not play well with changes. Imagine if the user-defined type
that was previously default constructible has its default constructor
removed. Now the users needs to add std::monostate all over the place and
fix up all the indices for index-based access.
There needs to be a better solution. I do think that having an empty state
semantically fails at the idea of variant in the first place ("either A or
B", not "either A, B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues that IMHO
deserve another look.
Markus
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_113_438218308.1433492271652
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi everyone,<div><br></div><div>I would like to voice my c=
oncerns about default construction of std::variant and std::monostate. The =
proposal did not make clear to me why default constructed empty state is su=
ch a big issue in the first place and the current alternative suffers from =
significant drawbacks:</div><div><ul><li><span style=3D"line-height: normal=
;">To me it is very surprising that variant tries to default-construct the =
first type. Why not the 2nd, 5th type? I'd rather have variant have no defa=
ult constructor than some arbitrary decision.</span></li><li><span style=3D=
"line-height: normal;">It is yet another special case that users need to be=
taught about and frankly, it's not pretty either. Users have to remember "=
Oh, I have to use this std::monostate workaround if my type is not default =
constructible!". <i>Hacks</i> (another spelling for 'workaround') are <i>ba=
d</i>.</span></li><li><span style=3D"line-height: normal;">It does not play=
well with changes. Imagine if the user-defined type that was previously de=
fault constructible has its default constructor removed. Now the users need=
s to add std::monostate all over the place and fix up all the indices for i=
ndex-based access.</span></li></ul><div>There needs to be a better solution=
.. I do think that having an empty state semantically fails at the idea of v=
ariant in the first place ("either A or B", not "either A, B or empty"), bu=
t it is not the end of the world. The current std::monostate design however=
has significant issues that IMHO deserve another look.</div></div><div><br=
></div><div>Markus</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_113_438218308.1433492271652--
------=_Part_112_1589013200.1433492271652--
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Fri, 5 Jun 2015 13:21:58 +0200
Raw View
--Apple-Mail=_064B7A5D-ED0B-4FC0-9699-8562077EC21D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 05 Jun 2015, at 10:17 , Markus Grech <markus.grech@gmail.com> wrote:
>=20
> Hi everyone,
>=20
> I would like to voice my concerns about default construction of std::vari=
ant and std::monostate. The proposal did not make clear to me why default c=
onstructed empty state is such a big issue in the first place and the curre=
nt alternative suffers from significant drawbacks:
> To me it is very surprising that variant tries to default-construct the f=
irst type. Why not the 2nd, 5th type? I'd rather have variant have no defau=
lt constructor than some arbitrary decision.
Agreed completely. This seems like an arbitrary decision just for the sake =
of having a DefaultConstructible variant. I am sure it would not be surpris=
ing to anybody at all if someone were to change the signature of a variant =
by adding a new type at the front and suddenly having all default construct=
ed variants completely change the behavior of the program with no warnings =
or errors.
> It is yet another special case that users need to be taught about and fra=
nkly, it's not pretty either. Users have to remember "Oh, I have to use thi=
s std::monostate workaround if my type is not default constructible!". Hack=
s (another spelling for 'workaround') are bad.
> It does not play well with changes. Imagine if the user-defined type that=
was previously default constructible has its default constructor removed. =
Now the users needs to add std::monostate all over the place and fix up all=
the indices for index-based access.
Also considering =E2=80=9CMonostate=E2=80=9D is a software design pattern t=
hat is completely unrelated
> There needs to be a better solution. I do think that having an empty stat=
e semantically fails at the idea of variant in the first place ("either A o=
r B", not "either A, B or empty"), but it is not the end of the world. The =
current std::monostate design however has significant issues that IMHO dese=
rve another look.
Although I do think the empty state is a terrible decision that needlessly =
complicates the interface. We already have a proposed type that can be empt=
y and it=E2=80=99s called optional. That role is served. Just because some =
people think it=E2=80=99s a good idea to have throwing move constructors me=
ans everybody using std::variant now has to keep this tiny detail in their =
head all the time. Getting rid of this just plays well with all the advice =
out there to make move operations nothrow.
I=E2=80=99d rather have a variant that cannot store every type under the su=
n, which is something the compiler can enforce and inform me about before i=
t=E2=80=99s too late, than having to constantly worry about it being possib=
ly empty.
This is insane!
--=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/.
--Apple-Mail=_064B7A5D-ED0B-4FC0-9699-8562077EC21D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 05 Jun 2015, at 1=
0:17 , Markus Grech <<a href=3D"mailto:markus.grech@gmail.com" class=3D"=
">markus.grech@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange=
-newline"><div class=3D""><div dir=3D"ltr" class=3D"">Hi everyone,<div clas=
s=3D""><br class=3D""></div><div class=3D"">I would like to voice my concer=
ns about default construction of std::variant and std::monostate. The propo=
sal did not make clear to me why default constructed empty state is such a =
big issue in the first place and the current alternative suffers from signi=
ficant drawbacks:</div><div class=3D""><ul class=3D""><li class=3D""><span =
style=3D"line-height: normal;" class=3D"">To me it is very surprising that =
variant tries to default-construct the first type. Why not the 2nd, 5th typ=
e? I'd rather have variant have no default constructor than some arbitrary =
decision.</span></li></ul></div></div></div></blockquote><div>Agreed comple=
tely. This seems like an arbitrary decision just for the sake of having a D=
efaultConstructible variant. I am sure it would not be surprising to anybod=
y at all if someone were to change the signature of a variant by adding a n=
ew type at the front and suddenly having all default constructed variants c=
ompletely change the behavior of the program with no warnings or errors.</d=
iv><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" cl=
ass=3D""><div class=3D""><ul class=3D""><li class=3D""><span style=3D"line-=
height: normal;" class=3D"">It is yet another special case that users need =
to be taught about and frankly, it's not pretty either. Users have to remem=
ber "Oh, I have to use this std::monostate workaround if my type is not def=
ault constructible!". <i class=3D"">Hacks</i> (another spelling for 'workar=
ound') are <i class=3D"">bad</i>.</span></li><li class=3D""><span style=3D"=
line-height: normal;" class=3D"">It does not play well with changes. Imagin=
e if the user-defined type that was previously default constructible has it=
s default constructor removed. Now the users needs to add std::monostate al=
l over the place and fix up all the indices for index-based access.</span><=
/li></ul></div></div></div></blockquote>Also considering =E2=80=9CMonostate=
=E2=80=9D is a software design pattern that is completely unrelated</div><d=
iv><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div=
dir=3D"ltr" class=3D""><div class=3D""><div class=3D"">There needs to be a=
better solution. I do think that having an empty state semantically fails =
at the idea of variant in the first place ("either A or B", not "either A, =
B or empty"), but it is not the end of the world. The current std::monostat=
e design however has significant issues that IMHO deserve another look.</di=
v></div></div></div></blockquote><div><br class=3D""></div></div><div>Altho=
ugh I do think the empty state is a terrible decision that needlessly compl=
icates the interface. We already have a proposed type that can be empty and=
it=E2=80=99s called optional. That role is served. Just because some peopl=
e think it=E2=80=99s a good idea to have throwing move constructors means e=
verybody using std::variant now has to keep this tiny detail in their head =
all the time. Getting rid of this just plays well with all the advice out t=
here to make move operations nothrow.</div><div><br class=3D""></div><div>I=
=E2=80=99d rather have a variant that cannot store every type under the sun=
, which is something the compiler can enforce and inform me about before it=
=E2=80=99s too late, than having to constantly worry about it being possibl=
y empty.</div><div><br class=3D""></div><div>This is insane!</div><div><br =
class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_064B7A5D-ED0B-4FC0-9699-8562077EC21D--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 08:52:04 -0700 (PDT)
Raw View
------=_Part_1229_680187108.1433519524128
Content-Type: multipart/alternative;
boundary="----=_Part_1230_849271175.1433519524128"
------=_Part_1230_849271175.1433519524128
Content-Type: text/plain; charset=UTF-8
On Friday, June 5, 2015 at 4:17:51 AM UTC-4, Markus Grech wrote:
>
> Hi everyone,
>
> I would like to voice my concerns about default construction of
> std::variant and std::monostate. The proposal did not make clear to me why
> default constructed empty state is such a big issue in the first place and
> the current alternative suffers from significant drawbacks:
>
> - To me it is very surprising that variant tries to default-construct
> the first type. Why not the 2nd, 5th type? I'd rather have variant have no
> default constructor than some arbitrary decision.
> - It is yet another special case that users need to be taught about
> and frankly, it's not pretty either. Users have to remember "Oh, I have to
> use this std::monostate workaround if my type is not default
> constructible!". *Hacks* (another spelling for 'workaround') are *bad*.
> - It does not play well with changes. Imagine if the user-defined type
> that was previously default constructible has its default constructor
> removed. Now the users needs to add std::monostate all over the place and
> fix up all the indices for index-based access.
>
>
Well... you could just pretend it doesn't have a default constructor ;)
I'm being at least partially serious here. If you would prefer not to rely
on the default constructor's behavior, then just don't use it. Sure, the
compiler won't error if you use it by accident, which is unfortunate. But
you are free to avoid the constructor if you so desire.
Without default construction, it would be exceedingly difficult to create
std::arrays of variants, as well as other types that don't make it easy to
avoid default construction. You might say that those things are problems
that should be solved in and of themselves. But we have to live within the
limitations of the language that exists, not the language we would like to
use.
I do think that having an empty state semantically fails at the idea of
> variant in the first place ("either A or B", not "either A, B or empty"),
> but it is not the end of the world. The current std::monostate design
> however has significant issues that IMHO deserve another look.
>
>
Monostate and default construction are separate issues. The only design
consideration they share is the idea of default construction making the
variant empty. Which is a bad idea.
The monostate design (as I understand it) is purely as an error-handling
mechanism. Variants are intended to only assume this state if a
copy/emplace/etc operation could not be performed. Thus, if you want
"empty" to be a legitimate state for a variant, that's something you have
to provide as one of the possible variant types.
Think of "monostate" as "invalid"; that's how the proposal describes its
behavior. There are numerous operations where the precondition is `variant
parameter is valid`, so you can't even call them unless the variant is
valid. I think this is a good thing. It means that you don't have to
consider the possibility of an empty variant unless it contains a type that
can throw on copy/move/emplace. That is, its fairly easy to avoid.
`monostate` and invalid are, and should be, rare conditions.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1230_849271175.1433519524128
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 5, 2015 at 4:17:51 AM UTC-4, Markus Grech =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Hi ever=
yone,<div><br></div><div>I would like to voice my concerns about default co=
nstruction of std::variant and std::monostate. The proposal did not make cl=
ear to me why default constructed empty state is such a big issue in the fi=
rst place and the current alternative suffers from significant drawbacks:</=
div><div><ul><li><span style=3D"line-height:normal">To me it is very surpri=
sing that variant tries to default-construct the first type. Why not the 2n=
d, 5th type? I'd rather have variant have no default constructor than some =
arbitrary decision.</span></li><li><span style=3D"line-height:normal">It is=
yet another special case that users need to be taught about and frankly, i=
t's not pretty either. Users have to remember "Oh, I have to use this std::=
monostate workaround if my type is not default constructible!". <i>Hacks</i=
> (another spelling for 'workaround') are <i>bad</i>.</span></li><li><span =
style=3D"line-height:normal">It does not play well with changes. Imagine if=
the user-defined type that was previously default constructible has its de=
fault constructor removed. Now the users needs to add std::monostate all ov=
er the place and fix up all the indices for index-based access.</span></li>=
</ul></div></div></blockquote><div><br>Well... you could just pretend it do=
esn't have a default constructor ;)<br><br>I'm being at least partially ser=
ious here.
If you would prefer not to rely on the default constructor's behavior,=20
then just don't use it. Sure, the compiler won't error if you use it by=20
accident, which is unfortunate. But you are free to avoid the constructor i=
f you so desire.<br><br>Without default construction, it would be exceeding=
ly difficult to create std::arrays of variants, as well as other types that=
don't make it easy to avoid default construction. You might say that those=
things are problems that should be solved in and of themselves. But we hav=
e to live within the limitations of the language that exists, not the langu=
age we would like to use.<br><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div><div>I do think that having an empty state s=
emantically fails at the idea of variant in the first place ("either A or B=
", not "either A, B or empty"), but it is not the end of the world. The cur=
rent std::monostate design however has significant issues that IMHO deserve=
another look.</div></div><br></div></blockquote><div><br>Monostate and def=
ault construction are separate issues. The only design consideration they s=
hare is the idea of default construction making the variant empty. Which is=
a bad idea.<br><br>The monostate design (as I understand it) is purely as =
an error-handling mechanism. Variants are intended to only assume this stat=
e if a copy/emplace/etc operation could not be performed. Thus, if you want=
"empty" to be a legitimate state for a variant, that's something you have =
to provide as one of the possible variant types.<br><br>Think of "monostate=
" as "invalid"; that's how the proposal describes its behavior. There are n=
umerous operations where the precondition is `variant parameter is valid`, =
so you can't even call them unless the variant is valid. I think this is a =
good thing. It means that you don't have to consider the possibility of an =
empty variant unless it contains a type that can throw on copy/move/emplace=
.. That is, its fairly easy to avoid.<br><br>`monostate` and invalid are, an=
d should be, rare conditions.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1230_849271175.1433519524128--
------=_Part_1229_680187108.1433519524128--
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Fri, 05 Jun 2015 11:53:42 -0400
Raw View
On 2015-06-05 04:17, Markus Grech wrote:
> I would like to voice my concerns about default construction of
> std::variant and std::monostate. The proposal did not make clear to me why
> default constructed empty state is such a big issue in the first place and
> the current alternative suffers from significant drawbacks:
>
> - To me it is very surprising that variant tries to default-construct
> the first type. Why not the 2nd, 5th type? I'd rather have variant have no
> default constructor than some arbitrary decision.
While QVariant is probably closer to boost::any, it may still be worth
considering the precedent: QVariant has a null state.
(I agree, having default construction use the first type seems...
arbitrary.)
--
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Alisdair Meredith <alisdairm@me.com>
Date: Fri, 05 Jun 2015 12:02:39 -0400
Raw View
Default construction initializing the first type is modeled on the way
that a union works in the language, where the first element of the
union is value-initialized if a union needs value initialization.
If a variant is thought of as =E2=80=98a union that knows its active elemen=
t=E2=80=99,
then I think this makes sense. If the variant is thought of as something
quite distinct from C++ unions, then I agree it might seem arbitrary.
AlisdairM
> On Jun 5, 2015, at 11:53 AM, Matthew Woehlke <mw_triad@users.sourceforge.=
net> wrote:
>=20
> On 2015-06-05 04:17, Markus Grech wrote:
>> I would like to voice my concerns about default construction of=20
>> std::variant and std::monostate. The proposal did not make clear to me w=
hy=20
>> default constructed empty state is such a big issue in the first place a=
nd=20
>> the current alternative suffers from significant drawbacks:
>>=20
>> - To me it is very surprising that variant tries to default-construct=
=20
>> the first type. Why not the 2nd, 5th type? I'd rather have variant hav=
e no=20
>> default constructor than some arbitrary decision.
>=20
> While QVariant is probably closer to boost::any, it may still be worth
> considering the precedent: QVariant has a null state.
>=20
> (I agree, having default construction use the first type seems...
> arbitrary.)
>=20
> --=20
> Matthew
>=20
> --=20
>=20
> ---=20
> You received this message because you are subscribed to the Google Groups=
"ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-propo=
sals/.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Izzy Coding <matthew.i.greenwood@gmail.com>
Date: Sat, 6 Jun 2015 01:39:59 -0700 (PDT)
Raw View
------=_Part_379_318870196.1433579999336
Content-Type: text/plain; charset=UTF-8
Surely a std::variant should only be default constructable if all its allowed types are default constructable?
Also I would suggest that default construction should initialise to being empty which could be checked using a member function empty() like most other STL container?
Just my opinion
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_379_318870196.1433579999336--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 06 Jun 2015 13:42:29 +0200
Raw View
On Saturday 06 June 2015 01:39:59 Izzy Coding wrote:
> Surely a std::variant should only be default constructable if all its
> allowed types are default constructable?
>
> Also I would suggest that default construction should initialise to being
> empty which could be checked using a member function empty() like most
> other STL container?
If std::variant, as described, should operate like the unrestricted union of
the types it contains, then it should have a default constructor under the
same rules. If the union has the default constructor deleted, so should
std::variant.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Farid Mehrabi <farid.mehrabi@gmail.com>
Date: Sat, 6 Jun 2015 20:15:44 +0430
Raw View
--001a1135a2e8a523e60517db4f2c
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
What about the new extended union(i.e don`t generate special members if any
field lacks)?
The last version of boost::variant that I am aware of calls for thoughts on
having a blank state.
So what is wrong with having a null state?
I personally prefer to implement std::optional<T> in terms of
std::variant<T>. I also think that std::function can be defined in terms
of a null-able std::variant type.
regards,
FM.
2015-06-05 20:32 GMT+04:30 Alisdair Meredith <alisdairm@me.com>:
> Default construction initializing the first type is modeled on the way
> that a union works in the language, where the first element of the
> union is value-initialized if a union needs value initialization.
>
> If a variant is thought of as =E2=80=98a union that knows its active elem=
ent=E2=80=99,
> then I think this makes sense. If the variant is thought of as something
> quite distinct from C++ unions, then I agree it might seem arbitrary.
>
> AlisdairM
>
> > On Jun 5, 2015, at 11:53 AM, Matthew Woehlke <
> mw_triad@users.sourceforge.net> wrote:
> >
> > On 2015-06-05 04:17, Markus Grech wrote:
> >> I would like to voice my concerns about default construction of
> >> std::variant and std::monostate. The proposal did not make clear to me
> why
> >> default constructed empty state is such a big issue in the first place
> and
> >> the current alternative suffers from significant drawbacks:
> >>
> >> - To me it is very surprising that variant tries to default-construc=
t
> >> the first type. Why not the 2nd, 5th type? I'd rather have variant
> have no
> >> default constructor than some arbitrary decision.
> >
> > While QVariant is probably closer to boost::any, it may still be worth
> > considering the precedent: QVariant has a null state.
> >
> > (I agree, having default construction use the first type seems...
> > arbitrary.)
> >
> > --
> > 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.
> > Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
how am I supposed to end the twisted road of your hair in such a dark
night??
unless the candle of your face does shed some light upon my way!!!
--=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/.
--001a1135a2e8a523e60517db4f2c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"rtl"><div class=3D"gmail_default" style=3D"font-family:arial na=
rrow,sans-serif;font-size:large" dir=3D"ltr">What about the new extended un=
ion(i.e don`t generate special members if any field lacks)?</div><div class=
=3D"gmail_default" style=3D"font-family:arial narrow,sans-serif;font-size:l=
arge" dir=3D"ltr">The last version of boost::variant that I am aware of cal=
ls for thoughts on having a blank state.</div><div class=3D"gmail_default" =
style=3D"font-family:arial narrow,sans-serif;font-size:large" dir=3D"ltr">S=
o what is wrong with having a null state?</div><div class=3D"gmail_default"=
style=3D"font-family:arial narrow,sans-serif;font-size:large" dir=3D"ltr">=
I personally prefer to implement std::optional<T> in terms of std::va=
riant<T>. I also think =C2=A0that std::function can be defined in ter=
ms of a null-able std::variant type.</div><div class=3D"gmail_default" styl=
e=3D"font-family:arial narrow,sans-serif;font-size:large" dir=3D"ltr"><br><=
/div><div class=3D"gmail_default" style=3D"font-family:arial narrow,sans-se=
rif;font-size:large" dir=3D"ltr">regards,</div><div class=3D"gmail_default"=
style=3D"font-family:arial narrow,sans-serif;font-size:large" dir=3D"ltr">=
FM.</div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote"><d=
iv dir=3D"ltr">2015-06-05 20:32 GMT+04:30 Alisdair Meredith <span dir=3D"lt=
r"><<a href=3D"mailto:alisdairm@me.com" target=3D"_blank">alisdairm@me.c=
om</a>></span>:</div><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Default construction=
initializing the first type is modeled on the way<br>
that a union works in the language, where the first element of the<br>
union is value-initialized if a union needs value initialization.<br>
<br>
If a variant is thought of as =E2=80=98a union that knows its active elemen=
t=E2=80=99,<br>
then I think this makes sense.=C2=A0 If the variant is thought of as someth=
ing<br>
quite distinct from C++ unions, then I agree it might seem arbitrary.<br>
<br>
AlisdairM<br>
<div class=3D"HOEnZb"><div class=3D"h5"><br>
> On Jun 5, 2015, at 11:53 AM, Matthew Woehlke <<a href=3D"mailto:mw_=
triad@users.sourceforge.net">mw_triad@users.sourceforge.net</a>> wrote:<=
br>
><br>
> On 2015-06-05 04:17, Markus Grech wrote:<br>
>> I would like to voice my concerns about default construction of<br=
>
>> std::variant and std::monostate. The proposal did not make clear t=
o me why<br>
>> default constructed empty state is such a big issue in the first p=
lace and<br>
>> the current alternative suffers from significant drawbacks:<br>
>><br>
>>=C2=A0 =C2=A0- To me it is very surprising that variant tries to de=
fault-construct<br>
>>=C2=A0 =C2=A0the first type. Why not the 2nd, 5th type? I'd rat=
her have variant have no<br>
>>=C2=A0 =C2=A0default constructor than some arbitrary decision.<br>
><br>
> While QVariant is probably closer to boost::any, it may still be worth=
<br>
> considering the precedent: QVariant has a null state.<br>
><br>
> (I agree, having default construction use the first type seems...<br>
> arbitrary.)<br>
><br>
> --<br>
> Matthew<br>
><br>
> --<br>
><br>
> ---<br>
> You received this message because you are subscribed to the Google Gro=
ups "ISO C++ Standard - Future Proposals" group.<br>
> To unsubscribe from this group and stop receiving emails from it, send=
an email to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">std-=
proposals+unsubscribe@isocpp.org</a>.<br>
> To post to this group, send email to <a href=3D"mailto:std-proposals@i=
socpp.org">std-proposals@isocpp.org</a>.<br>
> Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/g=
roup/std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.or=
g/group/std-proposals/</a>.<br>
<br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br><br clear=3D"all"><div><br></div>-- <br>=
<div class=3D"gmail_signature"><div dir=3D"rtl"><div><div dir=3D"ltr">how a=
m I supposed to end the twisted road of=C2=A0 your hair in such a dark nigh=
t??<br>unless the candle of your face does shed some light upon my way!!!<b=
r></div></div></div></div>
</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1135a2e8a523e60517db4f2c--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 6 Jun 2015 10:12:33 -0700 (PDT)
Raw View
------=_Part_664_1323852344.1433610753028
Content-Type: multipart/alternative;
boundary="----=_Part_665_2055762688.1433610753028"
------=_Part_665_2055762688.1433610753028
Content-Type: text/plain; charset=UTF-8
On Saturday, June 6, 2015 at 11:52:37 AM UTC-4, Farid Mehrabi wrote:
>
> What about the new extended union(i.e don`t generate special members if
> any field lacks)?
> The last version of boost::variant that I am aware of calls for thoughts
> on having a blank state.
> So what is wrong with having a null state?'
>
boost::variant doesn't have a blank state. You can *give* it a blank state,
but only by putting `boost::blank` in the argument list. But that's a user
choice, not something every variant has.
Consider two variants. Variant A forces a null state, while Variant B (like
boost::variant) allows you to have one if you want, but makes it an
argument in the list.
Let's say I'm in a situation where all my variants are filled. I don't
default construct anything, and none of my move constructors throw. So why
should my visitation code *have* to consider the possibility of being
empty? Why should my visitor functors have to consider `std::blank_t` or
whatever as one of the choices, when the variant will never have that
value? Variant A is decidedly less useful to me than Variant B.
Now, let's consider the situation where I want a variant to potentially be
empty. Well, Variant A gives it to me by default. For Variant B... I just
put it `std::blank_t` in the template argument list, and it's there.
`std::variant` is nice in that it doesn't really have an "empty" state; it
has an "invalid" state. It only gets this state when copy/move fails in
some not-easily-recovered way.
> I personally prefer to implement std::optional<T> in terms of
> std::variant<T>. I also think that std::function can be defined in terms
> of a null-able std::variant type.
>
.... why? It's highly unlikely that a person who uses `optional` will
suddenly change it to `variant` and want all his code to work without
changes. It's also unlikely that template code that accepts `optional<T>`
would be able to reasonably work with `variant<T...>`.
So what's the need for such arbitrary compatibility?
Some people like to think of `optional` as a nullable variant with only one
non-null state. Other people think of it as a container that could have
zero or one element. Neither view encapsulates how *users* will want to use
the object. This kind of high-concept thinking can lead to very bad
interfaces.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_665_2055762688.1433610753028
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, June 6, 2015 at 11:52:37 AM UTC-4, Fa=
rid Mehrabi wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
rtl"><div style=3D"font-family:arial narrow,sans-serif;font-size:large" dir=
=3D"ltr">What about the new extended union(i.e don`t generate special membe=
rs if any field lacks)?</div><div style=3D"font-family:arial narrow,sans-se=
rif;font-size:large" dir=3D"ltr">The last version of boost::variant that I =
am aware of calls for thoughts on having a blank state.</div><div style=3D"=
font-family:arial narrow,sans-serif;font-size:large" dir=3D"ltr">So what is=
wrong with having a null state?'</div></div></blockquote><div><br>boost::v=
ariant doesn't have a blank state. You can <i>give</i> it a blank state, bu=
t only by putting `boost::blank` in the argument list. But that's a user ch=
oice, not something every variant has.<br><br>Consider two variants. Varian=
t A forces a null state, while Variant B (like boost::variant) allows you t=
o have one if you want, but makes it an argument in the list.<br><br>Let's =
say I'm in a situation where all my variants are filled. I don't default co=
nstruct anything, and none of my move constructors throw. So why should my =
visitation code <i>have</i> to consider the possibility of being empty? Why=
should my visitor functors have to consider `std::blank_t` or whatever as =
one of the choices, when the variant will never have that value? Variant A =
is decidedly less useful to me than Variant B.<br><br>Now, let's consider t=
he situation where I want a variant to potentially be empty. Well, Variant =
A gives it to me by default. For Variant B... I just put it `std::blank_t` =
in the template argument list, and it's there.<br><br>`std::variant` is nic=
e in that it doesn't really have an "empty" state; it has an "invalid" stat=
e. It only gets this state when copy/move fails in some not-easily-recovere=
d way.<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"rtl"><div style=3D"font-family:arial narrow,sans-serif;font-size:large"=
dir=3D"ltr">I personally prefer to implement std::optional<T> in ter=
ms of std::variant<T>. I also think that std::function can be d=
efined in terms of a null-able std::variant type.</div></div></blockquote><=
div><br>... why? It's highly unlikely that a person who uses `optional` wil=
l suddenly change it to `variant` and want all his code to work without cha=
nges. It's also unlikely that template code that accepts `optional<T>=
` would be able to reasonably work with `variant<T...>`.<br><br>So wh=
at's the need for such arbitrary compatibility?<br><br></div>Some people li=
ke to think of `optional` as a nullable variant with only one non-null stat=
e. Other people think of it as a container that could have zero or one elem=
ent. Neither view encapsulates how <i>users</i> will want to use the object=
.. This kind of high-concept thinking can lead to very bad interfaces.<br></=
div>
<p></p>
-- <br />
<br />
--- <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 />
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_665_2055762688.1433610753028--
------=_Part_664_1323852344.1433610753028--
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Sat, 06 Jun 2015 22:23:33 +0200
Raw View
Am 06.06.2015 um 13:42 schrieb Thiago Macieira:
> On Saturday 06 June 2015 01:39:59 Izzy Coding wrote:
>> Surely a std::variant should only be default constructable if all its
>> allowed types are default constructable?
>>
>> Also I would suggest that default construction should initialise to being
>> empty which could be checked using a member function empty() like most
>> other STL container?
> If std::variant, as described, should operate like the unrestricted union of
> the types it contains, then it should have a default constructor under the
> same rules. If the union has the default constructor deleted, so should
> std::variant.
I agree that if the equivalent union has a deleted default constructor
so should the variant, however the "initialize the first member" rule
only goes when value- and zero-initializing a union and there is a
subtle difference to default-initialization. I find it to be one of
these surprising things where people look at their code for hours and go
"wtf is going on". How many people are familiar with the initialization
rules for unions?
I can already see the confusions coming where someone changes variant<T,
U> to variant<U, T> and things go wrong. I am not speaking about "wrong"
as in "get<0>(v) now returns a different type" which can be cought at
compile time. I am speaking about the kind of "wrong" where suddenly all
default-initialized objects have a different state. This is along the
same category of stealthy behavior changes implict conversions cause and
are mostly avoided for. I think this does more harm than good in the
long run.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Sat, 6 Jun 2015 23:57:45 -0700 (PDT)
Raw View
------=_Part_1089_1109840432.1433660265764
Content-Type: multipart/alternative;
boundary="----=_Part_1090_1325289683.1433660265764"
------=_Part_1090_1325289683.1433660265764
Content-Type: text/plain; charset=UTF-8
On Saturday, June 6, 2015 at 10:12:33 AM UTC-7, Nicol Bolas wrote:
>
>
> ... why? It's highly unlikely that a person who uses `optional` will
> suddenly change it to `variant` and want all his code to work without
> changes. It's also unlikely that template code that accepts `optional<T>`
> would be able to reasonably work with `variant<T...>`.
>
Why reimplement a ton of machinery you already have? Why make users include
two big headers with a bunch similar templates if they happen to use both
library facilities? Learning not to needlessly redesign the wheel is one of
the first instincts we try to instill in first-year engineering students.
That said, if variant is massively more complicated than optional, then
perhaps the argument should be that users shouldn't need to include far
more machinery than they need for compile-time reasons. In which case
there'd be an actually good argument to reimplement optional as its own
thing, assuming we stick our heads in the sand and pretend that C++'s core
language is incapable of ever changing ever again.
Of course, as we've already discussed, both variant and optional and
expected are just over-complicated templates that poorly emulate small
subsets of decades-old type theory research that could just be built-in to
the language. :p
I'm being at least partially serious here. If you would prefer not to rely
> on the default constructor's behavior, then just don't use it. Sure, the
> compiler won't error if you use it by accident, which is unfortunate. But
> you are free to avoid the constructor if you so desire.
Ah, yes. It's so very very easy to make sure your generic code isn't
accidentally default constructing or copying something behind your back.
I've certainly never spent hours tracking down one-character mistakes in
container libraries that could have been easily tracked down had the
contained types' constructors just been deleted.
And certainly there are no libraries that usefully change behavior after
detecting if a type is default constructible or not.
But we have to live within the limitations of the language that exists, not
> the language we would like to use.
.... we are discussing this on a mailing that is specifically about changing
the limitations of the language that exists and making the language into
the one we would like to use.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1090_1325289683.1433660265764
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 6, 2015 at 10:12:33 AM UTC-7, Nicol Bola=
s 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"><div>=
<br>... why? It's highly unlikely that a person who uses `optional` will su=
ddenly change it to `variant` and want all his code to work without changes=
.. It's also unlikely that template code that accepts `optional<T>` wo=
uld be able to reasonably work with `variant<T...>`.<br></div></div><=
/blockquote><div><br></div><div>Why reimplement a ton of machinery you alre=
ady have? Why make users include two big headers with a bunch similar templ=
ates if they happen to use both library facilities? Learning not to needles=
sly redesign the wheel is one of the first instincts we try to instill in f=
irst-year engineering students.<br></div><div><br></div><div>That said, if =
variant is massively more complicated than optional, then perhaps the argum=
ent should be that users shouldn't need to include far more machinery than =
they need for compile-time reasons. In which case there'd be an actually go=
od argument to reimplement optional as its own thing, assuming we stick our=
heads in the sand and pretend that C++'s core language is incapable of eve=
r changing ever again.</div><div><br></div><div>Of course, as we've already=
discussed, both variant and optional and expected are just over-complicate=
d templates that poorly emulate small subsets of decades-old type theory re=
search that could just be built-in to the language. :p</div><div><br></div>=
<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;">I'm being at least partially serious here=
.. If you would prefer not to rely on the default constructor's behavior, th=
en just don't use it. Sure, the compiler won't error if you use it by accid=
ent, which is unfortunate. But you are free to avoid the constructor if you=
so desire.</blockquote><div><br></div><div>Ah, yes. It's so very very easy=
to make sure your generic code isn't accidentally default constructing or =
copying something behind your back. I've certainly never spent hours tracki=
ng down one-character mistakes in container libraries that could have been =
easily tracked down had the contained types' constructors just been deleted=
..</div><div><br></div><div>And certainly there are no libraries that useful=
ly change behavior after detecting if a type is default constructible or no=
t.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, =
204); border-left-style: solid; padding-left: 1ex;">But we have to live wit=
hin the limitations of the language that exists, not the language we would =
like to use.</blockquote><div><br></div><div>... we are discussing this on =
a mailing that is specifically about changing the limitations of the langua=
ge that exists and making the language into the one we would like to use.</=
div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1090_1325289683.1433660265764--
------=_Part_1089_1109840432.1433660265764--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 7 Jun 2015 00:31:34 -0700 (PDT)
Raw View
------=_Part_1133_254981967.1433662294553
Content-Type: multipart/alternative;
boundary="----=_Part_1134_1252043604.1433662294553"
------=_Part_1134_1252043604.1433662294553
Content-Type: text/plain; charset=UTF-8
On Sunday, June 7, 2015 at 2:57:45 AM UTC-4, Sean Middleditch wrote:
>
> On Saturday, June 6, 2015 at 10:12:33 AM UTC-7, Nicol Bolas wrote:
>>
>>
>> ... why? It's highly unlikely that a person who uses `optional` will
>> suddenly change it to `variant` and want all his code to work without
>> changes. It's also unlikely that template code that accepts `optional<T>`
>> would be able to reasonably work with `variant<T...>`.
>>
>
> Why reimplement a ton of machinery you already have?
>
Interface and implementation are not the same thing. A repetition of one
does not require a repetition of the other.
> Why make users include two big headers with a bunch similar templates if
> they happen to use both library facilities?
>
Because they don't have similar templates, similar library facilities, or
similar use cases.
> Learning not to needlessly redesign the wheel is one of the first
> instincts we try to instill in first-year engineering students.
>
And learning the difference between a wheel and a donut is also something I
would hope would be instilled in "first-year engineering students". Just
because something is round and has a hole in the middle doesn't make it a
wheel.
Of course, as we've already discussed, both variant and optional and
> expected are just over-complicated templates that poorly emulate small
> subsets of decades-old type theory research that could just be built-in to
> the language. :p
>
No, we have not "discussed" this; you have *asserted* it as though it were
fact. You declare them to be a functional programming concept; the rest of
us say that they're C++ types, all of whom have very different uses.
Something that would qualify as "discussion" of this point would be for you
to provide evidence to back up your assertion. Not Haskell or some other
non-C++ language. Not unquestionable functional programming wisdom, brought
down from Mt. Sinai, and carved into stone by the very finger of God. An
actual C++ interface, where it is *semantically reasonable* for variant,
expected, and/or optional to all interoperate as a function parameter or
return type.
Show me an actual problem that C++ programmers would face that would be
solved by variant, expected, and/or optional sharing identical,
interoperable interfaces and implementations.
Here's a bit of argument from the "they're all different" side.
I present the Zero-One-Infinity rule
<https://en.wikipedia.org/wiki/Zero_one_infinity_rule>. Every type in C++
conceptually exists in a single state: its current type. optional,
expected, and variant all semantically change this, adding some number of
alternate states. And they each correspond to one of the three items in the
aforementioned rule.
`optional` represents Zero: the "state" that is a lack of state. The object
exists or it does not.
`expected` represents One: a single alternative state. The object exists or
a single alternate object exists.
`variant` represents Infinity: the object can have infinitely many
alternate states. The object exists or one of potentially infinitely many
alternate objects exist.
Each concept is distinct and therefore deserves its own type, with whatever
interface is appropriate to their concept.
You are *dangerously close* to the logic behind `vector<bool>`: a
space-optimized dynamically allocated bit array masquerading as a `vector`,
simply because the interface happened to have certain superficial
similarities to `vector`.
> I'm being at least partially serious here. If you would prefer not to rely
>> on the default constructor's behavior, then just don't use it. Sure, the
>> compiler won't error if you use it by accident, which is unfortunate. But
>> you are free to avoid the constructor if you so desire.
>
>
> Ah, yes. It's so very very easy to make sure your generic code isn't
> accidentally default constructing or copying something behind your back.
> I've certainly never spent hours tracking down one-character mistakes in
> container libraries that could have been easily tracked down had the
> contained types' constructors just been deleted.
>
> And certainly there are no libraries that usefully change behavior after
> detecting if a type is default constructible or not.
>
I never claimed that it was *easy*; only that you were free to do so ;)
>
> But we have to live within the limitations of the language that exists,
>> not the language we would like to use.
>
>
> ... we are discussing this on a mailing that is specifically about
> changing the limitations of the language that exists and making the
> language into the one we would like to use.
>
And we're discussing this in a thread that's talking about a pure *library*
proposal, not a language change. Fixing the general problem of
initialization vs. construction universally is out-of-bounds for this
discussion. Thus, the proposal must work within the world as it exists
today.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1134_1252043604.1433662294553
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, June 7, 2015 at 2:57:45 AM UTC-4, Sean Middledi=
tch 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">On =
Saturday, June 6, 2015 at 10:12:33 AM UTC-7, Nicol Bolas 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"><div><br>... why? It's highly =
unlikely that a person who uses `optional` will suddenly change it to `vari=
ant` and want all his code to work without changes. It's also unlikely that=
template code that accepts `optional<T>` would be able to reasonably=
work with `variant<T...>`.<br></div></div></blockquote><div><br></di=
v><div>Why reimplement a ton of machinery you already have?</div></div></bl=
ockquote><div><br>Interface and implementation are not the same thing. A re=
petition of one does not require a repetition of the other.<br> </div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Why make=
users include two big headers with a bunch similar templates if they happe=
n to use both library facilities?</div></div></blockquote><div><br>Because =
they don't have similar templates, similar library facilities, or similar u=
se cases.<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>Learning not to needlessly redesign the wheel is one of th=
e first instincts we try to instill in first-year engineering students.<br>=
</div></div></blockquote><div><br>And learning the difference between a whe=
el and a donut is also something I would hope would be instilled in "first-=
year engineering students". Just because something is round and has a hole =
in the middle doesn't make it a wheel.<br><br> </div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>Of course, as we've=
already discussed, both variant and optional and expected are just over-co=
mplicated templates that poorly emulate small subsets of decades-old type t=
heory research that could just be built-in to the language. :p</div></div><=
/blockquote><div><br>No, we have not "discussed" this; you have <i>asserted=
</i> it as though it were fact. You declare them to be a functional program=
ming concept; the rest of us say that they're C++ types, all of whom have v=
ery different uses.<br><br>Something that would qualify as "discussion" of =
this point would be for you to provide evidence to back up your assertion. =
Not Haskell or some other non-C++ language. Not unquestionable functional p=
rogramming wisdom, brought down from Mt. Sinai, and carved into stone by th=
e very finger of God. An actual C++ interface, where it is <i>semantically =
reasonable</i> for variant, expected, and/or optional to all interoperate a=
s a function parameter or return type.<br><br>Show me an actual problem tha=
t C++ programmers would face that would be solved by variant, expected, and=
/or optional sharing identical, interoperable interfaces and implementation=
s.<br><br>Here's a bit of argument from the "they're all different" side.<b=
r><br>I present the <a href=3D"https://en.wikipedia.org/wiki/Zero_one_infin=
ity_rule">Zero-One-Infinity rule</a>. Every type in C++ conceptually exists=
in a single state: its current type. optional, expected, and variant all s=
emantically change this, adding some number of alternate states. And they e=
ach correspond to one of the three items in the aforementioned rule.<br><br=
>`optional` represents Zero: the "state" that is a lack of state. The objec=
t exists or it does not.<br><br>`expected` represents One: a single alterna=
tive state. The object exists or a single alternate object exists.<br><br>`=
variant` represents Infinity: the object can have infinitely many alternate=
states. The object exists or one of potentially infinitely many alternate =
objects exist.<br><br>Each concept is distinct and therefore deserves its o=
wn type, with whatever interface is appropriate to their concept.<br><br>Yo=
u are <i>dangerously close</i> to the logic behind `vector<bool>`: a =
space-optimized dynamically allocated bit array masquerading as a `vector`,=
simply because the interface happened to have certain superficial similari=
ties to `vector`.<br><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div><br></div><div><blockquote class=3D"gmail_quote" sty=
le=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">I'm being at least p=
artially serious here. If you would prefer not to rely on the default const=
ructor's behavior, then just don't use it. Sure, the compiler won't error i=
f you use it by accident, which is unfortunate. But you are free to avoid t=
he constructor if you so desire.</blockquote><div><br></div><div>Ah, yes. I=
t's so very very easy to make sure your generic code isn't accidentally def=
ault constructing or copying something behind your back. I've certainly nev=
er spent hours tracking down one-character mistakes in container libraries =
that could have been easily tracked down had the contained types' construct=
ors just been deleted.</div><div><br></div><div>And certainly there are no =
libraries that usefully change behavior after detecting if a type is defaul=
t constructible or not.</div></div></div></blockquote><div><br>I never clai=
med that it was <i>easy</i>; only that you were free to do so ;)<br> <=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><di=
v><br></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-s=
tyle:solid;padding-left:1ex">But we have to live within the limitations of =
the language that exists, not the language we would like to use.</blockquot=
e><div><br></div><div>... we are discussing this on a mailing that is speci=
fically about changing the limitations of the language that exists and maki=
ng the language into the one we would like to use.</div></div></div></block=
quote><div><br>And we're discussing this in a thread that's talking about a=
pure <i>library</i> proposal, not a language change. Fixing the gene=
ral problem of initialization vs. construction universally is out-of-bounds=
for this discussion. Thus, the proposal must work within the world as it e=
xists today.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1134_1252043604.1433662294553--
------=_Part_1133_254981967.1433662294553--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 19:40:28 +0200
Raw View
This is a multi-part message in MIME format.
--------------080603080509020303070101
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 06/06/15 19:12, Nicol Bolas a =C3=A9crit :
>
>
> On Saturday, June 6, 2015 at 11:52:37 AM UTC-4, Farid Mehrabi wrote:
>
> What about the new extended union(i.e don`t generate special
> members if any field lacks)?
> The last version of boost::variant that I am aware of calls for
> thoughts on having a blank state.
> So what is wrong with having a null state?'
>
>
> boost::variant doesn't have a blank state. You can /give/ it a blank=20
> state, but only by putting `boost::blank` in the argument list. But=20
> that's a user choice, not something every variant has.
>
> Consider two variants. Variant A forces a null state, while Variant B=20
> (like boost::variant) allows you to have one if you want, but makes it=20
> an argument in the list.
>
> Let's say I'm in a situation where all my variants are filled. I don't=20
> default construct anything, and none of my move constructors throw. So=20
> why should my visitation code /have/ to consider the possibility of=20
> being empty? Why should my visitor functors have to consider=20
> `std::blank_t` or whatever as one of the choices, when the variant=20
> will never have that value? Variant A is decidedly less useful to me=20
> than Variant B.
>
> Now, let's consider the situation where I want a variant to=20
> potentially be empty. Well, Variant A gives it to me by default. For=20
> Variant B... I just put it `std::blank_t` in the template argument=20
> list, and it's there.
>
> `std::variant` is nice in that it doesn't really have an "empty"=20
> state; it has an "invalid" state. It only gets this state when=20
> copy/move fails in some not-easily-recovered way.
>
> I personally prefer to implement std::optional<T> in terms of
> std::variant<T>. I also think that std::function can be defined
> in terms of a null-able std::variant type.
>
>
> ... why? It's highly unlikely that a person who uses `optional` will=20
> suddenly change it to `variant` and want all his code to work without=20
> changes. It's also unlikely that template code that accepts=20
> `optional<T>` would be able to reasonably work with `variant<T...>`.
>
> So what's the need for such arbitrary compatibility?
>
> Some people like to think of `optional` as a nullable variant with=20
> only one non-null state. Other people think of it as a container that=20
> could have zero or one element. Neither view encapsulates how /users/=20
> will want to use the object. This kind of high-concept thinking can=20
> lead to very bad interfaces.
>
variant, optional, expected and future are all sum types as vector,=20
list, .... are containers. I don't mind whether one can be implemented=20
in function of the other, but some coherency must be preserved on the=20
interfaces.
When each one of this concrete types provide a common sum type interface=20
(or we map each concrete type as a sum type interface) we are able to=20
build new algorithm, abstraction on top of this common interface=20
independently of the concrete type.
This doesn't mean that the final user can use interchangeably variant,=20
optional, expected. But there are a lot of thing to do with the sum type=20
common interface.
One of the common operations on sum types is to apply (visit) an=20
hetorgeneous function to all the elements. Currently the variant=20
proposal includes a visit function, expected has fmap/bind/catch_error=20
and optional has no visitation function.
We need a match function that works on all these types. This function=20
can be a non-member function or a member one.
This match function could be naturally extended to variadic sum types=20
(that must of course be a non-member one).
The other minimal operation on sum types is to construct one instance of=20
a sum type from one instance of one of its possible elements.
Once you a common and minimal interface for sum types, you can build=20
anything on top of this minimal interface independently of whether we=20
have variant, optional, expected or whatever other sum type we can have=20
on the future.
optional<T>, expected<T>, future<T> and why not variant<T,E> or=20
variant<E,T> where E is fixed and means an Error are in addition monads=20
which open other extension (but this out of the scope of this thread).
These is the kind of design some of us are suggesting/proposing. Seen=20
concrete types as instances of a Concept helps to identify its interface.
Now responding the PO, we can have two kind of variants, one that can be=20
empty and one that can not be empty.
The first can be seen as optional<variant<Ts>> and sure we can have a=20
better implementation for this concrete type. The question is if we need=20
a specific optional_variant name or if we want to specialize the=20
optional when the type is variant. Another way to see it is as a=20
variadic optional
optional<T1, ..., Tn>
Vicente
--=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/.
--------------080603080509020303070101
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 06/06/15 19:12, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:318b68be-ffb6-4943-93f7-dbdcc336eb22@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
<br>
On Saturday, June 6, 2015 at 11:52:37 AM UTC-4, Farid Mehrabi
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"rtl">
<div style=3D"font-family:arial
narrow,sans-serif;font-size:large" dir=3D"ltr">What about
the new extended union(i.e don`t generate special members
if any field lacks)?</div>
<div style=3D"font-family:arial
narrow,sans-serif;font-size:large" dir=3D"ltr">The last
version of boost::variant that I am aware of calls for
thoughts on having a blank state.</div>
<div style=3D"font-family:arial
narrow,sans-serif;font-size:large" dir=3D"ltr">So what is
wrong with having a null state?'</div>
</div>
</blockquote>
<div><br>
boost::variant doesn't have a blank state. You can <i>give</i>
it a blank state, but only by putting `boost::blank` in the
argument list. But that's a user choice, not something every
variant has.<br>
<br>
Consider two variants. Variant A forces a null state, while
Variant B (like boost::variant) allows you to have one if you
want, but makes it an argument in the list.<br>
<br>
Let's say I'm in a situation where all my variants are filled.
I don't default construct anything, and none of my move
constructors throw. So why should my visitation code <i>have</i>
to consider the possibility of being empty? Why should my
visitor functors have to consider `std::blank_t` or whatever
as one of the choices, when the variant will never have that
value? Variant A is decidedly less useful to me than Variant
B.<br>
<br>
Now, let's consider the situation where I want a variant to
potentially be empty. Well, Variant A gives it to me by
default. For Variant B... I just put it `std::blank_t` in the
template argument list, and it's there.<br>
<br>
`std::variant` is nice in that it doesn't really have an
"empty" state; it has an "invalid" state. It only gets this
state when copy/move fails in some not-easily-recovered way.<br>
=C2=A0</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"rtl">
<div style=3D"font-family:arial
narrow,sans-serif;font-size:large" dir=3D"ltr">I personally
prefer to implement std::optional<T> in terms of
std::variant<T>. I also think =C2=A0that std::function
can be defined in terms of a null-able std::variant type.</di=
v>
</div>
</blockquote>
<div><br>
... why? It's highly unlikely that a person who uses
`optional` will suddenly change it to `variant` and want all
his code to work without changes. It's also unlikely that
template code that accepts `optional<T>` would be able
to reasonably work with `variant<T...>`.<br>
<br>
So what's the need for such arbitrary compatibility?<br>
<br>
</div>
Some people like to think of `optional` as a nullable variant
with only one non-null state. Other people think of it as a
container that could have zero or one element. Neither view
encapsulates how <i>users</i> will want to use the object. This
kind of high-concept thinking can lead to very bad interfaces.<br>
</div>
<br>
</blockquote>
variant, optional, expected and future are all sum types as vector,
list,=C2=A0 .... are containers. I don't mind whether one can be
implemented in function of the other, but some coherency must be
preserved on the interfaces.<br>
<br>
When each one of this concrete types provide a common sum type
interface (or we map each concrete type as a sum type interface) we
are able to build new algorithm, abstraction on top of this common
interface independently of the concrete type.<br>
<br>
This doesn't mean that the final user can use interchangeably
variant, optional, expected. But there are a lot of thing to do with
the sum type common interface.<br>
<br>
One of the common operations on sum types is to apply (visit) an
hetorgeneous function to all the elements. Currently the variant
proposal includes a visit function, expected has
fmap/bind/catch_error and optional has no visitation function.<br>
We need a match function that works on all these types. This
function can be a non-member function or a member one.<br>
This match function could be naturally extended to variadic sum
types (that must of course be a non-member one).<br>
<br>
The other minimal operation on sum types is to construct one
instance of a sum type from one instance of one of its possible
elements.<br>
<br>
Once you a common and minimal interface for sum types, you can build
anything on top of this minimal interface independently of whether
we have variant, optional, expected or whatever other sum type we
can have on the future.<br>
<br>
optional<T>, expected<T>, future<T> and why not
variant<T,E> or variant<E,T> where E is fixed and means
an Error are in addition monads which open other extension (but this
out of the scope of this thread).<br>
<br>
These is the kind of design some of us are suggesting/proposing.
Seen concrete types as instances of a Concept helps to identify its
interface.<br>
<br>
Now responding the PO, we can have two kind of variants, one that
can be empty and one that can not be empty.<br>
The first can be seen as optional<variant<Ts>> and sure
we can have a better implementation for this concrete type. The
question is if we need a specific optional_variant name or if we
want to specialize the optional when the type is variant. Another
way to see it is as a variadic optional<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<T1, ..., Tn><br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--------------080603080509020303070101--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 19:58:53 +0200
Raw View
This is a multi-part message in MIME format.
--------------090803000602090301030303
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
> Hi everyone,
>
> I would like to voice my concerns about default construction of=20
> std::variant and std::monostate. The proposal did not make clear to me=20
> why default constructed empty state is such a big issue in the first=20
> place and the current alternative suffers from significant drawbacks:
>
> * To me it is very surprising that variant tries to
> default-construct the first type. Why not the 2nd, 5th type? I'd
> rather have variant have no default constructor than some
> arbitrary decision.
> * It is yet another special case that users need to be taught about
> and frankly, it's not pretty either. Users have to remember "Oh, I
> have to use this std::monostate workaround if my type is not
> default constructible!". /Hacks/ (another spelling for
> 'workaround') are /bad/.
> * It does not play well with changes. Imagine if the user-defined
> type that was previously default constructible has its default
> constructor removed. Now the users needs to add std::monostate all
> over the place and fix up all the indices for index-based access.
>
> There needs to be a better solution. I do think that having an empty=20
> state semantically fails at the idea of variant in the first place=20
> ("either A or B", not "either A, B or empty"), but it is not the end=20
> of the world. The current std::monostate design however has=20
> significant issues that IMHO deserve another look.
>
>
We have two orthogonal interface decissions that could interact
* default construction
* possible empty
A - We can have a variant class that is not default constructible and=20
cannot be empty.
B - We can have a variant class that is default constructible and can=20
be empty, so the default constructor is naturally empty.
C - We can have a variant class that is default constructible and=20
cannot be empty (we need to state how it is default constructed).
The not default constructible and empty seems not interesting enough.
The current proposal correspond to C, when its first alternative is=20
default constructible and A otherwise, and I think this is the better we=20
can have.
The standard could also have a class behaving always as A. I wouldn't be=20
against.
You are advocating for option B. I believe that option B would be=20
represented better by
optional<variant<Ts...>>
with a possible specialization implementation
or by a variadic optional version
optional<Ts...>
All these concrete classes share a lot in common and I would expect that=20
the library implementor would make use of an implementation class that=20
covers the common parts.
Vicente
--=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/.
--------------090803000602090301030303
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:52830824-6895-47e2-8fab-970391945694@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The proposal
did not make clear to me why default constructed empty state
is such a big issue in the first place and the current
alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height: normal;">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some arbitrary
decision.</span></li>
<li><span style=3D"line-height: normal;">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember
"Oh, I have to use this std::monostate workaround if my
type is not default constructible!". <i>Hacks</i>
(another spelling for 'workaround') are <i>bad</i>.</span><=
/li>
<li><span style=3D"line-height: normal;">It does not play well
with changes. Imagine if the user-defined type that was
previously default constructible has its default
constructor removed. Now the users needs to add
std::monostate all over the place and fix up all the
indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not "either A,
B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues
that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 and
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 and
cannot=C2=A0 be empty (we need to state how it is default constructed).=
<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative is
default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
<br>
You are advocating for option B. I believe that option B would be
represented better by<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<variant<Ts...>><br>
<br>
with a possible specialization=C2=A0 implementation<br>
<br>
or by a variadic optional version<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<Ts...><br>
<br>
All these concrete classes share a lot in common and I would expect
that the library implementor would make use of an implementation
class that covers the common parts.<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--------------090803000602090301030303--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 20:04:53 +0200
Raw View
This is a multi-part message in MIME format.
--------------070302020106000207090402
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 07/06/15 19:58, Vicente J. Botet Escriba a =C3=A9crit :
> Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
>> Hi everyone,
>>
>> I would like to voice my concerns about default construction of=20
>> std::variant and std::monostate. The proposal did not make clear to=20
>> me why default constructed empty state is such a big issue in the=20
>> first place and the current alternative suffers from significant=20
>> drawbacks:
>>
>> * To me it is very surprising that variant tries to
>> default-construct the first type. Why not the 2nd, 5th type? I'd
>> rather have variant have no default constructor than some
>> arbitrary decision.
>> * It is yet another special case that users need to be taught about
>> and frankly, it's not pretty either. Users have to remember "Oh,
>> I have to use this std::monostate workaround if my type is not
>> default constructible!". /Hacks/ (another spelling for
>> 'workaround') are /bad/.
>> * It does not play well with changes. Imagine if the user-defined
>> type that was previously default constructible has its default
>> constructor removed. Now the users needs to add std::monostate
>> all over the place and fix up all the indices for index-based access=
..
>>
>> There needs to be a better solution. I do think that having an empty=20
>> state semantically fails at the idea of variant in the first place=20
>> ("either A or B", not "either A, B or empty"), but it is not the end=20
>> of the world. The current std::monostate design however has=20
>> significant issues that IMHO deserve another look.
>>
>>
> We have two orthogonal interface decissions that could interact
> * default construction
> * possible empty
>
> A - We can have a variant class that is not default constructible and=20
> cannot be empty.
> B - We can have a variant class that is default constructible and can=20
> be empty, so the default constructor is naturally empty.
> C - We can have a variant class that is default constructible and=20
> cannot be empty (we need to state how it is default constructed).
>
> The not default constructible and empty seems not interesting enough.
>
> The current proposal correspond to C, when its first alternative is=20
> default constructible and A otherwise, and I think this is the better=20
> we can have.
> The standard could also have a class behaving always as A. I wouldn't=20
> be against.
BTW, option A could be simulated with the current proposal by using as=20
first alternative a class that is no constructible at all.
struct non_constructible {
non_constructible() =3D delete;
};
template <class ... Ts>
using non_default_constructible_variant<non_constructible, Ts...>
Vicente
--=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/.
--------------070302020106000207090402
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 07/06/15 19:58, Vicente J. Botet
Escriba a =C3=A9crit=C2=A0:<br>
</div>
<blockquote cite=3D"mid:5574865D.1010708@wanadoo.fr" type=3D"cite">
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Ty=
pe">
<div class=3D"moz-cite-prefix">Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:52830824-6895-47e2-8fab-970391945694@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The
proposal did not make clear to me why default constructed
empty state is such a big issue in the first place and the
current alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height: normal;">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some
arbitrary decision.</span></li>
<li><span style=3D"line-height: normal;">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to
remember "Oh, I have to use this std::monostate
workaround if my type is not default constructible!".
<i>Hacks</i> (another spelling for 'workaround') are <i>b=
ad</i>.</span></li>
<li><span style=3D"line-height: normal;">It does not play
well with changes. Imagine if the user-defined type
that was previously default constructible has its
default constructor removed. Now the users needs to
add std::monostate all over the place and fix up all
the indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not "either
A, B or empty"), but it is not the end of the world. The
current std::monostate design however has significant
issues that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=
=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 a=
nd
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 a=
nd
cannot=C2=A0 be empty (we need to state how it is default constructed=
).<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative
is default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
</blockquote>
BTW, option A could be simulated with the current proposal by using
as first alternative a class that is no constructible at all. <br>
<br>
struct non_constructible {<br>
=C2=A0=C2=A0=C2=A0 non_constructible() =3D delete;<br>
};<br>
<br>
template <class ... Ts><br>
using non_default_constructible_variant<non_constructible,
Ts...><br>
<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--------------070302020106000207090402--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 20:07:18 +0200
Raw View
Le 06/06/15 10:39, Izzy Coding a =C3=A9crit :
> Surely a std::variant should only be default constructable if all its all=
owed types are default constructable?
An to what it should default construct?
>
> Also I would suggest that default construction should initialise to being=
empty which could be checked using a member function empty() like most oth=
er STL container?
This default construction corresponds to a different type. And in this=20
case we don't need that all the types are default constructible.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 20:55:53 +0200
Raw View
Le 06/06/15 22:23, Miro Knejp a =C3=A9crit :
>
>
> Am 06.06.2015 um 13:42 schrieb Thiago Macieira:
>> On Saturday 06 June 2015 01:39:59 Izzy Coding wrote:
>>> Surely a std::variant should only be default constructable if all its
>>> allowed types are default constructable?
>>>
>>> Also I would suggest that default construction should initialise to=20
>>> being
>>> empty which could be checked using a member function empty() like most
>>> other STL container?
>> If std::variant, as described, should operate like the unrestricted=20
>> union of
>> the types it contains, then it should have a default constructor=20
>> under the
>> same rules. If the union has the default constructor deleted, so should
>> std::variant.
> I agree that if the equivalent union has a deleted default constructor=20
> so should the variant, however the "initialize the first member" rule=20
> only goes when value- and zero-initializing a union and there is a=20
> subtle difference to default-initialization. I find it to be one of=20
> these surprising things where people look at their code for hours and=20
> go "wtf is going on". How many people are familiar with the=20
> initialization rules for unions?
>
> I can already see the confusions coming where someone changes=20
> variant<T, U> to variant<U, T> and things go wrong. I am not speaking=20
> about "wrong" as in "get<0>(v) now returns a different type" which can=20
> be cought at compile time. I am speaking about the kind of "wrong"=20
> where suddenly all default-initialized objects have a different state.=20
> This is along the same category of stealthy behavior changes implict=20
> conversions cause and are mostly avoided for. I think this does more=20
> harm than good in the long run.
>
In the same way we would have tagged_tuple (See [1] last draft of the=20
Range TS) we could have tagged_variant. As far as we access=20
tagged_variant by their tags tagged_variant<T, U> and tagged_variant<U,=20
T> would behave almost the same.
If the user don't want the varaint to be default_constructible it could=20
use non_default_constructible_tagged_variant<T, U> or=20
non_default_constructible_tagged_variant<U, T>.
Having the good building blocks would allow us to provide whatever the=20
user wants.
A different question is what the C++ standard library would use on a=20
particular case. But this question should be answered in a case by case=20
bases.
Vicente
[1] https://github.com/ericniebler/stl2/blob/master/DXXXX.pdf)
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Farid Mehrabi <farid.mehrabi@gmail.com>
Date: Tue, 16 Jun 2015 00:42:58 +0430
Raw View
--001a1139b2c2edef6d0518941784
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
2015-06-07 22:28 GMT+04:30 Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr>:
=E2=80=8B=E2=80=8B
> Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
>
> Hi everyone,
>
> I would like to voice my concerns about default construction of
> std::variant and std::monostate. The proposal did not make clear to me wh=
y
> default constructed empty state is such a big issue in the first place an=
d
> the current alternative suffers from significant drawbacks:
>
> - To me it is very surprising that variant tries to default-construct
> the first type. Why not the 2nd, 5th type? I'd rather have variant hav=
e no
> default constructor than some arbitrary decision.
> - It is yet another special case that users need to be taught about
> and frankly, it's not pretty either. Users have to remember "Oh, I hav=
e to
> use this std::monostate workaround if my type is not default
> constructible!". *Hacks* (another spelling for 'workaround') are *bad*=
..
> - It does not play well with changes. Imagine if the user-defined type
> that was previously default constructible has its default constructor
> removed. Now the users needs to add std::monostate all over the place =
and
> fix up all the indices for index-based access.
>
> There needs to be a better solution. I do think that having an empty stat=
e
> semantically fails at the idea of variant in the first place ("either A o=
r
> B", not "either A, B or empty"), but it is not the end of the world. The
> current std::monostate design however has significant issues that IMHO
> deserve another look.
>
>
> We have two orthogonal interface decissions that could interact
> * default construction
> * possible empty
>
> A - We can have a variant class that is not default constructible and
> cannot be empty.
> B - We can have a variant class that is default constructible and can be
> empty, so the default constructor is naturally empty.
> C - We can have a variant class that is default constructible and cannot
> be empty (we need to state how it is default constructed).
>
> The not default constructible and empty seems not interesting enough.
>
> The current proposal correspond to C, when its first alternative is
> default constructible and A otherwise, and I think this is the better we
> can have.
> The standard could also have a class behaving always as A. I wouldn't be
> against.
>
> You are advocating for option B. I believe that option B would be
> represented better by
>
> optional<variant<Ts...>>
>
> with a possible specialization implementation
>
> or by a variadic optional version
>
> optional<Ts...>
>
> All these concrete classes share a lot in common and I would expect that
> the library implementor would make use of an implementation class that
> covers the common parts.
>
=E2=80=8BA lot of effort has been put together to make option C possible an=
d I do
appreciate that, but why should we set option B aside while it is much
easier to implement and more generic?
recalling that a variant assignment generally consists of 3 steps:
1. back up destination.
2. copy source.
3. restore destination if 2 fails.
consider Option C (direct porting of boost::variant into std):
Q: what happens if during an assignment operation, copy from source throws
and the restoration move in the destination throws too?=E2=80=8B
A: either a an uncaught exception or undefined behavior in a blank-less
variant.
Option B is not only easier,but also less dangerous: if copy fails and
restoration fails too, reset to blank(null,empy ...).
A worse scenario is when the backup move throws during the assignment;
with option C it means the sky collapsing, whilst with option B the
variant can reset to blank, a subsequent test of blankness can be used to
check whether or not the assignment has succeeded.
By the way what are the benefits of the never empty promise of option C?
What might go wrong if the variant is in blank state? visitors might
eventually ignore the null state or be forced to do something.
And you have actually pointed out one of my concerns about overhead: the
'optional<variant<...>>'. With option B optional variant is just a thin API
wrapper with no overhead on the variant, but with option C it is just
paying twice the essential price.
regards,
FM.
--=20
how am I supposed to end the twisted road of your hair in such a dark
night??
unless the candle of your face does shed some light upon my way!!!
--=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/.
--001a1139b2c2edef6d0518941784
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"rtl"><div class=3D"gmail_default" style=3D"font-family:arial na=
rrow,sans-serif;font-size:large"><br></div><div class=3D"gmail_extra"><br><=
div class=3D"gmail_quote"><div dir=3D"ltr">2015-06-07 22:28 GMT+04:30 Vicen=
te J. Botet Escriba <span dir=3D"ltr"><<a href=3D"mailto:vicente.botet@w=
anadoo.fr" target=3D"_blank">vicente.botet@wanadoo.fr</a>></span>:<div c=
lass=3D"gmail_default" style=3D"font-family:'arial narrow',sans-ser=
if;font-size:large;display:inline">=E2=80=8B=E2=80=8B</div></div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div><span class=3D"">
<blockquote type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The proposal
did not make clear to me why default constructed empty state
is such a big issue in the first place and the current
alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height:normal">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some arbitrary
decision.</span></li>
<li><span style=3D"line-height:normal">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember
"Oh, I have to use this std::monostate workaround if m=
y
type is not default constructible!". <i>Hacks</i>
(another spelling for 'workaround') are <i>bad</i>.=
</span></li>
<li><span style=3D"line-height:normal">It does not play well
with changes. Imagine if the user-defined type that was
previously default constructible has its default
constructor removed. Now the users needs to add
std::monostate all over the place and fix up all the
indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not &quo=
t;either A,
B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues
that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote></span>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 and
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 and
cannot=C2=A0 be empty (we need to state how it is default constructed).=
<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative is
default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
<br>
You are advocating for option B. I believe that option B would be
represented better by<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<variant<Ts...>><br>
<br>
with a possible specialization=C2=A0 implementation<br>
<br>
or by a variadic optional version<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<Ts...><br>
<br>
All these concrete classes share a lot in common and I would expect
that the library implementor would make use of an implementation
class that covers the common parts.<span class=3D"HOEnZb"><font color=
=3D"#888888"><br></font></span></div></blockquote></div><div><br></div><div=
style=3D"text-align:left"><div class=3D"gmail_default" style=3D"font-famil=
y:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">=E2=80=8BA=
lot of effort has been put together to make option C possible and I do app=
reciate that, but why should we set option B aside while it is much easier =
to implement and more generic?</div><div class=3D"gmail_default" style=3D"f=
ont-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">r=
ecalling that a variant assignment generally consists of 3 steps:</div><div=
class=3D"gmail_default" style=3D"font-family:'arial narrow',sans-s=
erif;font-size:large" dir=3D"ltr"><br></div><div class=3D"gmail_default" st=
yle=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=
=3D"ltr">1. back up destination.</div><div class=3D"gmail_default" style=3D=
"font-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr"=
>2. copy source.</div><div class=3D"gmail_default" style=3D"font-family:=
9;arial narrow',sans-serif;font-size:large" dir=3D"ltr">3. restore dest=
ination if 2 fails.</div><div class=3D"gmail_default" style=3D"font-family:=
'arial narrow',sans-serif;font-size:large" dir=3D"ltr"><br></div><d=
iv class=3D"gmail_default" style=3D"font-family:'arial narrow',sans=
-serif;font-size:large" dir=3D"ltr">consider Option C (direct porting of bo=
ost::variant into std):</div><div class=3D"gmail_default" style=3D"font-fam=
ily:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">Q: what =
happens if during an assignment operation, copy from source throws and the =
restoration move in the destination throws too?=E2=80=8B</div><div class=3D=
"gmail_default" style=3D"font-family:'arial narrow',sans-serif;font=
-size:large" dir=3D"ltr">=C2=A0A: either a an uncaught exception or undefin=
ed behavior in a blank-less variant.</div><div class=3D"gmail_default" styl=
e=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=3D"=
ltr">Option B is not only easier,but also less dangerous: if copy fails and=
restoration fails too, reset to blank(null,empy ...).</div><div class=3D"g=
mail_default" style=3D"font-family:'arial narrow',sans-serif;font-s=
ize:large" dir=3D"ltr"><br></div><div class=3D"gmail_default" style=3D"font=
-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">A wo=
rse scenario is when the backup move throws during the assignment; =C2=A0wi=
th option C it means the sky collapsing, whilst with option B the variant c=
an reset to blank, a subsequent test of blankness can be used to check whet=
her or not the assignment has succeeded.</div><div class=3D"gmail_default" =
style=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=
=3D"ltr"><br></div><div class=3D"gmail_default" style=3D"font-family:'a=
rial narrow',sans-serif;font-size:large" dir=3D"ltr">By the way what ar=
e the benefits of the never empty promise of option C? What might go wrong =
if the variant is in blank state? visitors might eventually ignore the null=
state or be forced to do something.<br></div><div class=3D"gmail_default" =
style=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=
=3D"ltr"><br></div><div class=3D"gmail_default" style=3D"font-family:'a=
rial narrow',sans-serif;font-size:large" dir=3D"ltr">And you have actua=
lly pointed out one of my concerns about overhead: the 'optional<var=
iant<...>>'. With option B optional variant is just a thin API=
wrapper with no overhead on the variant, but with option C it is just payi=
ng twice the essential price.</div><div class=3D"gmail_default" style=3D"fo=
nt-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr"><b=
r></div><div class=3D"gmail_default" style=3D"font-family:'arial narrow=
',sans-serif;font-size:large" dir=3D"ltr">regards,</div><div class=3D"g=
mail_default" style=3D"font-family:'arial narrow',sans-serif;font-s=
ize:large" dir=3D"ltr">FM.</div><br></div>-- <br><div class=3D"gmail_signat=
ure"><div dir=3D"rtl"><div><div dir=3D"ltr">how am I supposed to end the tw=
isted road of=C2=A0 your hair in such a dark night??<br>unless the candle o=
f your face does shed some light upon my way!!!<br></div></div></div></div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1139b2c2edef6d0518941784--
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Tue, 16 Jun 2015 11:26:35 -0400
Raw View
On 2015-06-15 16:12, Farid Mehrabi wrote:
> And you have actually pointed out one of my concerns about overhead: the
> 'optional<variant<...>>'. With option B optional variant is just a thin API
> wrapper with no overhead on the variant, but with option C it is just
> paying twice the essential price.
No; there may be a semantic difference between not having a value and
having a variant value that is empty. (OTOH you'd probably rarely if
ever see such a construct. Though it could be similarly argued that if
nullability matters, you should always have blank_t as the first type.)
I would expect 'optional<optional<T>>' to not collapse into
'optional<T>' for that reason. Neither should 'optional<variant<...>>'
collapse into 'variant<...>'.
--
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 16 Jun 2015 13:25:44 -0400
Raw View
--089e01227ec043d24b0518a5ddea
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Mon, Jun 15, 2015 at 4:12 PM, Farid Mehrabi <farid.mehrabi@gmail.com>
wrote:
>
>
> 2015-06-07 22:28 GMT+04:30 Vicente J. Botet Escriba <
> vicente.botet@wanadoo.fr>:
> =E2=80=8B=E2=80=8B
>
>> Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
>>
>> Hi everyone,
>>
>> I would like to voice my concerns about default construction of
>> std::variant and std::monostate. The proposal did not make clear to me w=
hy
>> default constructed empty state is such a big issue in the first place a=
nd
>> the current alternative suffers from significant drawbacks:
>>
>> - To me it is very surprising that variant tries to default-construct
>> the first type. Why not the 2nd, 5th type? I'd rather have variant ha=
ve no
>> default constructor than some arbitrary decision.
>> - It is yet another special case that users need to be taught about
>> and frankly, it's not pretty either. Users have to remember "Oh, I ha=
ve to
>> use this std::monostate workaround if my type is not default
>> constructible!". *Hacks* (another spelling for 'workaround') are *bad=
*
>> .
>> - It does not play well with changes. Imagine if the user-defined
>> type that was previously default constructible has its default constr=
uctor
>> removed. Now the users needs to add std::monostate all over the place=
and
>> fix up all the indices for index-based access.
>>
>> There needs to be a better solution. I do think that having an empty
>> state semantically fails at the idea of variant in the first place ("eit=
her
>> A or B", not "either A, B or empty"), but it is not the end of the world=
..
>> The current std::monostate design however has significant issues that IM=
HO
>> deserve another look.
>>
>>
>> We have two orthogonal interface decissions that could interact
>> * default construction
>> * possible empty
>>
>> A - We can have a variant class that is not default constructible and
>> cannot be empty.
>> B - We can have a variant class that is default constructible and can b=
e
>> empty, so the default constructor is naturally empty.
>> C - We can have a variant class that is default constructible and
>> cannot be empty (we need to state how it is default constructed).
>>
>> The not default constructible and empty seems not interesting enough.
>>
>> The current proposal correspond to C, when its first alternative is
>> default constructible and A otherwise, and I think this is the better we
>> can have.
>> The standard could also have a class behaving always as A. I wouldn't be
>> against.
>>
>> You are advocating for option B. I believe that option B would be
>> represented better by
>>
>> optional<variant<Ts...>>
>>
>> with a possible specialization implementation
>>
>> or by a variadic optional version
>>
>> optional<Ts...>
>>
>> All these concrete classes share a lot in common and I would expect that
>> the library implementor would make use of an implementation class that
>> covers the common parts.
>>
>
> =E2=80=8BA lot of effort has been put together to make option C possible =
and I do
> appreciate that, but why should we set option B aside while it is much
> easier to implement and more generic?
> recalling that a variant assignment generally consists of 3 steps:
>
> 1. back up destination.
> 2. copy source.
> 3. restore destination if 2 fails.
>
> consider Option C (direct porting of boost::variant into std):
> Q: what happens if during an assignment operation, copy from source throw=
s
> and the restoration move in the destination throws too?=E2=80=8B
> A: either a an uncaught exception or undefined behavior in a blank-less
> variant.
> Option B is not only easier,but also less dangerous: if copy fails and
> restoration fails too, reset to blank(null,empy ...).
>
> A worse scenario is when the backup move throws during the assignment;
> with option C it means the sky collapsing, whilst with option B the
> variant can reset to blank, a subsequent test of blankness can be used to
> check whether or not the assignment has succeeded.
>
> By the way what are the benefits of the never empty promise of option C?
> What might go wrong if the variant is in blank state? visitors might
> eventually ignore the null state or be forced to do something.
>
> And you have actually pointed out one of my concerns about overhead: the
> 'optional<variant<...>>'. With option B optional variant is just a thin A=
PI
> wrapper with no overhead on the variant, but with option C it is just
> paying twice the essential price.
>
> regards,
> FM.
>
>
Move operations shouldn't throw. So we shouldn't add an empty state to ALL
variants just for the rare case of throwing move.
And more rare than the types with throwing moves, is those types actually
throwing on move. ie even if a type has a throwing move, it will probably
never throw (typically it means you can't even allocated a few bytes - at
this point you are probably screwed anyhow).
So we have a very rare state of a should-be-rare type. Let's not litter
our code with if( !v.empty() ).... for that rare case. And if you do get
that rare case, you probably handled it via throw/catch, so your
variant-reading code doesn't happen, so again, you don't need to check for
empty.
So I don't think the empty state is worth it for throwing moves.
That leaves empty only being worthwhile for default-construction. I think
you can argue that, but the never-empty has benefits as well. So it is left
for the user to decide (by using a specific 'blank' type).
Tony
--=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/.
--089e01227ec043d24b0518a5ddea
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Jun 15, 2015 at 4:12 PM, Farid Mehrabi <span dir=3D"ltr"><<a=
href=3D"mailto:farid.mehrabi@gmail.com" target=3D"_blank">farid.mehrabi@gm=
ail.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=
"rtl"><div style=3D"font-family:arial narrow,sans-serif;font-size:large"><b=
r></div><div class=3D"gmail_extra"><span class=3D""><br><div class=3D"gmail=
_quote"><div dir=3D"ltr">2015-06-07 22:28 GMT+04:30 Vicente J. Botet Escrib=
a <span dir=3D"ltr"><<a href=3D"mailto:vicente.botet@wanadoo.fr" target=
=3D"_blank">vicente.botet@wanadoo.fr</a>></span>:<div style=3D"font-fami=
ly:'arial narrow',sans-serif;font-size:large;display:inline">=E2=80=
=8B=E2=80=8B</div></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div><span>
<blockquote type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The proposal
did not make clear to me why default constructed empty state
is such a big issue in the first place and the current
alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height:normal">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some arbitrary
decision.</span></li>
<li><span style=3D"line-height:normal">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember
"Oh, I have to use this std::monostate workaround if m=
y
type is not default constructible!". <i>Hacks</i>
(another spelling for 'workaround') are <i>bad</i>.=
</span></li>
<li><span style=3D"line-height:normal">It does not play well
with changes. Imagine if the user-defined type that was
previously default constructible has its default
constructor removed. Now the users needs to add
std::monostate all over the place and fix up all the
indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not &quo=
t;either A,
B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues
that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote></span>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 and
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 and
cannot=C2=A0 be empty (we need to state how it is default constructed).=
<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative is
default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
<br>
You are advocating for option B. I believe that option B would be
represented better by<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<variant<Ts...>><br>
<br>
with a possible specialization=C2=A0 implementation<br>
<br>
or by a variadic optional version<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<Ts...><br>
<br>
All these concrete classes share a lot in common and I would expect
that the library implementor would make use of an implementation
class that covers the common parts.<span><font color=3D"#888888"><br></=
font></span></div></blockquote></div><div><br></div></span><div style=3D"te=
xt-align:left"><div style=3D"font-family:'arial narrow',sans-serif;=
font-size:large" dir=3D"ltr">=E2=80=8BA lot of effort has been put together=
to make option C possible and I do appreciate that, but why should we set =
option B aside while it is much easier to implement and more generic?</div>=
<div style=3D"font-family:'arial narrow',sans-serif;font-size:large=
" dir=3D"ltr">recalling that a variant assignment generally consists of 3 s=
teps:</div><div style=3D"font-family:'arial narrow',sans-serif;font=
-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial nar=
row',sans-serif;font-size:large" dir=3D"ltr">1. back up destination.</d=
iv><div style=3D"font-family:'arial narrow',sans-serif;font-size:la=
rge" dir=3D"ltr">2. copy source.</div><div style=3D"font-family:'arial =
narrow',sans-serif;font-size:large" dir=3D"ltr">3. restore destination =
if 2 fails.</div><div style=3D"font-family:'arial narrow',sans-seri=
f;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'ari=
al narrow',sans-serif;font-size:large" dir=3D"ltr">consider Option C (d=
irect porting of boost::variant into std):</div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr">Q: what happe=
ns if during an assignment operation, copy from source throws and the resto=
ration move in the destination throws too?=E2=80=8B</div><div style=3D"font=
-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">=C2=
=A0A: either a an uncaught exception or undefined behavior in a blank-less =
variant.</div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">Option B is not only easier,but also less dange=
rous: if copy fails and restoration fails too, reset to blank(null,empy ...=
).</div><div style=3D"font-family:'arial narrow',sans-serif;font-si=
ze:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial narrow=
',sans-serif;font-size:large" dir=3D"ltr">A worse scenario is when the =
backup move throws during the assignment; =C2=A0with option C it means the =
sky collapsing, whilst with option B the variant can reset to blank, a subs=
equent test of blankness can be used to check whether or not the assignment=
has succeeded.</div><div style=3D"font-family:'arial narrow',sans-=
serif;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'=
;arial narrow',sans-serif;font-size:large" dir=3D"ltr">By the way what =
are the benefits of the never empty promise of option C? What might go wron=
g if the variant is in blank state? visitors might eventually ignore the nu=
ll state or be forced to do something.<br></div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr"><br></div><di=
v style=3D"font-family:'arial narrow',sans-serif;font-size:large" d=
ir=3D"ltr">And you have actually pointed out one of my concerns about overh=
ead: the 'optional<variant<...>>'. With option B option=
al variant is just a thin API wrapper with no overhead on the variant, but =
with option C it is just paying twice the essential price.</div><div style=
=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=3D"l=
tr"><br></div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">regards,</div><div style=3D"font-family:'ar=
ial narrow',sans-serif;font-size:large" dir=3D"ltr">FM.</div><br></div>=
</div></div></blockquote><div><br></div></div>Move operations shouldn't=
throw.=C2=A0 So we shouldn't add an empty state to ALL variants just f=
or the rare case of throwing move.<br></div><div class=3D"gmail_extra">And =
more rare than the types with throwing moves, is those types actually throw=
ing on move.=C2=A0 ie even if a type has a throwing move, it will probably =
never throw (typically it means you can't even allocated a few bytes - =
at this point you are probably screwed anyhow).<br><br></div><div class=3D"=
gmail_extra">So we have a very rare state of a should-be-rare type.=C2=A0 L=
et's not litter our code with if( !v.empty() ).... for that rare case.=
=C2=A0 And if you do get that rare case, you probably handled it via throw/=
catch, so your variant-reading code doesn't happen, so again, you don&#=
39;t need to check for empty.<br><br></div><div class=3D"gmail_extra">So I =
don't think the empty state is worth it for throwing moves.<br><br></di=
v><div class=3D"gmail_extra">That leaves empty only being worthwhile for de=
fault-construction.=C2=A0 I think you can argue that, but the never-empty h=
as benefits as well. So it is left for the user to decide (by using a speci=
fic 'blank' type).<br><br></div><div class=3D"gmail_extra">Tony<br>=
<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01227ec043d24b0518a5ddea--
.
Author: Farid Mehrabi <farid.mehrabi@gmail.com>
Date: Fri, 19 Jun 2015 20:56:54 +0430
Raw View
--001a11472e1acc82750518e1663a
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
2015-06-16 21:55 GMT+04:30 Tony V E <tvaneerd@gmail.com>:
>
>
> On Mon, Jun 15, 2015 at 4:12 PM, Farid Mehrabi <farid.mehrabi@gmail.com>
> wrote:
>
>>
>>
>> 2015-06-07 22:28 GMT+04:30 Vicente J. Botet Escriba <
>> vicente.botet@wanadoo.fr>:
>> =E2=80=8B=E2=80=8B
>>
>>> Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
>>>
>>> Hi everyone,
>>>
>>> I would like to voice my concerns about default construction of
>>> std::variant and std::monostate. The proposal did not make clear to me =
why
>>> default constructed empty state is such a big issue in the first place =
and
>>> the current alternative suffers from significant drawbacks:
>>>
>>> - To me it is very surprising that variant tries to
>>> default-construct the first type. Why not the 2nd, 5th type? I'd rat=
her
>>> have variant have no default constructor than some arbitrary decisio=
n.
>>> - It is yet another special case that users need to be taught about
>>> and frankly, it's not pretty either. Users have to remember "Oh, I h=
ave to
>>> use this std::monostate workaround if my type is not default
>>> constructible!". *Hacks* (another spelling for 'workaround') are
>>> *bad*.
>>> - It does not play well with changes. Imagine if the user-defined
>>> type that was previously default constructible has its default const=
ructor
>>> removed. Now the users needs to add std::monostate all over the plac=
e and
>>> fix up all the indices for index-based access.
>>>
>>> There needs to be a better solution. I do think that having an empty
>>> state semantically fails at the idea of variant in the first place ("ei=
ther
>>> A or B", not "either A, B or empty"), but it is not the end of the worl=
d.
>>> The current std::monostate design however has significant issues that I=
MHO
>>> deserve another look.
>>>
>>>
>>> We have two orthogonal interface decissions that could interact
>>> * default construction
>>> * possible empty
>>>
>>> A - We can have a variant class that is not default constructible and
>>> cannot be empty.
>>> B - We can have a variant class that is default constructible and can
>>> be empty, so the default constructor is naturally empty.
>>> C - We can have a variant class that is default constructible and
>>> cannot be empty (we need to state how it is default constructed).
>>>
>>> The not default constructible and empty seems not interesting enough.
>>>
>>> The current proposal correspond to C, when its first alternative is
>>> default constructible and A otherwise, and I think this is the better w=
e
>>> can have.
>>> The standard could also have a class behaving always as A. I wouldn't b=
e
>>> against.
>>>
>>> You are advocating for option B. I believe that option B would be
>>> represented better by
>>>
>>> optional<variant<Ts...>>
>>>
>>> with a possible specialization implementation
>>>
>>> or by a variadic optional version
>>>
>>> optional<Ts...>
>>>
>>> All these concrete classes share a lot in common and I would expect tha=
t
>>> the library implementor would make use of an implementation class that
>>> covers the common parts.
>>>
>>
>> =E2=80=8BA lot of effort has been put together to make option C possible=
and I do
>> appreciate that, but why should we set option B aside while it is much
>> easier to implement and more generic?
>> recalling that a variant assignment generally consists of 3 steps:
>>
>> 1. back up destination.
>> 2. copy source.
>> 3. restore destination if 2 fails.
>>
>> consider Option C (direct porting of boost::variant into std):
>> Q: what happens if during an assignment operation, copy from source
>> throws and the restoration move in the destination throws too?=E2=80=8B
>> A: either a an uncaught exception or undefined behavior in a blank-less
>> variant.
>> Option B is not only easier,but also less dangerous: if copy fails and
>> restoration fails too, reset to blank(null,empy ...).
>>
>> A worse scenario is when the backup move throws during the assignment;
>> with option C it means the sky collapsing, whilst with option B the
>> variant can reset to blank, a subsequent test of blankness can be used t=
o
>> check whether or not the assignment has succeeded.
>>
>> By the way what are the benefits of the never empty promise of option C?
>> What might go wrong if the variant is in blank state? visitors might
>> eventually ignore the null state or be forced to do something.
>>
>> And you have actually pointed out one of my concerns about overhead: the
>> 'optional<variant<...>>'. With option B optional variant is just a thin =
API
>> wrapper with no overhead on the variant, but with option C it is just
>> paying twice the essential price.
>>
>> regards,
>> FM.
>>
>>
> Move operations shouldn't throw. So we shouldn't add an empty state to
> ALL variants just for the rare case of throwing move.
> And more rare than the types with throwing moves, is those types actually
> throwing on move. ie even if a type has a throwing move, it will probabl=
y
> never throw (typically it means you can't even allocated a few bytes - at
> this point you are probably screwed anyhow).
>
=E2=80=8Bnever means never not almost never. and we can`t be sure on what
circumstances the move ctor may throw, and it is not just about the ctor;
backup/restoration involve destruction of the source/temporary, either of
which may throw.
>
> So we have a very rare state of a should-be-rare type. Let's not litter
> our code with if( !v.empty() ).... for that rare case. And if you do get
> that rare case, you probably handled it via throw/catch, so your
> variant-reading code doesn't happen, so again, you don't need to check fo=
r
> empty.
>
=E2=80=8Bif one is sure about the nothrow promise, then [s]he does not need=
to
check for blankness; don`t pay for what u don`t use.
But as library programmers we must care even 4 very rare cases in our
design.
> So I don't think the empty state is worth it for throwing moves.
>
=E2=80=8Bactually the assignment can be simplified to:
1. destruct original.
2. copy source
3. set to blank in case of any sort of failure.
=E2=80=8Bmuch easier than the never-empty promise.
On second thought =E2=80=8BI even considered option A and it looked even si=
mpler to
implement and more basic, now I can see why boost designers called for
proposals on policy-based variant design.
regards,
FM.
=E2=80=8B
--=20
how am I supposed to end the twisted road of your hair in such a dark
night??
unless the candle of your face does shed some light upon my way!!!
--=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/.
--001a11472e1acc82750518e1663a
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"rtl"><div class=3D"gmail_default" style=3D"font-family:arial na=
rrow,sans-serif;font-size:large"><br></div><div class=3D"gmail_extra"><div =
dir=3D"ltr"><br><div class=3D"gmail_quote">2015-06-16 21:55 GMT+04:30 Tony =
V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_=
blank">tvaneerd@gmail.com</a>></span>:<br><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 .8ex;border-left:1px #ccc solid;border-right:1px #ccc=
solid;padding-left:1ex;padding-right:1ex"><br><div class=3D"gmail_extra"><=
div><div class=3D"h5"><br><div class=3D"gmail_quote">On Mon, Jun 15, 2015 a=
t 4:12 PM, Farid Mehrabi <span dir=3D"ltr"><<a href=3D"mailto:farid.mehr=
abi@gmail.com" target=3D"_blank">farid.mehrabi@gmail.com</a>></span> wro=
te:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div dir=3D"rtl"><div style=3D"font-f=
amily:arial narrow,sans-serif;font-size:large"><br></div><div class=3D"gmai=
l_extra"><span><br><div class=3D"gmail_quote"><div dir=3D"ltr">2015-06-07 2=
2:28 GMT+04:30 Vicente J. Botet Escriba <span dir=3D"ltr"><<a href=3D"ma=
ilto:vicente.botet@wanadoo.fr" target=3D"_blank">vicente.botet@wanadoo.fr</=
a>></span>:<div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large;display:inline">=E2=80=8B=E2=80=8B</div></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div><span>
<blockquote type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The proposal
did not make clear to me why default constructed empty state
is such a big issue in the first place and the current
alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height:normal">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some arbitrary
decision.</span></li>
<li><span style=3D"line-height:normal">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember
"Oh, I have to use this std::monostate workaround if m=
y
type is not default constructible!". <i>Hacks</i>
(another spelling for 'workaround') are <i>bad</i>.=
</span></li>
<li><span style=3D"line-height:normal">It does not play well
with changes. Imagine if the user-defined type that was
previously default constructible has its default
constructor removed. Now the users needs to add
std::monostate all over the place and fix up all the
indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not &quo=
t;either A,
B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues
that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote></span>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 and
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 and
cannot=C2=A0 be empty (we need to state how it is default constructed).=
<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative is
default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
<br>
You are advocating for option B. I believe that option B would be
represented better by<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<variant<Ts...>><br>
<br>
with a possible specialization=C2=A0 implementation<br>
<br>
or by a variadic optional version<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<Ts...><br>
<br>
All these concrete classes share a lot in common and I would expect
that the library implementor would make use of an implementation
class that covers the common parts.<span><font color=3D"#888888"><br></=
font></span></div></blockquote></div><div><br></div></span><div style=3D"te=
xt-align:left"><div style=3D"font-family:'arial narrow',sans-serif;=
font-size:large" dir=3D"ltr">=E2=80=8BA lot of effort has been put together=
to make option C possible and I do appreciate that, but why should we set =
option B aside while it is much easier to implement and more generic?</div>=
<div style=3D"font-family:'arial narrow',sans-serif;font-size:large=
" dir=3D"ltr">recalling that a variant assignment generally consists of 3 s=
teps:</div><div style=3D"font-family:'arial narrow',sans-serif;font=
-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial nar=
row',sans-serif;font-size:large" dir=3D"ltr">1. back up destination.</d=
iv><div style=3D"font-family:'arial narrow',sans-serif;font-size:la=
rge" dir=3D"ltr">2. copy source.</div><div style=3D"font-family:'arial =
narrow',sans-serif;font-size:large" dir=3D"ltr">3. restore destination =
if 2 fails.</div><div style=3D"font-family:'arial narrow',sans-seri=
f;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'ari=
al narrow',sans-serif;font-size:large" dir=3D"ltr">consider Option C (d=
irect porting of boost::variant into std):</div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr">Q: what happe=
ns if during an assignment operation, copy from source throws and the resto=
ration move in the destination throws too?=E2=80=8B</div><div style=3D"font=
-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">=C2=
=A0A: either a an uncaught exception or undefined behavior in a blank-less =
variant.</div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">Option B is not only easier,but also less dange=
rous: if copy fails and restoration fails too, reset to blank(null,empy ...=
).</div><div style=3D"font-family:'arial narrow',sans-serif;font-si=
ze:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial narrow=
',sans-serif;font-size:large" dir=3D"ltr">A worse scenario is when the =
backup move throws during the assignment; =C2=A0with option C it means the =
sky collapsing, whilst with option B the variant can reset to blank, a subs=
equent test of blankness can be used to check whether or not the assignment=
has succeeded.</div><div style=3D"font-family:'arial narrow',sans-=
serif;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'=
;arial narrow',sans-serif;font-size:large" dir=3D"ltr">By the way what =
are the benefits of the never empty promise of option C? What might go wron=
g if the variant is in blank state? visitors might eventually ignore the nu=
ll state or be forced to do something.<br></div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr"><br></div><di=
v style=3D"font-family:'arial narrow',sans-serif;font-size:large" d=
ir=3D"ltr">And you have actually pointed out one of my concerns about overh=
ead: the 'optional<variant<...>>'. With option B option=
al variant is just a thin API wrapper with no overhead on the variant, but =
with option C it is just paying twice the essential price.</div><div style=
=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=3D"l=
tr"><br></div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">regards,</div><div style=3D"font-family:'ar=
ial narrow',sans-serif;font-size:large" dir=3D"ltr">FM.</div><br></div>=
</div></div></blockquote><div><br></div></div></div></div>Move operations s=
houldn't throw.=C2=A0 So we shouldn't add an empty state to ALL var=
iants just for the rare case of throwing move.<br></div><div class=3D"gmail=
_extra">And more rare than the types with throwing moves, is those types ac=
tually throwing on move.=C2=A0 ie even if a type has a throwing move, it wi=
ll probably never throw (typically it means you can't even allocated a =
few bytes - at this point you are probably screwed anyhow).<br></div></bloc=
kquote><div><br></div><div><div class=3D"gmail_default" style=3D"font-famil=
y:'arial narrow',sans-serif;font-size:large">=E2=80=8Bnever means n=
ever not almost never. and we can`t be sure on what circumstances the move =
ctor may throw, and it is not just about the ctor; backup/restoration invol=
ve destruction of the source/temporary, either of which may throw.</div></d=
iv><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 .8e=
x;border-left:1px #ccc solid;border-right:1px #ccc solid;padding-left:1ex;p=
adding-right:1ex"><div class=3D"gmail_extra"><br></div><div class=3D"gmail_=
extra">So we have a very rare state of a should-be-rare type.=C2=A0 Let'=
;s not litter our code with if( !v.empty() ).... for that rare case.=C2=A0 =
And if you do get that rare case, you probably handled it via throw/catch, =
so your variant-reading code doesn't happen, so again, you don't ne=
ed to check for empty.<br></div></blockquote><div><br></div><div><div class=
=3D"gmail_default" style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large;display:inline">=E2=80=8Bif one is sure about the nothrow pr=
omise, then [s]he does not need to check for blankness; don`t pay for what =
u don`t use.</div></div><div><div class=3D"gmail_default" style=3D"font-fam=
ily:'arial narrow',sans-serif;font-size:large;display:inline">But a=
s library programmers we must care even 4 very rare cases in our design.</d=
iv></div><div><div class=3D"gmail_default" style=3D"font-family:'arial =
narrow',sans-serif;font-size:large;display:inline"><br></div></div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 .8ex;border-left:1px #ccc s=
olid;border-right:1px #ccc solid;padding-left:1ex;padding-right:1ex"><div c=
lass=3D"gmail_extra"><br></div><div class=3D"gmail_extra">So I don't th=
ink the empty state is worth it for throwing moves.<br></div></blockquote><=
div><br></div><div><div class=3D"gmail_default" style=3D"font-family:'a=
rial narrow',sans-serif;font-size:large;display:inline">=E2=80=8Bactual=
ly the assignment can be simplified to:</div></div><div><div class=3D"gmail=
_default" style=3D"font-family:'arial narrow',sans-serif;font-size:=
large;display:inline"><br></div></div><div><div class=3D"gmail_default" sty=
le=3D"font-family:'arial narrow',sans-serif;font-size:large;display=
:inline">1. destruct original.</div></div><div><div class=3D"gmail_default"=
style=3D"font-family:'arial narrow',sans-serif;font-size:large;dis=
play:inline">2. copy source</div></div><div><div class=3D"gmail_default" st=
yle=3D"font-family:'arial narrow',sans-serif;font-size:large;displa=
y:inline">3. set to blank in case of any sort of failure.</div></div><div><=
div class=3D"gmail_default" style=3D"font-family:'arial narrow',san=
s-serif;font-size:large;display:inline"><br></div></div><div><div class=3D"=
gmail_default" style=3D"font-family:'arial narrow',sans-serif;font-=
size:large">=E2=80=8Bmuch easier than the never-empty promise.</div><div cl=
ass=3D"gmail_default" style=3D"font-family:'arial narrow',sans-seri=
f;font-size:large"><br></div><div class=3D"gmail_default" style=3D"font-fam=
ily:'arial narrow',sans-serif;font-size:large">On second thought =
=E2=80=8BI even considered option A and it looked even simpler to implement=
and more basic, now I can see why boost designers called for proposals on =
policy-based variant design.</div><div class=3D"gmail_default" style=3D"fon=
t-family:'arial narrow',sans-serif;font-size:large"><br></div><div =
class=3D"gmail_default" style=3D"font-family:'arial narrow',sans-se=
rif;font-size:large">regards,</div><div class=3D"gmail_default" style=3D"fo=
nt-family:'arial narrow',sans-serif;font-size:large">FM.</div><br><=
/div><div><div class=3D"gmail_default" style=3D"font-family:'arial narr=
ow',sans-serif;font-size:large;display:inline">=E2=80=8B</div>=C2=A0</d=
iv></div></div>-- <br><div class=3D"gmail_signature"><div dir=3D"rtl"><div>=
<div dir=3D"ltr">how am I supposed to end the twisted road of=C2=A0 your ha=
ir in such a dark night??<br>unless the candle of your face does shed some =
light upon my way!!!<br></div></div></div></div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11472e1acc82750518e1663a--
.
Author: Patrice Roy <patricer@gmail.com>
Date: Fri, 19 Jun 2015 12:32:19 -0400
Raw View
--001a11c3677ec5495b0518e1778e
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I hope for users that the =C2=ABassignment simplified to=C2=BB as you prese=
nt it
takes care of self-assignment (a =3D a; for some a), otherwise, with the
algorithm presented here, they're in for a surprise :)
2015-06-19 12:26 GMT-04:00 Farid Mehrabi <farid.mehrabi@gmail.com>:
>
>
> 2015-06-16 21:55 GMT+04:30 Tony V E <tvaneerd@gmail.com>:
>
>>
>>
>> On Mon, Jun 15, 2015 at 4:12 PM, Farid Mehrabi <farid.mehrabi@gmail.com>
>> wrote:
>>
>>>
>>>
>>> 2015-06-07 22:28 GMT+04:30 Vicente J. Botet Escriba <
>>> vicente.botet@wanadoo.fr>:
>>> =E2=80=8B=E2=80=8B
>>>
>>>> Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
>>>>
>>>> Hi everyone,
>>>>
>>>> I would like to voice my concerns about default construction of
>>>> std::variant and std::monostate. The proposal did not make clear to me=
why
>>>> default constructed empty state is such a big issue in the first place=
and
>>>> the current alternative suffers from significant drawbacks:
>>>>
>>>> - To me it is very surprising that variant tries to
>>>> default-construct the first type. Why not the 2nd, 5th type? I'd ra=
ther
>>>> have variant have no default constructor than some arbitrary decisi=
on.
>>>> - It is yet another special case that users need to be taught about
>>>> and frankly, it's not pretty either. Users have to remember "Oh, I =
have to
>>>> use this std::monostate workaround if my type is not default
>>>> constructible!". *Hacks* (another spelling for 'workaround') are
>>>> *bad*.
>>>> - It does not play well with changes. Imagine if the user-defined
>>>> type that was previously default constructible has its default cons=
tructor
>>>> removed. Now the users needs to add std::monostate all over the pla=
ce and
>>>> fix up all the indices for index-based access.
>>>>
>>>> There needs to be a better solution. I do think that having an empty
>>>> state semantically fails at the idea of variant in the first place ("e=
ither
>>>> A or B", not "either A, B or empty"), but it is not the end of the wor=
ld.
>>>> The current std::monostate design however has significant issues that =
IMHO
>>>> deserve another look.
>>>>
>>>>
>>>> We have two orthogonal interface decissions that could interact
>>>> * default construction
>>>> * possible empty
>>>>
>>>> A - We can have a variant class that is not default constructible and
>>>> cannot be empty.
>>>> B - We can have a variant class that is default constructible and can
>>>> be empty, so the default constructor is naturally empty.
>>>> C - We can have a variant class that is default constructible and
>>>> cannot be empty (we need to state how it is default constructed).
>>>>
>>>> The not default constructible and empty seems not interesting enough.
>>>>
>>>> The current proposal correspond to C, when its first alternative is
>>>> default constructible and A otherwise, and I think this is the better =
we
>>>> can have.
>>>> The standard could also have a class behaving always as A. I wouldn't
>>>> be against.
>>>>
>>>> You are advocating for option B. I believe that option B would be
>>>> represented better by
>>>>
>>>> optional<variant<Ts...>>
>>>>
>>>> with a possible specialization implementation
>>>>
>>>> or by a variadic optional version
>>>>
>>>> optional<Ts...>
>>>>
>>>> All these concrete classes share a lot in common and I would expect
>>>> that the library implementor would make use of an implementation class=
that
>>>> covers the common parts.
>>>>
>>>
>>> =E2=80=8BA lot of effort has been put together to make option C possibl=
e and I
>>> do appreciate that, but why should we set option B aside while it is mu=
ch
>>> easier to implement and more generic?
>>> recalling that a variant assignment generally consists of 3 steps:
>>>
>>> 1. back up destination.
>>> 2. copy source.
>>> 3. restore destination if 2 fails.
>>>
>>> consider Option C (direct porting of boost::variant into std):
>>> Q: what happens if during an assignment operation, copy from source
>>> throws and the restoration move in the destination throws too?=E2=80=8B
>>> A: either a an uncaught exception or undefined behavior in a blank-les=
s
>>> variant.
>>> Option B is not only easier,but also less dangerous: if copy fails and
>>> restoration fails too, reset to blank(null,empy ...).
>>>
>>> A worse scenario is when the backup move throws during the assignment;
>>> with option C it means the sky collapsing, whilst with option B the
>>> variant can reset to blank, a subsequent test of blankness can be used =
to
>>> check whether or not the assignment has succeeded.
>>>
>>> By the way what are the benefits of the never empty promise of option C=
?
>>> What might go wrong if the variant is in blank state? visitors might
>>> eventually ignore the null state or be forced to do something.
>>>
>>> And you have actually pointed out one of my concerns about overhead: th=
e
>>> 'optional<variant<...>>'. With option B optional variant is just a thin=
API
>>> wrapper with no overhead on the variant, but with option C it is just
>>> paying twice the essential price.
>>>
>>> regards,
>>> FM.
>>>
>>>
>> Move operations shouldn't throw. So we shouldn't add an empty state to
>> ALL variants just for the rare case of throwing move.
>> And more rare than the types with throwing moves, is those types actuall=
y
>> throwing on move. ie even if a type has a throwing move, it will probab=
ly
>> never throw (typically it means you can't even allocated a few bytes - a=
t
>> this point you are probably screwed anyhow).
>>
>
> =E2=80=8Bnever means never not almost never. and we can`t be sure on what
> circumstances the move ctor may throw, and it is not just about the ctor;
> backup/restoration involve destruction of the source/temporary, either of
> which may throw.
>
>
>>
>> So we have a very rare state of a should-be-rare type. Let's not litter
>> our code with if( !v.empty() ).... for that rare case. And if you do ge=
t
>> that rare case, you probably handled it via throw/catch, so your
>> variant-reading code doesn't happen, so again, you don't need to check f=
or
>> empty.
>>
>
> =E2=80=8Bif one is sure about the nothrow promise, then [s]he does not ne=
ed to
> check for blankness; don`t pay for what u don`t use.
> But as library programmers we must care even 4 very rare cases in our
> design.
>
>
>> So I don't think the empty state is worth it for throwing moves.
>>
>
> =E2=80=8Bactually the assignment can be simplified to:
>
> 1. destruct original.
> 2. copy source
> 3. set to blank in case of any sort of failure.
>
> =E2=80=8Bmuch easier than the never-empty promise.
>
> On second thought =E2=80=8BI even considered option A and it looked even =
simpler
> to implement and more basic, now I can see why boost designers called for
> proposals on policy-based variant design.
>
> regards,
> FM.
>
> =E2=80=8B
>
> --
> how am I supposed to end the twisted road of your hair in such a dark
> night??
> unless the candle of your face does shed some light upon my way!!!
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=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/.
--001a11c3677ec5495b0518e1778e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I hope for users that the =C2=ABassignment simplified to=
=C2=BB as you present it takes care of self-assignment (a =3D a; for some a=
), otherwise, with the algorithm presented here, they're in for a surpr=
ise :)<br></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">2=
015-06-19 12:26 GMT-04:00 Farid Mehrabi <span dir=3D"ltr"><<a href=3D"ma=
ilto:farid.mehrabi@gmail.com" target=3D"_blank">farid.mehrabi@gmail.com</a>=
></span>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"rtl"><div class=
=3D"gmail_default" style=3D"font-family:arial narrow,sans-serif;font-size:l=
arge"><br></div><div class=3D"gmail_extra"><div dir=3D"ltr"><br><div class=
=3D"gmail_quote"><div><div class=3D"h5">2015-06-16 21:55 GMT+04:30 Tony V E=
<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_bla=
nk">tvaneerd@gmail.com</a>></span>:<br><blockquote class=3D"gmail_quote"=
style=3D"margin:0 .8ex;border-left:1px #ccc solid;border-right:1px #ccc so=
lid;padding-left:1ex;padding-right:1ex"><br><div class=3D"gmail_extra"><div=
><div><br><div class=3D"gmail_quote">On Mon, Jun 15, 2015 at 4:12 PM, Farid=
Mehrabi <span dir=3D"ltr"><<a href=3D"mailto:farid.mehrabi@gmail.com" t=
arget=3D"_blank">farid.mehrabi@gmail.com</a>></span> wrote:<br><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><div dir=3D"rtl"><div style=3D"font-family:arial narr=
ow,sans-serif;font-size:large"><br></div><div class=3D"gmail_extra"><span><=
br><div class=3D"gmail_quote"><div dir=3D"ltr">2015-06-07 22:28 GMT+04:30 V=
icente J. Botet Escriba <span dir=3D"ltr"><<a href=3D"mailto:vicente.bot=
et@wanadoo.fr" target=3D"_blank">vicente.botet@wanadoo.fr</a>></span>:<d=
iv style=3D"font-family:'arial narrow',sans-serif;font-size:large;d=
isplay:inline">=E2=80=8B=E2=80=8B</div></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"=
>
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div><span>
<blockquote type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The proposal
did not make clear to me why default constructed empty state
is such a big issue in the first place and the current
alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height:normal">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some arbitrary
decision.</span></li>
<li><span style=3D"line-height:normal">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember
"Oh, I have to use this std::monostate workaround if m=
y
type is not default constructible!". <i>Hacks</i>
(another spelling for 'workaround') are <i>bad</i>.=
</span></li>
<li><span style=3D"line-height:normal">It does not play well
with changes. Imagine if the user-defined type that was
previously default constructible has its default
constructor removed. Now the users needs to add
std::monostate all over the place and fix up all the
indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not &quo=
t;either A,
B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues
that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote></span>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 and
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 and
cannot=C2=A0 be empty (we need to state how it is default constructed).=
<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative is
default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
<br>
You are advocating for option B. I believe that option B would be
represented better by<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<variant<Ts...>><br>
<br>
with a possible specialization=C2=A0 implementation<br>
<br>
or by a variadic optional version<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<Ts...><br>
<br>
All these concrete classes share a lot in common and I would expect
that the library implementor would make use of an implementation
class that covers the common parts.<span><font color=3D"#888888"><br></=
font></span></div></blockquote></div><div><br></div></span><div style=3D"te=
xt-align:left"><div style=3D"font-family:'arial narrow',sans-serif;=
font-size:large" dir=3D"ltr">=E2=80=8BA lot of effort has been put together=
to make option C possible and I do appreciate that, but why should we set =
option B aside while it is much easier to implement and more generic?</div>=
<div style=3D"font-family:'arial narrow',sans-serif;font-size:large=
" dir=3D"ltr">recalling that a variant assignment generally consists of 3 s=
teps:</div><div style=3D"font-family:'arial narrow',sans-serif;font=
-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial nar=
row',sans-serif;font-size:large" dir=3D"ltr">1. back up destination.</d=
iv><div style=3D"font-family:'arial narrow',sans-serif;font-size:la=
rge" dir=3D"ltr">2. copy source.</div><div style=3D"font-family:'arial =
narrow',sans-serif;font-size:large" dir=3D"ltr">3. restore destination =
if 2 fails.</div><div style=3D"font-family:'arial narrow',sans-seri=
f;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'ari=
al narrow',sans-serif;font-size:large" dir=3D"ltr">consider Option C (d=
irect porting of boost::variant into std):</div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr">Q: what happe=
ns if during an assignment operation, copy from source throws and the resto=
ration move in the destination throws too?=E2=80=8B</div><div style=3D"font=
-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">=C2=
=A0A: either a an uncaught exception or undefined behavior in a blank-less =
variant.</div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">Option B is not only easier,but also less dange=
rous: if copy fails and restoration fails too, reset to blank(null,empy ...=
).</div><div style=3D"font-family:'arial narrow',sans-serif;font-si=
ze:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial narrow=
',sans-serif;font-size:large" dir=3D"ltr">A worse scenario is when the =
backup move throws during the assignment; =C2=A0with option C it means the =
sky collapsing, whilst with option B the variant can reset to blank, a subs=
equent test of blankness can be used to check whether or not the assignment=
has succeeded.</div><div style=3D"font-family:'arial narrow',sans-=
serif;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'=
;arial narrow',sans-serif;font-size:large" dir=3D"ltr">By the way what =
are the benefits of the never empty promise of option C? What might go wron=
g if the variant is in blank state? visitors might eventually ignore the nu=
ll state or be forced to do something.<br></div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr"><br></div><di=
v style=3D"font-family:'arial narrow',sans-serif;font-size:large" d=
ir=3D"ltr">And you have actually pointed out one of my concerns about overh=
ead: the 'optional<variant<...>>'. With option B option=
al variant is just a thin API wrapper with no overhead on the variant, but =
with option C it is just paying twice the essential price.</div><div style=
=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=3D"l=
tr"><br></div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">regards,</div><div style=3D"font-family:'ar=
ial narrow',sans-serif;font-size:large" dir=3D"ltr">FM.</div><br></div>=
</div></div></blockquote><div><br></div></div></div></div>Move operations s=
houldn't throw.=C2=A0 So we shouldn't add an empty state to ALL var=
iants just for the rare case of throwing move.<br></div><div class=3D"gmail=
_extra">And more rare than the types with throwing moves, is those types ac=
tually throwing on move.=C2=A0 ie even if a type has a throwing move, it wi=
ll probably never throw (typically it means you can't even allocated a =
few bytes - at this point you are probably screwed anyhow).<br></div></bloc=
kquote><div><br></div></div></div><div><div class=3D"gmail_default" style=
=3D"font-family:'arial narrow',sans-serif;font-size:large">=E2=80=
=8Bnever means never not almost never. and we can`t be sure on what circums=
tances the move ctor may throw, and it is not just about the ctor; backup/r=
estoration involve destruction of the source/temporary, either of which may=
throw.</div></div><span class=3D""><div>=C2=A0</div><blockquote class=3D"g=
mail_quote" style=3D"margin:0 .8ex;border-left:1px #ccc solid;border-right:=
1px #ccc solid;padding-left:1ex;padding-right:1ex"><div class=3D"gmail_extr=
a"><br></div><div class=3D"gmail_extra">So we have a very rare state of a s=
hould-be-rare type.=C2=A0 Let's not litter our code with if( !v.empty()=
).... for that rare case.=C2=A0 And if you do get that rare case, you prob=
ably handled it via throw/catch, so your variant-reading code doesn't h=
appen, so again, you don't need to check for empty.<br></div></blockquo=
te><div><br></div></span><div><div class=3D"gmail_default" style=3D"font-fa=
mily:'arial narrow',sans-serif;font-size:large;display:inline">=E2=
=80=8Bif one is sure about the nothrow promise, then [s]he does not need to=
check for blankness; don`t pay for what u don`t use.</div></div><div><div =
class=3D"gmail_default" style=3D"font-family:'arial narrow',sans-se=
rif;font-size:large;display:inline">But as library programmers we must care=
even 4 very rare cases in our design.</div></div><span class=3D""><div><di=
v class=3D"gmail_default" style=3D"font-family:'arial narrow',sans-=
serif;font-size:large;display:inline"><br></div></div><blockquote class=3D"=
gmail_quote" style=3D"margin:0 .8ex;border-left:1px #ccc solid;border-right=
:1px #ccc solid;padding-left:1ex;padding-right:1ex"><div class=3D"gmail_ext=
ra"><br></div><div class=3D"gmail_extra">So I don't think the empty sta=
te is worth it for throwing moves.<br></div></blockquote><div><br></div></s=
pan><div><div class=3D"gmail_default" style=3D"font-family:'arial narro=
w',sans-serif;font-size:large;display:inline">=E2=80=8Bactually the ass=
ignment can be simplified to:</div></div><div><div class=3D"gmail_default" =
style=3D"font-family:'arial narrow',sans-serif;font-size:large;disp=
lay:inline"><br></div></div><div><div class=3D"gmail_default" style=3D"font=
-family:'arial narrow',sans-serif;font-size:large;display:inline">1=
.. destruct original.</div></div><div><div class=3D"gmail_default" style=3D"=
font-family:'arial narrow',sans-serif;font-size:large;display:inlin=
e">2. copy source</div></div><div><div class=3D"gmail_default" style=3D"fon=
t-family:'arial narrow',sans-serif;font-size:large;display:inline">=
3. set to blank in case of any sort of failure.</div></div><div><div class=
=3D"gmail_default" style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large;display:inline"><br></div></div><div><div class=3D"gmail_def=
ault" style=3D"font-family:'arial narrow',sans-serif;font-size:larg=
e">=E2=80=8Bmuch easier than the never-empty promise.</div><div class=3D"gm=
ail_default" style=3D"font-family:'arial narrow',sans-serif;font-si=
ze:large"><br></div><div class=3D"gmail_default" style=3D"font-family:'=
arial narrow',sans-serif;font-size:large">On second thought =E2=80=8BI =
even considered option A and it looked even simpler to implement and more b=
asic, now I can see why boost designers called for proposals on policy-base=
d variant design.</div><div class=3D"gmail_default" style=3D"font-family:&#=
39;arial narrow',sans-serif;font-size:large"><br></div><div class=3D"gm=
ail_default" style=3D"font-family:'arial narrow',sans-serif;font-si=
ze:large">regards,</div><div class=3D"gmail_default" style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large">FM.</div><br></div><div><=
div class=3D"gmail_default" style=3D"font-family:'arial narrow',san=
s-serif;font-size:large;display:inline">=E2=80=8B</div>=C2=A0</div></div></=
div><span class=3D"">-- <br><div><div dir=3D"rtl"><div><div dir=3D"ltr">how=
am I supposed to end the twisted road of=C2=A0 your hair in such a dark ni=
ght??<br>unless the candle of your face does shed some light upon my way!!!=
<br></div></div></div></div>
</span></div></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--001a11c3677ec5495b0518e1778e--
.
Author: Farid Mehrabi <farid.mehrabi@gmail.com>
Date: Fri, 19 Jun 2015 21:35:22 +0430
Raw View
--001a113569e260589f0518e1f05a
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
is that so hard to guard against self assignment? even a novice like me can
do it. I am leaving the details for the sake of main point. but thanx for
reminder.
regards,
FM.
2015-06-19 21:02 GMT+04:30 Patrice Roy <patricer@gmail.com>:
> I hope for users that the =C2=ABassignment simplified to=C2=BB as you pre=
sent it
> takes care of self-assignment (a =3D a; for some a), otherwise, with the
> algorithm presented here, they're in for a surprise :)
>
2015-06-19 12:26 GMT-04:00 Farid Mehrabi <farid.mehrabi@gmail.com>:
>
>
> 2015-06-16 21:55 GMT+04:30 Tony V E <tvaneerd@gmail.com>:
>
>>
>>
>> On Mon, Jun 15, 2015 at 4:12 PM, Farid Mehrabi <farid.mehrabi@gmail.com>
>> wrote:
>>
>>>
>>>
>>> 2015-06-07 22:28 GMT+04:30 Vicente J. Botet Escriba <
>>> vicente.botet@wanadoo.fr>:
>>> =E2=80=8B=E2=80=8B
>>>
>>>> Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
>>>>
>>>> Hi everyone,
>>>>
>>>> I would like to voice my concerns about default construction of
>>>> std::variant and std::monostate. The proposal did not make clear to me=
why
>>>> default constructed empty state is such a big issue in the first place=
and
>>>> the current alternative suffers from significant drawbacks:
>>>>
>>>> - To me it is very surprising that variant tries to
>>>> default-construct the first type. Why not the 2nd, 5th type? I'd ra=
ther
>>>> have variant have no default constructor than some arbitrary decisi=
on.
>>>> - It is yet another special case that users need to be taught about
>>>> and frankly, it's not pretty either. Users have to remember "Oh, I =
have to
>>>> use this std::monostate workaround if my type is not default
>>>> constructible!". *Hacks* (another spelling for 'workaround') are
>>>> *bad*.
>>>> - It does not play well with changes. Imagine if the user-defined
>>>> type that was previously default constructible has its default cons=
tructor
>>>> removed. Now the users needs to add std::monostate all over the pla=
ce and
>>>> fix up all the indices for index-based access.
>>>>
>>>> There needs to be a better solution. I do think that having an empty
>>>> state semantically fails at the idea of variant in the first place ("e=
ither
>>>> A or B", not "either A, B or empty"), but it is not the end of the wor=
ld.
>>>> The current std::monostate design however has significant issues that =
IMHO
>>>> deserve another look.
>>>>
>>>>
>>>> We have two orthogonal interface decissions that could interact
>>>> * default construction
>>>> * possible empty
>>>>
>>>> A - We can have a variant class that is not default constructible and
>>>> cannot be empty.
>>>> B - We can have a variant class that is default constructible and can
>>>> be empty, so the default constructor is naturally empty.
>>>> C - We can have a variant class that is default constructible and
>>>> cannot be empty (we need to state how it is default constructed).
>>>>
>>>> The not default constructible and empty seems not interesting enough.
>>>>
>>>> The current proposal correspond to C, when its first alternative is
>>>> default constructible and A otherwise, and I think this is the better =
we
>>>> can have.
>>>> The standard could also have a class behaving always as A. I wouldn't
>>>> be against.
>>>>
>>>> You are advocating for option B. I believe that option B would be
>>>> represented better by
>>>>
>>>> optional<variant<Ts...>>
>>>>
>>>> with a possible specialization implementation
>>>>
>>>> or by a variadic optional version
>>>>
>>>> optional<Ts...>
>>>>
>>>> All these concrete classes share a lot in common and I would expect
>>>> that the library implementor would make use of an implementation class=
that
>>>> covers the common parts.
>>>>
>>>
>>> =E2=80=8BA lot of effort has been put together to make option C possibl=
e and I
>>> do appreciate that, but why should we set option B aside while it is mu=
ch
>>> easier to implement and more generic?
>>> recalling that a variant assignment generally consists of 3 steps:
>>>
>>> 1. back up destination.
>>> 2. copy source.
>>> 3. restore destination if 2 fails.
>>>
>>> consider Option C (direct porting of boost::variant into std):
>>> Q: what happens if during an assignment operation, copy from source
>>> throws and the restoration move in the destination throws too?=E2=80=8B
>>> A: either a an uncaught exception or undefined behavior in a blank-les=
s
>>> variant.
>>> Option B is not only easier,but also less dangerous: if copy fails and
>>> restoration fails too, reset to blank(null,empy ...).
>>>
>>> A worse scenario is when the backup move throws during the assignment;
>>> with option C it means the sky collapsing, whilst with option B the
>>> variant can reset to blank, a subsequent test of blankness can be used =
to
>>> check whether or not the assignment has succeeded.
>>>
>>> By the way what are the benefits of the never empty promise of option C=
?
>>> What might go wrong if the variant is in blank state? visitors might
>>> eventually ignore the null state or be forced to do something.
>>>
>>> And you have actually pointed out one of my concerns about overhead: th=
e
>>> 'optional<variant<...>>'. With option B optional variant is just a thin=
API
>>> wrapper with no overhead on the variant, but with option C it is just
>>> paying twice the essential price.
>>>
>>> regards,
>>> FM.
>>>
>>>
>> Move operations shouldn't throw. So we shouldn't add an empty state to
>> ALL variants just for the rare case of throwing move.
>> And more rare than the types with throwing moves, is those types actuall=
y
>> throwing on move. ie even if a type has a throwing move, it will probab=
ly
>> never throw (typically it means you can't even allocated a few bytes - a=
t
>> this point you are probably screwed anyhow).
>>
>
> =E2=80=8Bnever means never not almost never. and we can`t be sure on what
> circumstances the move ctor may throw, and it is not just about the ctor;
> backup/restoration involve destruction of the source/temporary, either of
> which may throw.
>
>
>>
>> So we have a very rare state of a should-be-rare type. Let's not litter
>> our code with if( !v.empty() ).... for that rare case. And if you do ge=
t
>> that rare case, you probably handled it via throw/catch, so your
>> variant-reading code doesn't happen, so again, you don't need to check f=
or
>> empty.
>>
>
> =E2=80=8Bif one is sure about the nothrow promise, then [s]he does not ne=
ed to
> check for blankness; don`t pay for what u don`t use.
> But as library programmers we must care even 4 very rare cases in our
> design.
>
>
>> So I don't think the empty state is worth it for throwing moves.
>>
>
> =E2=80=8Bactually the assignment can be simplified to:
>
> 1. destruct original.
> 2. copy source
> 3. set to blank in case of any sort of failure.
>
> =E2=80=8Bmuch easier than the never-empty promise.
>
> On second thought =E2=80=8BI even considered option A and it looked even =
simpler
> to implement and more basic, now I can see why boost designers called for
> proposals on policy-based variant design.
>
> regards,
> FM.
>
> =E2=80=8B
>
> --
> how am I supposed to end the twisted road of your hair in such a dark
> night??
> unless the candle of your face does shed some light upon my way!!!
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-proposals/.
--=20
how am I supposed to end the twisted road of your hair in such a dark
night??
unless the candle of your face does shed some light upon my way!!!
--=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/.
--001a113569e260589f0518e1f05a
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"rtl"><div class=3D"gmail_default" style=3D"font-family:arial na=
rrow,sans-serif;font-size:large" dir=3D"ltr">is that so hard to guard again=
st self assignment? even a novice like me can do it. I am leaving the detai=
ls for the sake of =C2=A0main point. but thanx for reminder.</div><div clas=
s=3D"gmail_default" style=3D"font-family:arial narrow,sans-serif;font-size:=
large" dir=3D"ltr"><br></div><div class=3D"gmail_default" style=3D"font-fam=
ily:arial narrow,sans-serif;font-size:large" dir=3D"ltr">regards,</div><div=
class=3D"gmail_default" style=3D"font-family:arial narrow,sans-serif;font-=
size:large" dir=3D"ltr">FM.</div></div><div class=3D"gmail_extra"><div dir=
=3D"ltr"><br><div class=3D"gmail_quote">2015-06-19 21:02 GMT+04:30 Patrice =
Roy <span dir=3D"ltr"><<a href=3D"mailto:patricer@gmail.com" target=3D"_=
blank">patricer@gmail.com</a>></span>:<br><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 .8ex;border-left:1px #ccc solid;border-right:1px #ccc=
solid;padding-left:1ex;padding-right:1ex">I hope for users that the =C2=AB=
assignment simplified to=C2=BB as you present it takes care of self-assignm=
ent (a =3D a; for some a), otherwise, with the algorithm presented here, th=
ey're in for a surprise :)<br></blockquote></div><div class=3D"gmail_ex=
tra"><br><div class=3D"gmail_quote"><div><div class=3D"h5">2015-06-19 12:26=
GMT-04:00 Farid Mehrabi <span dir=3D"ltr"><<a href=3D"mailto:farid.mehr=
abi@gmail.com" target=3D"_blank">farid.mehrabi@gmail.com</a>></span>:<br=
></div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div><div class=3D"h5"><div dir=
=3D"rtl"><div class=3D"gmail_default" style=3D"font-family:arial narrow,san=
s-serif;font-size:large"><br></div><div class=3D"gmail_extra"><div dir=3D"l=
tr"><br><div class=3D"gmail_quote"><div><div>2015-06-16 21:55 GMT+04:30 Ton=
y V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D=
"_blank">tvaneerd@gmail.com</a>></span>:<br><blockquote class=3D"gmail_q=
uote" style=3D"margin:0 .8ex;border-left:1px #ccc solid;border-right:1px #c=
cc solid;padding-left:1ex;padding-right:1ex"><br><div class=3D"gmail_extra"=
><div><div><br><div class=3D"gmail_quote">On Mon, Jun 15, 2015 at 4:12 PM, =
Farid Mehrabi <span dir=3D"ltr"><<a href=3D"mailto:farid.mehrabi@gmail.c=
om" target=3D"_blank">farid.mehrabi@gmail.com</a>></span> wrote:<br><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"rtl"><div style=3D"font-family:arial=
narrow,sans-serif;font-size:large"><br></div><div class=3D"gmail_extra"><s=
pan><br><div class=3D"gmail_quote"><div dir=3D"ltr">2015-06-07 22:28 GMT+04=
:30 Vicente J. Botet Escriba <span dir=3D"ltr"><<a href=3D"mailto:vicent=
e.botet@wanadoo.fr" target=3D"_blank">vicente.botet@wanadoo.fr</a>></spa=
n>:<div style=3D"font-family:'arial narrow',sans-serif;font-size:la=
rge;display:inline">=E2=80=8B=E2=80=8B</div></div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div><span>
<blockquote type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The proposal
did not make clear to me why default constructed empty state
is such a big issue in the first place and the current
alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height:normal">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some arbitrary
decision.</span></li>
<li><span style=3D"line-height:normal">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember
"Oh, I have to use this std::monostate workaround if m=
y
type is not default constructible!". <i>Hacks</i>
(another spelling for 'workaround') are <i>bad</i>.=
</span></li>
<li><span style=3D"line-height:normal">It does not play well
with changes. Imagine if the user-defined type that was
previously default constructible has its default
constructor removed. Now the users needs to add
std::monostate all over the place and fix up all the
indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not &quo=
t;either A,
B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues
that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote></span>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 and
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 and
cannot=C2=A0 be empty (we need to state how it is default constructed).=
<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative is
default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
<br>
You are advocating for option B. I believe that option B would be
represented better by<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<variant<Ts...>><br>
<br>
with a possible specialization=C2=A0 implementation<br>
<br>
or by a variadic optional version<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<Ts...><br>
<br>
All these concrete classes share a lot in common and I would expect
that the library implementor would make use of an implementation
class that covers the common parts.<span><font color=3D"#888888"><br></=
font></span></div></blockquote></div><div><br></div></span><div style=3D"te=
xt-align:left"><div style=3D"font-family:'arial narrow',sans-serif;=
font-size:large" dir=3D"ltr">=E2=80=8BA lot of effort has been put together=
to make option C possible and I do appreciate that, but why should we set =
option B aside while it is much easier to implement and more generic?</div>=
<div style=3D"font-family:'arial narrow',sans-serif;font-size:large=
" dir=3D"ltr">recalling that a variant assignment generally consists of 3 s=
teps:</div><div style=3D"font-family:'arial narrow',sans-serif;font=
-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial nar=
row',sans-serif;font-size:large" dir=3D"ltr">1. back up destination.</d=
iv><div style=3D"font-family:'arial narrow',sans-serif;font-size:la=
rge" dir=3D"ltr">2. copy source.</div><div style=3D"font-family:'arial =
narrow',sans-serif;font-size:large" dir=3D"ltr">3. restore destination =
if 2 fails.</div><div style=3D"font-family:'arial narrow',sans-seri=
f;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'ari=
al narrow',sans-serif;font-size:large" dir=3D"ltr">consider Option C (d=
irect porting of boost::variant into std):</div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr">Q: what happe=
ns if during an assignment operation, copy from source throws and the resto=
ration move in the destination throws too?=E2=80=8B</div><div style=3D"font=
-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">=C2=
=A0A: either a an uncaught exception or undefined behavior in a blank-less =
variant.</div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">Option B is not only easier,but also less dange=
rous: if copy fails and restoration fails too, reset to blank(null,empy ...=
).</div><div style=3D"font-family:'arial narrow',sans-serif;font-si=
ze:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial narrow=
',sans-serif;font-size:large" dir=3D"ltr">A worse scenario is when the =
backup move throws during the assignment; =C2=A0with option C it means the =
sky collapsing, whilst with option B the variant can reset to blank, a subs=
equent test of blankness can be used to check whether or not the assignment=
has succeeded.</div><div style=3D"font-family:'arial narrow',sans-=
serif;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'=
;arial narrow',sans-serif;font-size:large" dir=3D"ltr">By the way what =
are the benefits of the never empty promise of option C? What might go wron=
g if the variant is in blank state? visitors might eventually ignore the nu=
ll state or be forced to do something.<br></div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr"><br></div><di=
v style=3D"font-family:'arial narrow',sans-serif;font-size:large" d=
ir=3D"ltr">And you have actually pointed out one of my concerns about overh=
ead: the 'optional<variant<...>>'. With option B option=
al variant is just a thin API wrapper with no overhead on the variant, but =
with option C it is just paying twice the essential price.</div><div style=
=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=3D"l=
tr"><br></div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">regards,</div><div style=3D"font-family:'ar=
ial narrow',sans-serif;font-size:large" dir=3D"ltr">FM.</div><br></div>=
</div></div></blockquote><div><br></div></div></div></div>Move operations s=
houldn't throw.=C2=A0 So we shouldn't add an empty state to ALL var=
iants just for the rare case of throwing move.<br></div><div class=3D"gmail=
_extra">And more rare than the types with throwing moves, is those types ac=
tually throwing on move.=C2=A0 ie even if a type has a throwing move, it wi=
ll probably never throw (typically it means you can't even allocated a =
few bytes - at this point you are probably screwed anyhow).<br></div></bloc=
kquote><div><br></div></div></div><div><div class=3D"gmail_default" style=
=3D"font-family:'arial narrow',sans-serif;font-size:large">=E2=80=
=8Bnever means never not almost never. and we can`t be sure on what circums=
tances the move ctor may throw, and it is not just about the ctor; backup/r=
estoration involve destruction of the source/temporary, either of which may=
throw.</div></div><span><div>=C2=A0</div><blockquote class=3D"gmail_quote"=
style=3D"margin:0 .8ex;border-left:1px #ccc solid;border-right:1px #ccc so=
lid;padding-left:1ex;padding-right:1ex"><div class=3D"gmail_extra"><br></di=
v><div class=3D"gmail_extra">So we have a very rare state of a should-be-ra=
re type.=C2=A0 Let's not litter our code with if( !v.empty() ).... for =
that rare case.=C2=A0 And if you do get that rare case, you probably handle=
d it via throw/catch, so your variant-reading code doesn't happen, so a=
gain, you don't need to check for empty.<br></div></blockquote><div><br=
></div></span><div><div class=3D"gmail_default" style=3D"font-family:'a=
rial narrow',sans-serif;font-size:large;display:inline">=E2=80=8Bif one=
is sure about the nothrow promise, then [s]he does not need to check for b=
lankness; don`t pay for what u don`t use.</div></div><div><div class=3D"gma=
il_default" style=3D"font-family:'arial narrow',sans-serif;font-siz=
e:large;display:inline">But as library programmers we must care even 4 very=
rare cases in our design.</div></div><span><div><div class=3D"gmail_defaul=
t" style=3D"font-family:'arial narrow',sans-serif;font-size:large;d=
isplay:inline"><br></div></div><blockquote class=3D"gmail_quote" style=3D"m=
argin:0 .8ex;border-left:1px #ccc solid;border-right:1px #ccc solid;padding=
-left:1ex;padding-right:1ex"><div class=3D"gmail_extra"><br></div><div clas=
s=3D"gmail_extra">So I don't think the empty state is worth it for thro=
wing moves.<br></div></blockquote><div><br></div></span><div><div class=3D"=
gmail_default" style=3D"font-family:'arial narrow',sans-serif;font-=
size:large;display:inline">=E2=80=8Bactually the assignment can be simplifi=
ed to:</div></div><div><div class=3D"gmail_default" style=3D"font-family:&#=
39;arial narrow',sans-serif;font-size:large;display:inline"><br></div><=
/div><div><div class=3D"gmail_default" style=3D"font-family:'arial narr=
ow',sans-serif;font-size:large;display:inline">1. destruct original.</d=
iv></div><div><div class=3D"gmail_default" style=3D"font-family:'arial =
narrow',sans-serif;font-size:large;display:inline">2. copy source</div>=
</div><div><div class=3D"gmail_default" style=3D"font-family:'arial nar=
row',sans-serif;font-size:large;display:inline">3. set to blank in case=
of any sort of failure.</div></div><div><div class=3D"gmail_default" style=
=3D"font-family:'arial narrow',sans-serif;font-size:large;display:i=
nline"><br></div></div><div><div class=3D"gmail_default" style=3D"font-fami=
ly:'arial narrow',sans-serif;font-size:large">=E2=80=8Bmuch easier =
than the never-empty promise.</div><div class=3D"gmail_default" style=3D"fo=
nt-family:'arial narrow',sans-serif;font-size:large"><br></div><div=
class=3D"gmail_default" style=3D"font-family:'arial narrow',sans-s=
erif;font-size:large">On second thought =E2=80=8BI even considered option A=
and it looked even simpler to implement and more basic, now I can see why =
boost designers called for proposals on policy-based variant design.</div><=
div class=3D"gmail_default" style=3D"font-family:'arial narrow',san=
s-serif;font-size:large"><br></div><div class=3D"gmail_default" style=3D"fo=
nt-family:'arial narrow',sans-serif;font-size:large">regards,</div>=
<div class=3D"gmail_default" style=3D"font-family:'arial narrow',sa=
ns-serif;font-size:large">FM.</div><br></div><div><div class=3D"gmail_defau=
lt" style=3D"font-family:'arial narrow',sans-serif;font-size:large;=
display:inline">=E2=80=8B</div>=C2=A0</div></div></div><span>-- <br><div><d=
iv dir=3D"rtl"><div><div dir=3D"ltr">how am I supposed to end the twisted r=
oad of=C2=A0 your hair in such a dark night??<br>unless the candle of your =
face does shed some light upon my way!!!<br></div></div></div></div>
</span></div></div></div></div><div><div>
<p></p>
-- <br><span class=3D"">
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</span></div></div></blockquote></div><br></div><div class=3D"HOEnZb"><div =
class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></div><br clear=3D"all"><div><br></div>-- <br><div class=3D"gma=
il_signature"><div dir=3D"rtl"><div><div dir=3D"ltr">how am I supposed to e=
nd the twisted road of=C2=A0 your hair in such a dark night??<br>unless the=
candle of your face does shed some light upon my way!!!<br></div></div></d=
iv></div>
</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113569e260589f0518e1f05a--
.
Author: Michael Park <mcypark@gmail.com>
Date: Mon, 21 Sep 2015 01:56:11 -0700 (PDT)
Raw View
------=_Part_533_471496141.1442825771243
Content-Type: multipart/alternative;
boundary="----=_Part_534_2065626181.1442825771245"
------=_Part_534_2065626181.1442825771245
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hello, I've been working on an alternative variant proposal. It's still=20
very rough at this point but I've captured the big questions I wanted to=20
answer, and would appreciate feedback from the community.
The following are some of the principles the design is based on:
(1) *union* is not a good starting point for a discriminated union. I=20
believe better starting points are:
From C++: *enum* as a special case where each member is a unit type,=
=20
and
*class inheritance* where an abstract base class is a discriminated=
=20
union of its derived classes.
From other languages: Sum types from Haskell and ML or enum from=20
Rust.
(2) The *order* of the types specified in *variant<Ts...>* should not=20
change its behavior.
(3) The API should be minimal, useful, and consistent.
The following are few design decisions that fall out from the above=20
principles:
* The visitation interface is a *type_switch* expression which looks=20
similar to a regular *switch* statement,
as well as *match* expressions from functional languages. (1)
* Default construction should not construct the first type. (2)
* The members should be discriminated by type rather than the index. (2),=
=20
(3)
(i.e. *variant<int, string, int>* behaves equivalently to *variant<int=
,=20
string>*)
* There is no special treatment for the null state. (3)
This is the work-in-progress in a Google Doc: Variant=20
<https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJH=
Dhp48/edit?usp=3Dsharing> and=20
it is open for comments.
I'm in Seattle attending CppCon this week. Please reach out if you're also=
=20
here and would like to provide feedback and/or have further design=20
discussions!
Thanks,
MPark.
On Friday, June 19, 2015 at 10:06:04 AM UTC-7, Farid Mehrabi wrote:
>
> is that so hard to guard against self assignment? even a novice like me=
=20
> can do it. I am leaving the details for the sake of main point. but than=
x=20
> for reminder.
>
> regards,
> FM.
>
> 2015-06-19 21:02 GMT+04:30 Patrice Roy <patr...@gmail.com <javascript:>>:
>
>> I hope for users that the =C2=ABassignment simplified to=C2=BB as you pr=
esent it=20
>> takes care of self-assignment (a =3D a; for some a), otherwise, with the=
=20
>> algorithm presented here, they're in for a surprise :)
>>
>
> 2015-06-19 12:26 GMT-04:00 Farid Mehrabi <farid....@gmail.com=20
> <javascript:>>:
>
>>
>>
>> 2015-06-16 21:55 GMT+04:30 Tony V E <tvan...@gmail.com <javascript:>>:
>>
>>>
>>>
>>> On Mon, Jun 15, 2015 at 4:12 PM, Farid Mehrabi <farid....@gmail.com=20
>>> <javascript:>> wrote:
>>>
>>>>
>>>>
>>>> 2015-06-07 22:28 GMT+04:30 Vicente J. Botet Escriba <
>>>> vicent...@wanadoo.fr <javascript:>>:
>>>> =E2=80=8B=E2=80=8B
>>>>
>>>>> Le 05/06/15 10:17, Markus Grech a =C3=A9crit :
>>>>>
>>>>> Hi everyone,=20
>>>>>
>>>>> I would like to voice my concerns about default construction of=20
>>>>> std::variant and std::monostate. The proposal did not make clear to m=
e why=20
>>>>> default constructed empty state is such a big issue in the first plac=
e and=20
>>>>> the current alternative suffers from significant drawbacks:
>>>>>
>>>>> - To me it is very surprising that variant tries to=20
>>>>> default-construct the first type. Why not the 2nd, 5th type? I'd r=
ather=20
>>>>> have variant have no default constructor than some arbitrary decis=
ion.=20
>>>>> - It is yet another special case that users need to be taught=20
>>>>> about and frankly, it's not pretty either. Users have to remember =
"Oh, I=20
>>>>> have to use this std::monostate workaround if my type is not defau=
lt=20
>>>>> constructible!". *Hacks* (another spelling for 'workaround') are=
=20
>>>>> *bad*.=20
>>>>> - It does not play well with changes. Imagine if the user-defined=
=20
>>>>> type that was previously default constructible has its default con=
structor=20
>>>>> removed. Now the users needs to add std::monostate all over the pl=
ace and=20
>>>>> fix up all the indices for index-based access.=20
>>>>>
>>>>> There needs to be a better solution. I do think that having an empty=
=20
>>>>> state semantically fails at the idea of variant in the first place ("=
either=20
>>>>> A or B", not "either A, B or empty"), but it is not the end of the wo=
rld.=20
>>>>> The current std::monostate design however has significant issues that=
IMHO=20
>>>>> deserve another look.
>>>>>
>>>>>
>>>>> We have two orthogonal interface decissions that could interact
>>>>> * default construction
>>>>> * possible empty
>>>>>
>>>>> A - We can have a variant class that is not default constructible an=
d=20
>>>>> cannot be empty.=20
>>>>> B - We can have a variant class that is default constructible and ca=
n=20
>>>>> be empty, so the default constructor is naturally empty.
>>>>> C - We can have a variant class that is default constructible and=20
>>>>> cannot be empty (we need to state how it is default constructed).
>>>>>
>>>>> The not default constructible and empty seems not interesting enough.
>>>>>
>>>>> The current proposal correspond to C, when its first alternative is=
=20
>>>>> default constructible and A otherwise, and I think this is the better=
we=20
>>>>> can have.
>>>>> The standard could also have a class behaving always as A. I wouldn't=
=20
>>>>> be against.
>>>>>
>>>>> You are advocating for option B. I believe that option B would be=20
>>>>> represented better by
>>>>>
>>>>> optional<variant<Ts...>>
>>>>>
>>>>> with a possible specialization implementation
>>>>>
>>>>> or by a variadic optional version
>>>>>
>>>>> optional<Ts...>
>>>>>
>>>>> All these concrete classes share a lot in common and I would expect=
=20
>>>>> that the library implementor would make use of an implementation clas=
s that=20
>>>>> covers the common parts.
>>>>>
>>>>
>>>> =E2=80=8BA lot of effort has been put together to make option C possib=
le and I=20
>>>> do appreciate that, but why should we set option B aside while it is m=
uch=20
>>>> easier to implement and more generic?
>>>> recalling that a variant assignment generally consists of 3 steps:
>>>>
>>>> 1. back up destination.
>>>> 2. copy source.
>>>> 3. restore destination if 2 fails.
>>>>
>>>> consider Option C (direct porting of boost::variant into std):
>>>> Q: what happens if during an assignment operation, copy from source=20
>>>> throws and the restoration move in the destination throws too?=E2=80=
=8B
>>>> A: either a an uncaught exception or undefined behavior in a=20
>>>> blank-less variant.
>>>> Option B is not only easier,but also less dangerous: if copy fails and=
=20
>>>> restoration fails too, reset to blank(null,empy ...).
>>>>
>>>> A worse scenario is when the backup move throws during the assignment;=
=20
>>>> with option C it means the sky collapsing, whilst with option B the=
=20
>>>> variant can reset to blank, a subsequent test of blankness can be used=
to=20
>>>> check whether or not the assignment has succeeded.
>>>>
>>>> By the way what are the benefits of the never empty promise of option=
=20
>>>> C? What might go wrong if the variant is in blank state? visitors migh=
t=20
>>>> eventually ignore the null state or be forced to do something.
>>>>
>>>> And you have actually pointed out one of my concerns about overhead:=
=20
>>>> the 'optional<variant<...>>'. With option B optional variant is just a=
thin=20
>>>> API wrapper with no overhead on the variant, but with option C it is j=
ust=20
>>>> paying twice the essential price.
>>>>
>>>> regards,
>>>> FM.
>>>>
>>>>
>>> Move operations shouldn't throw. So we shouldn't add an empty state to=
=20
>>> ALL variants just for the rare case of throwing move.
>>> And more rare than the types with throwing moves, is those types=20
>>> actually throwing on move. ie even if a type has a throwing move, it w=
ill=20
>>> probably never throw (typically it means you can't even allocated a few=
=20
>>> bytes - at this point you are probably screwed anyhow).
>>>
>>
>> =E2=80=8Bnever means never not almost never. and we can`t be sure on wha=
t=20
>> circumstances the move ctor may throw, and it is not just about the ctor=
;=20
>> backup/restoration involve destruction of the source/temporary, either o=
f=20
>> which may throw.
>> =20
>>
>>>
>>> So we have a very rare state of a should-be-rare type. Let's not litte=
r=20
>>> our code with if( !v.empty() ).... for that rare case. And if you do g=
et=20
>>> that rare case, you probably handled it via throw/catch, so your=20
>>> variant-reading code doesn't happen, so again, you don't need to check =
for=20
>>> empty.
>>>
>>
>> =E2=80=8Bif one is sure about the nothrow promise, then [s]he does not n=
eed to=20
>> check for blankness; don`t pay for what u don`t use.
>> But as library programmers we must care even 4 very rare cases in our=20
>> design.
>>
>>
>>> So I don't think the empty state is worth it for throwing moves.
>>>
>>
>> =E2=80=8Bactually the assignment can be simplified to:
>>
>> 1. destruct original.
>> 2. copy source
>> 3. set to blank in case of any sort of failure.
>>
>> =E2=80=8Bmuch easier than the never-empty promise.
>>
>> On second thought =E2=80=8BI even considered option A and it looked even=
simpler=20
>> to implement and more basic, now I can see why boost designers called fo=
r=20
>> proposals on policy-based variant design.
>>
>> regards,
>> FM.
>>
>> =E2=80=8B
>> =20
>> --=20
>> how am I supposed to end the twisted road of your hair in such a dark=
=20
>> night??
>> unless the candle of your face does shed some light upon my way!!!
>>
>> --=20
>>
>> ---=20
>> You received this message because you are subscribed to the Google Group=
s=20
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n=20
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at=20
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
> --=20
>
> ---=20
> You received this message because you are subscribed to the Google Groups=
=20
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
=20
> email to std-proposal...@isocpp.org <javascript:>.
> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
> Visit this group at=20
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
>
> --=20
> how am I supposed to end the twisted road of your hair in such a dark=20
> night??
> unless the candle of your face does shed some light upon my way!!!
>
--=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_534_2065626181.1442825771245
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hello, I've been working on an alternative variant pro=
posal. It's still very rough at this point but I've captured the bi=
g questions I wanted to answer, and would appreciate feedback from the comm=
unity.<div><br></div><div>The following are some of the principles the desi=
gn is based on:</div><div>=C2=A0 (1)=C2=A0<font face=3D"courier new, monosp=
ace"><b>union</b></font>=C2=A0is not a good starting point for a discrimina=
ted union. I believe better starting points are:</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0From C++:=C2=A0<font face=3D"courier new, monospace"><b>enum</=
b></font>=C2=A0as a special case where each member is a unit type, and</div=
><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0<b>class inheritance</b>=C2=A0where an abs=
tract base class is a discriminated union of its derived classes.</div><div=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0From other languages: Sum types from Haskell an=
d ML or=C2=A0<font face=3D"courier new, monospace" style=3D"font-weight: bo=
ld;">enum</font><font face=3D"arial, sans-serif"><b>=C2=A0</b>from Rust.</f=
ont></div><div>=C2=A0 (2) The=C2=A0<b>order</b>=C2=A0of the types specified=
in=C2=A0<font face=3D"courier new, monospace"><b>variant<Ts...></b><=
/font>=C2=A0should not change its behavior.</div><div>=C2=A0 (3) The API sh=
ould be minimal, useful, and consistent.</div><div><br></div><div>The follo=
wing are few design decisions that fall out from the above principles:</div=
><div>=C2=A0 * The visitation interface is a=C2=A0<b>type_switch</b>=C2=A0e=
xpression which looks similar to a regular=C2=A0<b>switch</b>=C2=A0statemen=
t,</div><div>=C2=A0 =C2=A0 as well as=C2=A0<b>match</b>=C2=A0expressions fr=
om functional languages. (1)</div><div>=C2=A0 * Default construction should=
not construct the first type. (2)</div><div>=C2=A0 * The members should be=
discriminated by type rather than the index. (2), (3)</div><div>=C2=A0 =C2=
=A0 =C2=A0(i.e.=C2=A0<font face=3D"courier new, monospace"><b>variant<in=
t, string, int></b></font>=C2=A0behaves equivalently to=C2=A0<b style=3D=
"font-family: 'courier new', monospace;">variant<int, string>=
</b><font face=3D"arial, sans-serif">)</font></div><div>=C2=A0 * There is n=
o special treatment for the null state. (3)</div><div><br></div><div>This i=
s the work-in-progress in a Google Doc:=C2=A0<a href=3D"https://docs.google=
..com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Dsha=
ring">Variant</a>=C2=A0and it is open for comments.</div><div><br></div><di=
v>I'm in Seattle attending CppCon this week. Please reach out if you=
9;re also here and would like to provide feedback and/or have further desig=
n discussions!</div><div><div><br></div><div>Thanks,</div><div><br></div><d=
iv>MPark.</div></div><br>On Friday, June 19, 2015 at 10:06:04 AM UTC-7, Far=
id Mehrabi wrote:<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"r=
tl"><div style=3D"font-family:arial narrow,sans-serif;font-size:large" dir=
=3D"ltr">is that so hard to guard against self assignment? even a novice li=
ke me can do it. I am leaving the details for the sake of =C2=A0main point.=
but thanx for reminder.</div><div style=3D"font-family:arial narrow,sans-s=
erif;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:arial=
narrow,sans-serif;font-size:large" dir=3D"ltr">regards,</div><div style=3D=
"font-family:arial narrow,sans-serif;font-size:large" dir=3D"ltr">FM.</div>=
</div><div><div dir=3D"ltr"><br><div class=3D"gmail_quote">2015-06-19 21:02=
GMT+04:30 Patrice Roy <span dir=3D"ltr"><<a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"izURoOEExpsJ" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hre=
f=3D'javascript:';return true;">patr...@gmail.com</a>></span>:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0 .8ex;border-left:1px =
#ccc solid;border-right:1px #ccc solid;padding-left:1ex;padding-right:1ex">=
I hope for users that the =C2=ABassignment simplified to=C2=BB as you prese=
nt it takes care of self-assignment (a =3D a; for some a), otherwise, with =
the algorithm presented here, they're in for a surprise :)<br></blockqu=
ote></div><div><br><div class=3D"gmail_quote"><div><div>2015-06-19 12:26 GM=
T-04:00 Farid Mehrabi <span dir=3D"ltr"><<a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"izURoOEExpsJ" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hre=
f=3D'javascript:';return true;">farid....@gmail.com</a>></span>:=
<br></div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div><div><div dir=3D"rtl"><=
div style=3D"font-family:arial narrow,sans-serif;font-size:large"><br></div=
><div><div dir=3D"ltr"><br><div class=3D"gmail_quote"><div><div>2015-06-16 =
21:55 GMT+04:30 Tony V E <span dir=3D"ltr"><<a href=3D"javascript:" targ=
et=3D"_blank" gdf-obfuscated-mailto=3D"izURoOEExpsJ" rel=3D"nofollow" onmou=
sedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.h=
ref=3D'javascript:';return true;">tvan...@gmail.com</a>></span>:=
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 .8ex;border-left:1p=
x #ccc solid;border-right:1px #ccc solid;padding-left:1ex;padding-right:1ex=
"><br><div><div><div><br><div class=3D"gmail_quote">On Mon, Jun 15, 2015 at=
4:12 PM, Farid Mehrabi <span dir=3D"ltr"><<a href=3D"javascript:" targe=
t=3D"_blank" gdf-obfuscated-mailto=3D"izURoOEExpsJ" rel=3D"nofollow" onmous=
edown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hr=
ef=3D'javascript:';return true;">farid....@gmail.com</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"rtl"><div style=3D"fo=
nt-family:arial narrow,sans-serif;font-size:large"><br></div><div><span><br=
><div class=3D"gmail_quote"><div dir=3D"ltr">2015-06-07 22:28 GMT+04:30 Vic=
ente J. Botet Escriba <span dir=3D"ltr"><<a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"izURoOEExpsJ" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hre=
f=3D'javascript:';return true;">vicent...@wanadoo.fr</a>></span>=
:<div style=3D"font-family:'arial narrow',sans-serif;font-size:larg=
e;display:inline">=E2=80=8B=E2=80=8B</div></div><blockquote class=3D"gmail_=
quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1=
ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 10:17, Markus Grech a
=C3=A9crit=C2=A0:<br>
</div><span>
<blockquote type=3D"cite">
<div dir=3D"ltr">Hi everyone,
<div><br>
</div>
<div>I would like to voice my concerns about default
construction of std::variant and std::monostate. The proposal
did not make clear to me why default constructed empty state
is such a big issue in the first place and the current
alternative suffers from significant drawbacks:</div>
<div>
<ul>
<li><span style=3D"line-height:normal">To me it is very
surprising that variant tries to default-construct the
first type. Why not the 2nd, 5th type? I'd rather have
variant have no default constructor than some arbitrary
decision.</span></li>
<li><span style=3D"line-height:normal">It is yet another
special case that users need to be taught about and
frankly, it's not pretty either. Users have to remember
"Oh, I have to use this std::monostate workaround if m=
y
type is not default constructible!". <i>Hacks</i>
(another spelling for 'workaround') are <i>bad</i>.=
</span></li>
<li><span style=3D"line-height:normal">It does not play well
with changes. Imagine if the user-defined type that was
previously default constructible has its default
constructor removed. Now the users needs to add
std::monostate all over the place and fix up all the
indices for index-based access.</span></li>
</ul>
<div>There needs to be a better solution. I do think that
having an empty state semantically fails at the idea of
variant in the first place ("either A or B", not &quo=
t;either A,
B or empty"), but it is not the end of the world. The
current std::monostate design however has significant issues
that IMHO deserve another look.</div>
</div>
<div><br>
</div>
<br>
</div>
</blockquote></span>
We have two orthogonal interface decissions that could interact<br>
=C2=A0=C2=A0=C2=A0 * default construction<br>
=C2=A0=C2=A0=C2=A0 * possible empty<br>
<br>
A - We can have a variant class that is not default constructible=C2=A0
and cannot be empty. <br>
B - We can have a variant class that is default constructible=C2=A0 and
can be empty, so the default constructor is naturally empty.<br>
C - We can have a variant class that is default constructible=C2=A0 and
cannot=C2=A0 be empty (we need to state how it is default constructed).=
<br>
<br>
The not default constructible and empty seems not interesting
enough.<br>
<br>
The current proposal correspond to C, when its first alternative is
default constructible and A otherwise, and I think this is the
better we can have.<br>
The standard could also have a class behaving always as A. I
wouldn't be against.<br>
<br>
You are advocating for option B. I believe that option B would be
represented better by<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<variant<Ts...>><br>
<br>
with a possible specialization=C2=A0 implementation<br>
<br>
or by a variadic optional version<br>
<br>
=C2=A0=C2=A0=C2=A0 optional<Ts...><br>
<br>
All these concrete classes share a lot in common and I would expect
that the library implementor would make use of an implementation
class that covers the common parts.<span><font color=3D"#888888"><br></=
font></span></div></blockquote></div><div><br></div></span><div style=3D"te=
xt-align:left"><div style=3D"font-family:'arial narrow',sans-serif;=
font-size:large" dir=3D"ltr">=E2=80=8BA lot of effort has been put together=
to make option C possible and I do appreciate that, but why should we set =
option B aside while it is much easier to implement and more generic?</div>=
<div style=3D"font-family:'arial narrow',sans-serif;font-size:large=
" dir=3D"ltr">recalling that a variant assignment generally consists of 3 s=
teps:</div><div style=3D"font-family:'arial narrow',sans-serif;font=
-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial nar=
row',sans-serif;font-size:large" dir=3D"ltr">1. back up destination.</d=
iv><div style=3D"font-family:'arial narrow',sans-serif;font-size:la=
rge" dir=3D"ltr">2. copy source.</div><div style=3D"font-family:'arial =
narrow',sans-serif;font-size:large" dir=3D"ltr">3. restore destination =
if 2 fails.</div><div style=3D"font-family:'arial narrow',sans-seri=
f;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'ari=
al narrow',sans-serif;font-size:large" dir=3D"ltr">consider Option C (d=
irect porting of boost::variant into std):</div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr">Q: what happe=
ns if during an assignment operation, copy from source throws and the resto=
ration move in the destination throws too?=E2=80=8B</div><div style=3D"font=
-family:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">=C2=
=A0A: either a an uncaught exception or undefined behavior in a blank-less =
variant.</div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">Option B is not only easier,but also less dange=
rous: if copy fails and restoration fails too, reset to blank(null,empy ...=
).</div><div style=3D"font-family:'arial narrow',sans-serif;font-si=
ze:large" dir=3D"ltr"><br></div><div style=3D"font-family:'arial narrow=
',sans-serif;font-size:large" dir=3D"ltr">A worse scenario is when the =
backup move throws during the assignment; =C2=A0with option C it means the =
sky collapsing, whilst with option B the variant can reset to blank, a subs=
equent test of blankness can be used to check whether or not the assignment=
has succeeded.</div><div style=3D"font-family:'arial narrow',sans-=
serif;font-size:large" dir=3D"ltr"><br></div><div style=3D"font-family:'=
;arial narrow',sans-serif;font-size:large" dir=3D"ltr">By the way what =
are the benefits of the never empty promise of option C? What might go wron=
g if the variant is in blank state? visitors might eventually ignore the nu=
ll state or be forced to do something.<br></div><div style=3D"font-family:&=
#39;arial narrow',sans-serif;font-size:large" dir=3D"ltr"><br></div><di=
v style=3D"font-family:'arial narrow',sans-serif;font-size:large" d=
ir=3D"ltr">And you have actually pointed out one of my concerns about overh=
ead: the 'optional<variant<...>>'. With option B option=
al variant is just a thin API wrapper with no overhead on the variant, but =
with option C it is just paying twice the essential price.</div><div style=
=3D"font-family:'arial narrow',sans-serif;font-size:large" dir=3D"l=
tr"><br></div><div style=3D"font-family:'arial narrow',sans-serif;f=
ont-size:large" dir=3D"ltr">regards,</div><div style=3D"font-family:'ar=
ial narrow',sans-serif;font-size:large" dir=3D"ltr">FM.</div><br></div>=
</div></div></blockquote><div><br></div></div></div></div>Move operations s=
houldn't throw.=C2=A0 So we shouldn't add an empty state to ALL var=
iants just for the rare case of throwing move.<br></div><div>And more rare =
than the types with throwing moves, is those types actually throwing on mov=
e.=C2=A0 ie even if a type has a throwing move, it will probably never thro=
w (typically it means you can't even allocated a few bytes - at this po=
int you are probably screwed anyhow).<br></div></blockquote><div><br></div>=
</div></div><div><div style=3D"font-family:'arial narrow',sans-seri=
f;font-size:large">=E2=80=8Bnever means never not almost never. and we can`=
t be sure on what circumstances the move ctor may throw, and it is not just=
about the ctor; backup/restoration involve destruction of the source/tempo=
rary, either of which may throw.</div></div><span><div>=C2=A0</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 .8ex;border-left:1px #ccc solid=
;border-right:1px #ccc solid;padding-left:1ex;padding-right:1ex"><div><br><=
/div><div>So we have a very rare state of a should-be-rare type.=C2=A0 Let&=
#39;s not litter our code with if( !v.empty() ).... for that rare case.=C2=
=A0 And if you do get that rare case, you probably handled it via throw/cat=
ch, so your variant-reading code doesn't happen, so again, you don'=
t need to check for empty.<br></div></blockquote><div><br></div></span><div=
><div style=3D"font-family:'arial narrow',sans-serif;font-size:larg=
e;display:inline">=E2=80=8Bif one is sure about the nothrow promise, then [=
s]he does not need to check for blankness; don`t pay for what u don`t use.<=
/div></div><div><div style=3D"font-family:'arial narrow',sans-serif=
;font-size:large;display:inline">But as library programmers we must care ev=
en 4 very rare cases in our design.</div></div><span><div><div style=3D"fon=
t-family:'arial narrow',sans-serif;font-size:large;display:inline">=
<br></div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 .8ex;bo=
rder-left:1px #ccc solid;border-right:1px #ccc solid;padding-left:1ex;paddi=
ng-right:1ex"><div><br></div><div>So I don't think the empty state is w=
orth it for throwing moves.<br></div></blockquote><div><br></div></span><di=
v><div style=3D"font-family:'arial narrow',sans-serif;font-size:lar=
ge;display:inline">=E2=80=8Bactually the assignment can be simplified to:</=
div></div><div><div style=3D"font-family:'arial narrow',sans-serif;=
font-size:large;display:inline"><br></div></div><div><div style=3D"font-fam=
ily:'arial narrow',sans-serif;font-size:large;display:inline">1. de=
struct original.</div></div><div><div style=3D"font-family:'arial narro=
w',sans-serif;font-size:large;display:inline">2. copy source</div></div=
><div><div style=3D"font-family:'arial narrow',sans-serif;font-size=
:large;display:inline">3. set to blank in case of any sort of failure.</div=
></div><div><div style=3D"font-family:'arial narrow',sans-serif;fon=
t-size:large;display:inline"><br></div></div><div><div style=3D"font-family=
:'arial narrow',sans-serif;font-size:large">=E2=80=8Bmuch easier th=
an the never-empty promise.</div><div style=3D"font-family:'arial narro=
w',sans-serif;font-size:large"><br></div><div style=3D"font-family:'=
;arial narrow',sans-serif;font-size:large">On second thought =E2=80=8BI=
even considered option A and it looked even simpler to implement and more =
basic, now I can see why boost designers called for proposals on policy-bas=
ed variant design.</div><div style=3D"font-family:'arial narrow',sa=
ns-serif;font-size:large"><br></div><div style=3D"font-family:'arial na=
rrow',sans-serif;font-size:large">regards,</div><div style=3D"font-fami=
ly:'arial narrow',sans-serif;font-size:large">FM.</div><br></div><d=
iv><div style=3D"font-family:'arial narrow',sans-serif;font-size:la=
rge;display:inline">=E2=80=8B</div>=C2=A0</div></div></div><span>-- <br><di=
v><div dir=3D"rtl"><div><div dir=3D"ltr">how am I supposed to end the twist=
ed road of=C2=A0 your hair in such a dark night??<br>unless the candle of y=
our face does shed some light upon my way!!!<br></div></div></div></div>
</span></div></div></div></div><div><div>
<p></p>
-- <br><span>
<br>
--- <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"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
izURoOEExpsJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"izURoOEExpsJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">std-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';ret=
urn true;" onclick=3D"this.href=3D'http://groups.google.com/a/isocpp.or=
g/group/std-proposals/';return true;">http://groups.google.com/a/<wbr>i=
socpp.org/group/std-<wbr>proposals/</a>.<br>
</span></div></div></blockquote></div><br></div><div><div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
izURoOEExpsJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"izURoOEExpsJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">std-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';ret=
urn true;" onclick=3D"this.href=3D'http://groups.google.com/a/isocpp.or=
g/group/std-proposals/';return true;">http://groups.google.com/a/<wbr>i=
socpp.org/group/std-<wbr>proposals/</a>.<br>
</div></div></div><br clear=3D"all"><div><br></div>-- <br><div><div dir=3D"=
rtl"><div><div dir=3D"ltr">how am I supposed to end the twisted road of=C2=
=A0 your hair in such a dark night??<br>unless the candle of your face does=
shed some light upon my way!!!<br></div></div></div></div>
</div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_534_2065626181.1442825771245--
------=_Part_533_471496141.1442825771243--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 21 Sep 2015 17:55:26 +0800
Raw View
--Apple-Mail=_D6066D8F-5F91-4EE9-88A2-36C51B9F93F5
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9321, at 4:56 PM, Michael Park <mcypark@gmail.co=
m> wrote:
>=20
> Hello, I've been working on an alternative variant proposal. It's still v=
ery rough at this point but I've captured the big questions I wanted to ans=
wer, and would appreciate feedback from the community.
>=20
> The following are some of the principles the design is based on:
> (1) union is not a good starting point for a discriminated union. I bel=
ieve better starting points are:
union is the only methodology with a chance at constexpr compatibility.
> From C++: enum as a special case where each member is a unit type,=
and
> class inheritance where an abstract base class is a discriminated =
union of its derived classes.
> From other languages: Sum types from Haskell and ML or enum from R=
ust.
Wait, what do you mean by =E2=80=9Cstarting point=E2=80=9D? How is any C++ =
variant template still like a union, to the user?
> (2) The order of the types specified in variant<Ts...> should not chang=
e its behavior.
Agreed. The better evolutionary direction is to allow the implementation to=
sort the type-list, so any permutation of the same type-list names the sam=
e variant type.
It=E2=80=99s only a series of unfortunate events that led std::type_info (a=
nd its member less()) to be non-constexpr, preventing this normalization fr=
om being done already.
> (3) The API should be minimal, useful, and consistent.
>=20
> The following are few design decisions that fall out from the above princ=
iples:
> * The visitation interface is a type_switch expression which looks simi=
lar to a regular switch statement,
> as well as match expressions from functional languages. (1)
> * Default construction should not construct the first type. (2)
> * The members should be discriminated by type rather than the index. (2=
), (3)
> (i.e. variant<int, string, int> behaves equivalently to variant<int,=
string>)
> * There is no special treatment for the null state. (3)
What the heck does this mean? The question is whether a null state exists o=
r not. How can it exist but not be special?
I think, given the controversy, nullable and non-nullable versions should b=
e supported. For example, it=E2=80=99s nullable if void appears in the type=
list. Let nullable_variant (not actual proposed name) be an alias template =
to nonnull_variant<void, T ...>.
> This is the work-in-progress in a Google Doc: Variant <https://docs.googl=
e.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Dsh=
aring> and it is open for comments.
The #1 problem with N4542, IMHO, is that it aggregates and idealizes some e=
xisting implementations without actually prototyping the result.
I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper l=
aying out arguments and principles for their own sake, not a complete self-=
contained proposal going from ancient history up to standardese.
--=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/.
--Apple-Mail=_D6066D8F-5F91-4EE9-88A2-36C51B9F93F5
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9321, at 4:56 PM, Michael Park <<a href=3D"mailto:mcypark@gmail.c=
om" class=3D"">mcypark@gmail.com</a>> wrote:</div><br class=3D"Apple-int=
erchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">Hello, I've b=
een working on an alternative variant proposal. It's still very rough at th=
is point but I've captured the big questions I wanted to answer, and would =
appreciate feedback from the community.<div class=3D""><br class=3D""></div=
><div class=3D"">The following are some of the principles the design is bas=
ed on:</div><div class=3D""> (1) <font face=3D"courier new, mono=
space" class=3D""><b class=3D"">union</b></font> is not a good startin=
g point for a discriminated union. I believe better starting points are:</d=
iv></div></div></blockquote><div><br class=3D""></div><div><font face=3D"Co=
urier" class=3D"">union</font> is the only methodology with a chance at <fo=
nt face=3D"Courier" class=3D"">constexpr</font> compatibility.</div><br cla=
ss=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"lt=
r" class=3D""><div class=3D""> From C++: <fo=
nt face=3D"courier new, monospace" class=3D""><b class=3D"">enum</b></font>=
as a special case where each member is a unit type, and</div><div cla=
ss=3D""> <b class=3D"">class inheritance</b> =
;where an abstract base class is a discriminated union of its derived class=
es.</div><div class=3D""> From other languages: S=
um types from Haskell and ML or <font face=3D"courier new, monospace" =
style=3D"font-weight: bold;" class=3D"">enum</font><font face=3D"arial, san=
s-serif" class=3D""><b class=3D""> </b>from Rust.</font></div></div></=
div></blockquote><div><br class=3D""></div><div>Wait, what do you mean by =
=E2=80=9Cstarting point=E2=80=9D? How is any C++ variant template still lik=
e a union, to the user?</div><br class=3D""><blockquote type=3D"cite" class=
=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class=3D""> (2=
) The <b class=3D"">order</b> of the types specified in <fon=
t face=3D"courier new, monospace" class=3D""><b class=3D"">variant<Ts...=
></b></font> should not change its behavior.</div></div></div></blo=
ckquote><div><br class=3D""></div><div>Agreed. The better evolutionary dire=
ction is to allow the implementation to sort the type-list, so any permutat=
ion of the same type-list names the same variant type.</div><div><br class=
=3D""></div><div>It=E2=80=99s only a series of unfortunate events that led =
<font face=3D"Courier" class=3D"">std::type_info</font> (and its member <fo=
nt face=3D"Courier" class=3D"">less()</font>) to be non-constexpr, preventi=
ng this normalization from being done already.</div><br class=3D""><blockqu=
ote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><d=
iv class=3D""> (3) The API should be minimal, useful, and consistent.=
</div><div class=3D""><br class=3D""></div><div class=3D"">The following ar=
e few design decisions that fall out from the above principles:</div><div c=
lass=3D""> * The visitation interface is a <b class=3D"">type_sw=
itch</b> expression which looks similar to a regular <b class=3D"=
">switch</b> statement,</div><div class=3D""> as well as&=
nbsp;<b class=3D"">match</b> expressions from functional languages. (1=
)</div><div class=3D""> * Default construction should not construct t=
he first type. (2)</div><div class=3D""> * The members should be disc=
riminated by type rather than the index. (2), (3)</div><div class=3D"">&nbs=
p; (i.e. <font face=3D"courier new, monospace" class=3D""=
><b class=3D"">variant<int, string, int></b></font> behaves equi=
valently to <b style=3D"font-family: 'courier new', monospace;" class=
=3D"">variant<int, string></b><font face=3D"arial, sans-serif" class=
=3D"">)</font></div><div class=3D""> * There is no special treatment =
for the null state. (3)</div><div class=3D""></div></div></div></blockquote=
><div><br class=3D""></div><div>What the heck does this mean? The question =
is whether a null state exists or not. How can it exist but not be special?=
</div><div><br class=3D""></div><div>I think, given the controversy, nullab=
le and non-nullable versions should be supported. For example, it=E2=80=99s=
nullable if <font face=3D"Courier" class=3D"">void</font> appears in the t=
ypelist. Let <font face=3D"Courier" class=3D"">nullable_variant</font> =
;(not actual proposed name) be an alias template to <font face=3D"Courier" =
class=3D"">nonnull_variant<void, T ...></font>.</div><br class=3D""><=
blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=
=3D""><div class=3D"">This is the work-in-progress in a Google Doc: <a=
href=3D"https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75=
dSq6YiJHDhp48/edit?usp=3Dsharing" class=3D"">Variant</a> and it is ope=
n for comments.</div><div class=3D""></div></div></div></blockquote><div><b=
r class=3D""></div><div>The #1 problem with N4542, IMHO, is that it aggrega=
tes and idealizes some existing implementations without actually prototypin=
g the result.</div><div><br class=3D""></div><div>I can=E2=80=99t speak for=
everyone, but I=E2=80=99d prefer to see a paper laying out arguments and p=
rinciples for their own sake, not a complete self-contained proposal going =
from ancient history up to standardese.</div></div><br class=3D""></body></=
html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_D6066D8F-5F91-4EE9-88A2-36C51B9F93F5--
.
Author: Michael Park <mcypark@gmail.com>
Date: Mon, 21 Sep 2015 03:59:23 -0700 (PDT)
Raw View
------=_Part_5067_2056639732.1442833163917
Content-Type: multipart/alternative;
boundary="----=_Part_5068_598190762.1442833163917"
------=_Part_5068_598190762.1442833163917
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 2:55:32 AM UTC-7, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9321, at 4:56 PM, Michael Park <mcy...@gmail.com=
<javascript:>>=20
> wrote:
>
> Hello, I've been working on an alternative variant proposal. It's still=
=20
> very rough at this point but I've captured the big questions I wanted to=
=20
> answer, and would appreciate feedback from the community.
>
> The following are some of the principles the design is based on:
> (1) *union* is not a good starting point for a discriminated union. I=
=20
> believe better starting points are:
>
>
> union is the only methodology with a chance at constexpr compatibility.
>
>
I think using union as the underlying storage for variant is necessary at=
=20
the implementation level to support constexpr (Agust=C3=ADn Berg=C3=A9 demo=
nstrates=20
this with eggs-variant <https://github.com/eggs-cpp/variant>).
But semantically, I don't think it should inherit union's behaviors such as=
=20
the default constructor attempting to default construct the first type.
> From C++: *enum* as a special case where each member is a unit=20
> type, and
> *class inheritance* where an abstract base class is a=20
> discriminated union of its derived classes.
> From other languages: Sum types from Haskell and ML or enum from=
=20
> Rust.
>
>
> Wait, what do you mean by =E2=80=9Cstarting point=E2=80=9D? How is any C+=
+ variant=20
> template still like a union, to the user?
>
I believe the *variant* proposed in N4542 is like a union to the user in=20
the following ways:
- Default construction tries to default construct the first type.
- The alternatives are discriminated by the index, rather than the type.=
=20
This leads to the result that *variant<int, int>* carries 2 distinct=20
states of int,
which means that index-based operations such as the index-based in-place=
=20
constructor, and index-based *get* must be provided.
(2) The *order* of the types specified in *variant<Ts...>* should not=20
> change its behavior.
>
>
> Agreed. The better evolutionary direction is to allow the implementation=
=20
> to sort the type-list, so any permutation of the same type-list names the=
=20
> same variant type.
>
> It=E2=80=99s only a series of unfortunate events that led std::type_info =
(and its=20
> member less()) to be non-constexpr, preventing this normalization from=20
> being done already.
>
=20
Yes, I agree that it would be ideal to sort the types. Meanwhile, I think=
=20
*variant* should still be order insensitive.
For example, *variant<int, std::string>* and *variant<std::string, int>*=20
should default-construct to the same state, if default-constructible at all=
..
Additionally, I think the index-based operations will be even less useful=
=20
once the types are ordered at compile-time.
> (3) The API should be minimal, useful, and consistent.
>
> The following are few design decisions that fall out from the above=20
> principles:
> * The visitation interface is a *type_switch* expression which looks=20
> similar to a regular *switch* statement,
> as well as *match* expressions from functional languages. (1)
> * Default construction should not construct the first type. (2)
> * The members should be discriminated by type rather than the index.=20
> (2), (3)
> (i.e. *variant<int, string, int>* behaves equivalently to *variant<i=
nt,=20
> string>*)
> * There is no special treatment for the null state. (3)
>
>
> What the heck does this mean? The question is whether a null state exists=
=20
> or not. How can it exist but not be special?
>
=20
>
I think, given the controversy, nullable and non-nullable versions should=
=20
> be supported. For example, it=E2=80=99s nullable if void appears in the t=
ypelist.=20
> Let nullable_variant (not actual proposed name) be an alias template to n=
onnull_variant<void,=20
> T ...>.
>
=20
Sorry that I was unclear about this. What I mean here is that a null state=
=20
exists by the presence of the null state tag, null_t,
but it's not special in the sense that variant does not change behavior in=
=20
its presence. It treats *null_t* as it would any other type.
It *does not do* any of the following:
- enable the default constructor only if variant is nullable
- set the variant to the null state rather than the valid, unspecified=
=20
state on assignment failure if *variant* is nullable
- provide a operator bool() if variant is nullable
This is the work-in-progress in a Google Doc: Variant=20
> <https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6Yi=
JHDhp48/edit?usp=3Dsharing> and=20
> it is open for comments.
>
> The #1 problem with N4542, IMHO, is that it aggregates and idealizes some=
=20
> existing implementations without actually prototyping the result.
>
I have a working implementation to supplement this proposal, but I haven't=
=20
mentioned it because it's a bit out of date.
It currently reflects the last iteration of the library. I'll be updating=
=20
the implementation throughout this week, but currently you can take a look=
=20
at https://github.com/mpark/variant
=20
> I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper=
laying out=20
> arguments and principles for their own sake, not a complete self-containe=
d=20
> proposal going from ancient history up to standardese.
>
Could you please elaborate a little on what you mean by "laying out=20
arguments and principles for their own sake"?
Thanks for your quick feedback!
MPark.
--=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_5068_598190762.1442833163917
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 21, 2015 at 2:55:32 AM UTC-7, David Krauss wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:bre=
ak-word"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=
=9321, at 4:56 PM, Michael Park <<a href=3D"javascript:" target=3D"_blan=
k" gdf-obfuscated-mailto=3D"Su6fbEexBQAJ" rel=3D"nofollow" onmousedown=3D"t=
his.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
javascript:';return true;">mcy...@gmail.com</a>> wrote:</div><br><di=
v><div dir=3D"ltr">Hello, I've been working on an alternative variant p=
roposal. It's still very rough at this point but I've captured the =
big questions I wanted to answer, and would appreciate feedback from the co=
mmunity.<div><br></div><div>The following are some of the principles the de=
sign is based on:</div><div>=C2=A0 (1)=C2=A0<font face=3D"courier new, mono=
space"><b>union</b></font>=C2=A0is not a good starting point for a discrimi=
nated union. I believe better starting points are:</div></div></div></block=
quote><div><br></div><div><font face=3D"Courier">union</font> is the only m=
ethodology with a chance at <font face=3D"Courier">constexpr</font> compati=
bility.</div><br></div></div></blockquote><div><br></div><div>I think using=
<font face=3D"courier new, monospace">union</font><font face=3D"arial, san=
s-serif">=C2=A0as the underlying storage for </font><font face=3D"courier n=
ew, monospace">variant</font><font face=3D"arial, sans-serif"> is necessary=
at the implementation level to support </font><font face=3D"courier new, m=
onospace">constexpr</font><font face=3D"arial, sans-serif"> (</font><span s=
tyle=3D"color: rgb(51, 51, 51); line-height: 25.6px;"><font face=3D"arial, =
sans-serif" size=3D"2">Agust=C3=ADn Berg=C3=A9 demonstrates this with</font=
><font face=3D"arial, sans-serif" size=3D"2">=C2=A0</font></span><span styl=
e=3D"font-family: arial, sans-serif;"><a href=3D"https://github.com/eggs-cp=
p/variant">eggs-variant</a>).</span></div><div><font face=3D"arial, sans-se=
rif">But semantically, I don't think it should inherit </font><font fac=
e=3D"courier new, monospace">union</font><font face=3D"arial, sans-serif">&=
#39;s behaviors such as the default constructor attempting to default const=
ruct the first type<font size=3D"2">.</font></font></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><block=
quote type=3D"cite"><div><div dir=3D"ltr"><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0F=
rom C++:=C2=A0<font face=3D"courier new, monospace"><b>enum</b></font>=C2=
=A0as a special case where each member is a unit type, and</div><div>=C2=A0=
=C2=A0 =C2=A0 =C2=A0<b>class inheritance</b>=C2=A0where an abstract base c=
lass is a discriminated union of its derived classes.</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0From other languages: Sum types from Haskell and ML or=C2=
=A0<font face=3D"courier new, monospace" style=3D"font-weight:bold">enum</f=
ont><font face=3D"arial, sans-serif"><b>=C2=A0</b>from Rust.</font></div></=
div></div></blockquote><div><br></div><div>Wait, what do you mean by =E2=80=
=9Cstarting point=E2=80=9D? How is any C++ variant template still like a un=
ion, to the user?</div></div></div></blockquote><div><br></div><div>I belie=
ve the <font face=3D"courier new, monospace"><b>variant</b></font><font fac=
e=3D"arial, sans-serif">=C2=A0proposed in N4542 is like a union to the user=
in the following ways:</font></div><div><ul><li>Default construction tries=
to default construct the first type.</li><li>The alternatives are discrimi=
nated by the index, rather than the type. This leads to the result that=C2=
=A0<font face=3D"courier new, monospace"><b>variant<int, int></b></fo=
nt><font face=3D"arial, sans-serif">=C2=A0carries 2 distinct states of=C2=
=A0</font><font face=3D"courier new, monospace" style=3D"font-weight: bold;=
">int</font><font face=3D"arial, sans-serif">,</font><br><font face=3D"aria=
l, sans-serif">which means that index-based operations </font>such as the i=
ndex-based in-place constructor, and index-based <b>get</b>=C2=A0must be pr=
ovided.</li></ul></div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div st=
yle=3D"word-wrap:break-word"><div><blockquote type=3D"cite"><div><div dir=
=3D"ltr"><div>=C2=A0 (2) The=C2=A0<b>order</b>=C2=A0of the types specified =
in=C2=A0<font face=3D"courier new, monospace"><b>variant<Ts...></b></=
font>=C2=A0should not change its behavior.</div></div></div></blockquote><d=
iv><br></div><div>Agreed. The better evolutionary direction is to allow the=
implementation to sort the type-list, so any permutation of the same type-=
list names the same variant type.</div><div><br></div><div>It=E2=80=99s onl=
y a series of unfortunate events that led <font face=3D"Courier">std::type_=
info</font> (and its member <font face=3D"Courier">less()</font>) to be non=
-constexpr, preventing this normalization from being done already.</div></d=
iv></div></blockquote><div>=C2=A0</div><div>Yes, I agree that it would be i=
deal to sort the types. Meanwhile, I think=C2=A0<font face=3D"courier new, =
monospace"><b>variant</b></font>=C2=A0should still be order insensitive.</d=
iv><div>For example, <font face=3D"courier new, monospace"><b>variant<in=
t, std::string></b></font> and <font face=3D"courier new, monospace"><b>=
variant<std::string, int></b></font> should default-construct to the =
same state, if default-constructible at all.<br></div><div><br></div><div>A=
dditionally, I think the index-based operations will be even less useful on=
ce the types are ordered at compile-time.</div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><blockquote type=
=3D"cite"><div><div dir=3D"ltr"><div>=C2=A0 (3) The API should be minimal, =
useful, and consistent.</div><div><br></div><div>The following are few desi=
gn decisions that fall out from the above principles:</div><div>=C2=A0 * Th=
e visitation interface is a=C2=A0<b>type_switch</b>=C2=A0expression which l=
ooks similar to a regular=C2=A0<b>switch</b>=C2=A0statement,</div><div>=C2=
=A0 =C2=A0 as well as=C2=A0<b>match</b>=C2=A0expressions from functional la=
nguages. (1)</div><div>=C2=A0 * Default construction should not construct t=
he first type. (2)</div><div>=C2=A0 * The members should be discriminated b=
y type rather than the index. (2), (3)</div><div>=C2=A0 =C2=A0 =C2=A0(i.e.=
=C2=A0<font face=3D"courier new, monospace"><b>variant<int, string, int&=
gt;</b></font>=C2=A0behaves equivalently to=C2=A0<b style=3D"font-family:&#=
39;courier new',monospace">variant<int, string></b><font face=3D"=
arial, sans-serif">)</font></div><div>=C2=A0 * There is no special treatmen=
t for the null state. (3)</div><div></div></div></div></blockquote><div><br=
></div><div>What the heck does this mean? The question is whether a null st=
ate exists or not. How can it exist but not be special?</div></div></div></=
blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-=
wrap:break-word"><div><div>=C2=A0</div></div></div></blockquote><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div>=
<div></div><div>I think, given the controversy, nullable and non-nullable v=
ersions should be supported. For example, it=E2=80=99s nullable if <font fa=
ce=3D"Courier">void</font> appears in the typelist. Let <font face=3D"Couri=
er">nullable_variant</font>=C2=A0(not actual proposed name) be an alias tem=
plate to <font face=3D"Courier">nonnull_variant<void, T ...></font>.<=
/div></div></div></blockquote><div>=C2=A0</div><div>Sorry that I was unclea=
r about this. What I mean here is that a null state exists by the presence =
of the null state tag,=C2=A0<font face=3D"courier new, monospace" style=3D"=
font-weight: bold;">null_t</font><font face=3D"arial, sans-serif">,</font><=
/div><div><font face=3D"arial, sans-serif">but=C2=A0it's=C2=A0not speci=
al in the sense that variant does not change behavior in its presence. It t=
reats </font><font face=3D"courier new, monospace"><b>null_t</b></font><fon=
t face=3D"arial, sans-serif"> as it would any other type.</font></div><div>=
<font face=3D"arial, sans-serif">It=C2=A0<b>does not do</b>=C2=A0any of the=
following:</font></div><div><ul><li><font face=3D"arial, sans-serif">enabl=
e the default constructor only if=C2=A0</font><font face=3D"courier new, mo=
nospace" style=3D"font-weight: bold;">variant</font><font face=3D"arial, sa=
ns-serif">=C2=A0is nullable</font><br></li><li><font face=3D"arial, sans-se=
rif">set the variant to the null state rather than the valid, unspecified s=
tate on assignment failure if=C2=A0</font><font face=3D"courier new, monosp=
ace"><b>variant</b></font><font face=3D"arial, sans-serif">=C2=A0is nullabl=
e</font></li><li><font face=3D"arial, sans-serif">provide a=C2=A0</font><fo=
nt face=3D"courier new, monospace" style=3D"font-weight: bold;">operator bo=
ol()</font><font face=3D"arial, sans-serif">=C2=A0if=C2=A0</font><font face=
=3D"courier new, monospace" style=3D"font-weight: bold;">variant</font><fon=
t face=3D"arial, sans-serif">=C2=A0is nullable</font></li></ul></div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word">=
<div><blockquote type=3D"cite"><div><div dir=3D"ltr"><div>This is the work-=
in-progress in a Google Doc:=C2=A0<a href=3D"https://docs.google.com/docume=
nt/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Dsharing" targe=
t=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://docs.=
google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=
\75sharing';return true;" onclick=3D"this.href=3D'https://docs.goog=
le.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp\75s=
haring';return true;">Variant</a>=C2=A0and it is open for comments.</di=
v></div></div></blockquote><div>The #1 problem with N4542, IMHO, is that it=
aggregates and idealizes some existing implementations without actually pr=
ototyping the result.</div></div></div></blockquote><div><br></div><div>I h=
ave a working implementation to supplement this proposal, but I haven't=
mentioned it because it's a bit out of date.</div><div>It currently re=
flects the last iteration of the library. I'll be updating the implemen=
tation throughout this week, but currently you can take a look at <a href=
=3D"https://github.com/mpark/variant">https://github.com/mpark/variant</a><=
/div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div sty=
le=3D"word-wrap:break-word"><div><div>I can=E2=80=99t speak for everyone, b=
ut I=E2=80=99d prefer to see a paper laying out arguments and principles fo=
r their own sake, not a complete self-contained proposal going from ancient=
history up to standardese.</div></div></div></blockquote><div><br></div><d=
iv>Could you please elaborate a little on what you mean by "laying out=
arguments and principles for their own sake"?</div><div><br></div><di=
v>Thanks for your quick feedback!</div><div><br></div><div>MPark.</div>
<p></p>
-- <br />
<br />
--- <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 />
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_5068_598190762.1442833163917--
------=_Part_5067_2056639732.1442833163917--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 21 Sep 2015 05:15:23 -0700 (PDT)
Raw View
------=_Part_457_1182104650.1442837723127
Content-Type: multipart/alternative;
boundary="----=_Part_458_1970126247.1442837723127"
------=_Part_458_1970126247.1442837723127
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 5:55:32 AM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9321, at 4:56 PM, Michael Park <mcy...@gmail.com=
<javascript:>>=20
> wrote:
>
> (2) The *order* of the types specified in *variant<Ts...>* should not=
=20
> change its behavior.
>
>
> Agreed. The better evolutionary direction is to allow the implementation=
=20
> to sort the type-list, so any permutation of the same type-list names the=
=20
> same variant type.
>
Sort it based on what, exactly?
Personally, I don't see why it's so important to have a few default=20
behaviors based on the ordering in the list. If you're going to have=20
default construction that constructs one element, then the user should be=
=20
able to control what that default element is. Who cares what other=20
languages do; this is C++, and C++ has its own unique needs.
If you don't want behavior based on the order of items in the list, fine;=
=20
don't use those behaviors. Don't default-construct your variants.
=20
> It=E2=80=99s only a series of unfortunate events that led std::type_info =
(and its=20
> member less()) to be non-constexpr, preventing this normalization from=20
> being done already.
>
> (3) The API should be minimal, useful, and consistent.
>
> The following are few design decisions that fall out from the above=20
> principles:
> * The visitation interface is a *type_switch* expression which looks=20
> similar to a regular *switch* statement,
> as well as *match* expressions from functional languages. (1)
> * Default construction should not construct the first type. (2)
> * The members should be discriminated by type rather than the index.=20
> (2), (3)
> (i.e. *variant<int, string, int>* behaves equivalently to *variant<i=
nt,=20
> string>*)
> * There is no special treatment for the null state. (3)
>
>
> What the heck does this mean? The question is whether a null state exists=
=20
> or not. How can it exist but not be special?
>
> I think, given the controversy, nullable and non-nullable versions should=
=20
> be supported. For example, it=E2=80=99s nullable if void appears in the t=
ypelist.=20
> Let nullable_variant (not actual proposed name) be an alias template to n=
onnull_variant<void,=20
> T ...>.
>
I don't think that `void` would be appropriate for the nullable type. While=
=20
you can get pointers to void, you can't get void references. It just=20
doesn't behave like a normal type. It would be better to define an=20
explicit, empty type that would be treated by users as the empty type for=
=20
variants.
Also, I really prefer the current design, where there is a distinction=20
between being empty and being in a state that the user considers empty. The=
=20
former can only happen as a consequence of a copy/move failure; it exists=
=20
*solely* for error handling as an unfortunate consequence of the C++=20
language.
> This is the work-in-progress in a Google Doc: Variant=20
> <https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6Yi=
JHDhp48/edit?usp=3Dsharing> and=20
> it is open for comments.
>
>
> The #1 problem with N4542, IMHO, is that it aggregates and idealizes some=
=20
> existing implementations without actually prototyping the result.
>
To be fair, there's not much difference between Boost.Variant and N4542.=20
The principle differences are the empty-as-error state and C++11/14=20
features. In principle, the visitation has been around for quite some time=
=20
and has a lot of user-experience behind it.
And it's not like std::any and std::optional didn't do more or less the=20
same thing. Or std::shared_ptr, for that matter.
It's a Boost component being introduced to the standard library.
> I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper=
laying out=20
> arguments and principles for their own sake, not a complete self-containe=
d=20
> proposal going from ancient history up to standardese.
>
That would make things take *longer*.
--=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_458_1970126247.1442837723127
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 21, 2015 at 5:55:32 AM UTC-4, David Krauss wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:bre=
ak-word"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=
=9321, at 4:56 PM, Michael Park <<a href=3D"javascript:" target=3D"_blan=
k" gdf-obfuscated-mailto=3D"Su6fbEexBQAJ" rel=3D"nofollow" onmousedown=3D"t=
his.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
javascript:';return true;">mcy...@gmail.com</a>> wrote:</div></block=
quote><blockquote type=3D"cite"><div><div dir=3D"ltr"><div>=C2=A0 (2) The=
=C2=A0<b>order</b>=C2=A0of the types specified in=C2=A0<font face=3D"courie=
r new, monospace"><b>variant<Ts...></b></font>=C2=A0should not change=
its behavior.</div></div></div></blockquote><div><br></div><div>Agreed. Th=
e better evolutionary direction is to allow the implementation to sort the =
type-list, so any permutation of the same type-list names the same variant =
type.</div></div></div></blockquote><div><br>Sort it based on what, exactly=
?<br><br>Personally, I don't see why it's so important to have a fe=
w default behaviors based on the ordering in the list. If you're going =
to have default construction that constructs one element, then the user sho=
uld be able to control what that default element is. Who cares what other l=
anguages do; this is C++, and C++ has its own unique needs.<br><br>If you d=
on't want behavior based on the order of items in the list, fine; don&#=
39;t use those behaviors. Don't default-construct your variants.<br>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wr=
ap:break-word"><div><div></div><div>It=E2=80=99s only a series of unfortuna=
te events that led <font face=3D"Courier">std::type_info</font> (and its me=
mber <font face=3D"Courier">less()</font>) to be non-constexpr, preventing =
this normalization from being done already.</div><br><blockquote type=3D"ci=
te"><div><div dir=3D"ltr"><div>=C2=A0 (3) The API should be minimal, useful=
, and consistent.</div><div><br></div><div>The following are few design dec=
isions that fall out from the above principles:</div><div>=C2=A0 * The visi=
tation interface is a=C2=A0<b>type_switch</b>=C2=A0expression which looks s=
imilar to a regular=C2=A0<b>switch</b>=C2=A0statement,</div><div>=C2=A0 =C2=
=A0 as well as=C2=A0<b>match</b>=C2=A0expressions from functional languages=
.. (1)</div><div>=C2=A0 * Default construction should not construct the firs=
t type. (2)</div><div>=C2=A0 * The members should be discriminated by type =
rather than the index. (2), (3)</div><div>=C2=A0 =C2=A0 =C2=A0(i.e.=C2=A0<f=
ont face=3D"courier new, monospace"><b>variant<int, string, int></b><=
/font>=C2=A0behaves equivalently to=C2=A0<b style=3D"font-family:'couri=
er new',monospace">variant<int, string></b><font face=3D"arial, s=
ans-serif">)</font></div><div>=C2=A0 * There is no special treatment for th=
e null state. (3)</div><div></div></div></div></blockquote><div><br></div><=
div>What the heck does this mean? The question is whether a null state exis=
ts or not. How can it exist but not be special?</div><div><br></div><div>I =
think, given the controversy, nullable and non-nullable versions should be =
supported. For example, it=E2=80=99s nullable if <font face=3D"Courier">voi=
d</font> appears in the typelist. Let <font face=3D"Courier">nullable_varia=
nt</font>=C2=A0(not actual proposed name) be an alias template to <font fac=
e=3D"Courier">nonnull_variant<void, T ...></font>.</div></div></div><=
/blockquote><div><br>I don't think that `void` would be appropriate for=
the nullable type. While you can get pointers to void, you can't get v=
oid references. It just doesn't behave like a normal type. It would be =
better to define an explicit, empty type that would be treated by users as =
the empty type for variants.<br><br>Also, I really prefer the current desig=
n, where there is a distinction between being empty and being in a state th=
at the user considers empty. The former can only happen as a consequence of=
a copy/move failure; it exists <i>solely</i> for error handling as an unfo=
rtunate consequence of the C++ language.<br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><blockquote ty=
pe=3D"cite"><div><div dir=3D"ltr"><div>This is the work-in-progress in a Go=
ogle Doc:=C2=A0<a href=3D"https://docs.google.com/document/d/12PPuGwSel38Yz=
XadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Dsharing" target=3D"_blank" rel=3D=
"nofollow" onmousedown=3D"this.href=3D'https://docs.google.com/document=
/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp\75sharing';ret=
urn true;" onclick=3D"this.href=3D'https://docs.google.com/document/d/1=
2PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp\75sharing';return =
true;">Variant</a>=C2=A0and it is open for comments.</div><div></div></div>=
</div></blockquote><div><br></div><div>The #1 problem with N4542, IMHO, is =
that it aggregates and idealizes some existing implementations without actu=
ally prototyping the result.</div></div></div></blockquote><div><br>To be f=
air, there's not much difference between Boost.Variant and N4542. The p=
rinciple differences are the empty-as-error state and C++11/14 features. In=
principle, the visitation has been around for quite some time and has a lo=
t of user-experience behind it.<br><br>And it's not like std::any and s=
td::optional didn't do more or less the same thing. Or std::shared_ptr,=
for that matter.<br><br>It's a Boost component being introduced to the=
standard library.<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 style=3D"word-wrap:break-word"><div><div><br></div><div>I can=E2=80=
=99t speak for everyone, but I=E2=80=99d prefer to see a paper laying out a=
rguments and principles for their own sake, not a complete self-contained p=
roposal going from ancient history up to standardese.<br></div></div></div>=
</blockquote><div><br>That would make things take <i>longer</i>.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_458_1970126247.1442837723127--
------=_Part_457_1182104650.1442837723127--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 21 Sep 2015 05:17:06 -0700 (PDT)
Raw View
------=_Part_183_1917312979.1442837826710
Content-Type: multipart/alternative;
boundary="----=_Part_184_448698372.1442837826710"
------=_Part_184_448698372.1442837826710
Content-Type: text/plain; charset=UTF-8
On Monday, September 21, 2015 at 8:15:23 AM UTC-4, Nicol Bolas wrote:
>
> Personally, I don't see why it's so important to have a few default
> behaviors based on the ordering in the list.
>
Sorry; I said that wrong. That should be:
Personally, I don't see what's wrong with having a few default behaviors
> based on the ordering in the list.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_184_448698372.1442837826710
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, September 21, 2015 at 8:15:23 AM UTC-4, Nicol B=
olas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>Personally, I =
don't see why it's so important to have a few default behaviors bas=
ed on the ordering in the list.</div></blockquote><div><br>Sorry; I said th=
at wrong. That should be:<br><br><blockquote style=3D"margin: 0px 0px 0px 0=
..8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class=
=3D"gmail_quote">Personally, I don't see what's wrong with having a=
few default behaviors based on the ordering in the list.</blockquote></div=
></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_184_448698372.1442837826710--
------=_Part_183_1917312979.1442837826710--
.
Author: David Krauss <potswa@mac.com>
Date: Mon, 21 Sep 2015 20:18:50 +0800
Raw View
--Apple-Mail=_BBA49961-8B46-4411-AE62-3FE6D40AD7E4
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9321, at 6:59 PM, Michael Park <mcypark@gmail.co=
m> wrote:
>=20
> I believe the variant proposed in N4542 is like a union to the user in th=
e following ways:
> Default construction tries to default construct the first type.
Yes, this is bad. It=E2=80=99s not quite so bad for C-style unions, which g=
et a deleted default constructor if any member is not trivially constructib=
le. The construct-first-member behavior only comes back when using aggregat=
e initialization.
> The alternatives are discriminated by the index, rather than the type. Th=
is leads to the result that variant<int, int> carries 2 distinct states of =
int,
> which means that index-based operations such as the index-based in-place =
constructor, and index-based get must be provided.
They=E2=80=99re discriminated by either, but as mentioned, I don=E2=80=99t =
think numeric indexing is a good idea. (I guess you mean that unions can ha=
ve different-named members of the same type, and numbers are like names.)
I=E2=80=99m not going back just now to review N4542, but I thought I saw it=
forbid including the same type twice. Such a violation of a library precon=
dition would result in UB.
> Sorry that I was unclear about this. What I mean here is that a null stat=
e exists by the presence of the null state tag, null_t,
> but it's not special in the sense that variant does not change behavior i=
n its presence. It treats null_t as it would any other type.
> It does not do any of the following:
Why not spell null_t as void? null_t sounds like a type with a single value=
, perhaps one which can be compared to a variant or passed as a constructor=
overloading dispatch tag. Any type, even such a special wacky one, should =
be supported within variant. (Which motivates avoidance of having special s=
ingletons in the first place.)
The type with no values is void.
> enable the default constructor only if variant is nullable
This seems a bit draconian to me.
> set the variant to the null state rather than the valid, unspecified stat=
e on assignment failure if variant is nullable
Agreed; variant assignment failure should work the same as any, function, a=
rray, or any non-node-based handle class. I=E2=80=99m surprised this is eve=
n being considered as a problem in particular.
> provide a operator bool() if variant is nullable
Yes; operator bool should simply always return true if not nullable.
>> This is the work-in-progress in a Google Doc: Variant <https://docs.goog=
le.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Ds=
haring> and it is open for comments.
> The #1 problem with N4542, IMHO, is that it aggregates and idealizes some=
existing implementations without actually prototyping the result.
>=20
> I have a working implementation to supplement this proposal, but I haven'=
t mentioned it because it's a bit out of date.
> It currently reflects the last iteration of the library. I'll be updating=
the implementation throughout this week, but currently you can take a look=
at https://github.com/mpark/variant <https://github.com/mpark/variant>
Oh, nice!
I don=E2=80=99t see any mention of reference types, which are supported in =
N4542.
> I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper=
laying out arguments and principles for their own sake, not a complete sel=
f-contained proposal going from ancient history up to standardese.
>=20
> Could you please elaborate a little on what you mean by "laying out argum=
ents and principles for their own sake=E2=80=9D?
Well, I presumed that no implementation would be forthcoming so close to th=
e deadline, so I meant to encourage you to cut the fat and focus on new mat=
erial. But, I agree that a comprehensive prototype deserves a comprehensive=
proposal. Unfortunately I=E2=80=99m a bit busy this week to review your li=
brary in detail, but best luck to you!
--=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/.
--Apple-Mail=_BBA49961-8B46-4411-AE62-3FE6D40AD7E4
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9321, at 6:59 PM, Michael Park <<a href=3D"mailto:mcypark@gmail.c=
om" class=3D"">mcypark@gmail.com</a>> wrote:</div><br class=3D"Apple-int=
erchange-newline"><div class=3D"">I believe the <font face=3D"courier =
new, monospace" class=3D""><b class=3D"">variant</b></font><font face=3D"ar=
ial, sans-serif" class=3D""> proposed in N4542 is like a union to the =
user in the following ways:</font><br class=3D""><div style=3D"font-family:=
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font=
-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto=
; text-align: start; text-indent: 0px; text-transform: none; white-space: n=
ormal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" cl=
ass=3D""><ul class=3D""><li class=3D"">Default construction tries to defaul=
t construct the first type.</li></ul></div></div></blockquote><div>Yes, thi=
s is bad. It=E2=80=99s not quite so bad for C-style <font face=3D"Courier" =
class=3D"">union</font>s, which get a deleted default constructor if any me=
mber is not trivially constructible. The construct-first-member behavior on=
ly comes back when using aggregate initialization.</div><blockquote type=3D=
"cite" class=3D""><div class=3D""><div style=3D"font-family: Helvetica; fon=
t-size: 12px; font-style: normal; font-variant: normal; font-weight: normal=
; letter-spacing: normal; line-height: normal; orphans: auto; text-align: s=
tart; text-indent: 0px; text-transform: none; white-space: normal; widows: =
auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><ul cl=
ass=3D""><li class=3D"">The alternatives are discriminated by the index, ra=
ther than the type. This leads to the result that <font face=3D"courie=
r new, monospace" class=3D""><b class=3D"">variant<int, int></b></fon=
t><font face=3D"arial, sans-serif" class=3D""> carries 2 distinct stat=
es of </font><font face=3D"courier new, monospace" style=3D"font-weigh=
t: bold;" class=3D"">int</font><font face=3D"arial, sans-serif" class=3D"">=
,</font><br class=3D""><font face=3D"arial, sans-serif" class=3D"">which me=
ans that index-based operations<span class=3D"Apple-converted-space"> =
</span></font>such as the index-based in-place constructor, and index-based=
<span class=3D"Apple-converted-space"> </span><b class=3D"">get</b>&nb=
sp;must be provided.</li></ul></div></div></blockquote><div>They=E2=80=99re=
discriminated by either, but as mentioned, I don=E2=80=99t think numeric i=
ndexing is a good idea. (I guess you mean that unions can have differe=
nt-named members of the same type, and numbers are like names.)</div><div><=
br class=3D""></div><div>I=E2=80=99m not going back just now to review N454=
2, but I thought I saw it forbid including the same type twice. Such a viol=
ation of a library precondition would result in UB.</div><br class=3D""><bl=
ockquote type=3D"cite" class=3D""><div class=3D""><div style=3D"font-family=
: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; fon=
t-weight: normal; letter-spacing: normal; line-height: normal; orphans: aut=
o; text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" c=
lass=3D"">Sorry that I was unclear about this. What I mean here is that a n=
ull state exists by the presence of the null state tag, <font face=3D"=
courier new, monospace" style=3D"font-weight: bold;" class=3D"">null_t</fon=
t><font face=3D"arial, sans-serif" class=3D"">,</font></div><div style=3D"f=
ont-family: Helvetica; font-size: 12px; font-style: normal; font-variant: n=
ormal; font-weight: normal; letter-spacing: normal; line-height: normal; or=
phans: auto; text-align: start; text-indent: 0px; text-transform: none; whi=
te-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-widt=
h: 0px;" class=3D""><font face=3D"arial, sans-serif" class=3D"">but it=
's not special in the sense that variant does not change behavior in i=
ts presence. It treats<span class=3D"Apple-converted-space"> </span></=
font><font face=3D"courier new, monospace" class=3D""><b class=3D"">null_t<=
/b></font><font face=3D"arial, sans-serif" class=3D""><span class=3D"Apple-=
converted-space"> </span>as it would any other type.</font></div><div =
style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-=
variant: normal; font-weight: normal; letter-spacing: normal; line-height: =
normal; orphans: auto; text-align: start; text-indent: 0px; text-transform:=
none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-s=
troke-width: 0px;" class=3D""><font face=3D"arial, sans-serif" class=3D"">I=
t <b class=3D"">does not do</b> any of the following:</font></div=
></div></blockquote><div><br class=3D""></div>Why not spell <font face=3D"C=
ourier" class=3D"">null_t</font> as <font face=3D"Courier" class=3D"">void<=
/font>? <font face=3D"Courier" class=3D"">null_t</font> sounds like a type =
with a single value, perhaps one which can be compared to a <font face=3D"C=
ourier" class=3D"">variant</font> or passed as a constructor overloadi=
ng dispatch tag. Any type, even such a special wacky one, should be support=
ed within <font face=3D"Courier" class=3D"">variant</font>. (Which mot=
ivates avoidance of having special singletons in the first place.)</div><di=
v><br class=3D""></div><div>The type with no values is <font face=3D"Courie=
r" class=3D"">void</font>.<br class=3D""><blockquote type=3D"cite" class=3D=
""><div class=3D""><div style=3D"font-family: Helvetica; font-size: 12px; f=
ont-style: normal; font-variant: normal; font-weight: normal; letter-spacin=
g: normal; line-height: normal; orphans: auto; text-align: start; text-inde=
nt: 0px; text-transform: none; white-space: normal; widows: auto; word-spac=
ing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><ul class=3D""><li cl=
ass=3D""><font face=3D"arial, sans-serif" class=3D"">enable the default con=
structor only if </font><font face=3D"courier new, monospace" style=3D=
"font-weight: bold;" class=3D"">variant</font><font face=3D"arial, sans-ser=
if" class=3D""> is nullable</font><br class=3D""></li></ul></div></div=
></blockquote>This seems a bit draconian to me.<br class=3D""><blockquote t=
ype=3D"cite" class=3D""><div class=3D""><div style=3D"font-family: Helvetic=
a; font-size: 12px; font-style: normal; font-variant: normal; font-weight: =
normal; letter-spacing: normal; line-height: normal; orphans: auto; text-al=
ign: start; text-indent: 0px; text-transform: none; white-space: normal; wi=
dows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D"">=
<ul class=3D""><li class=3D""><font face=3D"arial, sans-serif" class=3D"">s=
et the variant to the null state rather than the valid, unspecified state o=
n assignment failure if </font><font face=3D"courier new, monospace" c=
lass=3D""><b class=3D"">variant</b></font><font face=3D"arial, sans-serif" =
class=3D""> is nullable</font></li></ul></div></div></blockquote>Agree=
d; <font face=3D"Courier" class=3D"">variant</font> assignment failure shou=
ld work the same as <font face=3D"Courier" class=3D"">any</font>, <font fac=
e=3D"Courier" class=3D"">function</font>, <font face=3D"Courier" class=3D""=
>array</font>, or any non-node-based handle class. I=E2=80=99m surprised th=
is is even being considered as a problem in particular.<br class=3D""><bloc=
kquote type=3D"cite" class=3D""><div class=3D""><div style=3D"font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-=
weight: normal; letter-spacing: normal; line-height: normal; orphans: auto;=
text-align: start; text-indent: 0px; text-transform: none; white-space: no=
rmal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" cla=
ss=3D""><ul class=3D""><li class=3D""><font face=3D"arial, sans-serif" clas=
s=3D"">provide a </font><font face=3D"courier new, monospace" style=3D=
"font-weight: bold;" class=3D"">operator bool()</font><font face=3D"arial, =
sans-serif" class=3D""> if </font><font face=3D"courier new, mono=
space" style=3D"font-weight: bold;" class=3D"">variant</font><font face=3D"=
arial, sans-serif" class=3D""> is nullable</font></li></ul></div></div=
></blockquote><div>Yes; <font face=3D"Courier" class=3D"">operator bool</fo=
nt> should simply always return <font face=3D"Courier" class=3D"">true</fon=
t> if not nullable.</div><br class=3D""><blockquote type=3D"cite" class=3D"=
"><blockquote class=3D"gmail_quote" style=3D"font-family: Helvetica; font-s=
ize: 12px; font-style: normal; font-variant: normal; font-weight: normal; l=
etter-spacing: normal; line-height: normal; orphans: auto; text-align: star=
t; text-indent: 0px; text-transform: none; white-space: normal; widows: aut=
o; word-spacing: 0px; -webkit-text-stroke-width: 0px; 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 style=3D"word-wrap: break-word=
;" class=3D""><div class=3D""><blockquote type=3D"cite" class=3D""><div cla=
ss=3D""><div dir=3D"ltr" class=3D""><div class=3D"">This is the work-in-pro=
gress in a Google Doc: <a href=3D"https://docs.google.com/document/d/1=
2PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Dsharing" target=3D"_=
blank" rel=3D"nofollow" class=3D"">Variant</a> and it is open for comm=
ents.</div></div></div></blockquote><div class=3D"">The #1 problem with N45=
42, IMHO, is that it aggregates and idealizes some existing implementations=
without actually prototyping the result.</div></div></div></blockquote><di=
v style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; fon=
t-variant: normal; font-weight: normal; letter-spacing: normal; line-height=
: normal; orphans: auto; text-align: start; text-indent: 0px; text-transfor=
m: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text=
-stroke-width: 0px;" class=3D""><br class=3D""></div><div style=3D"font-fam=
ily: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; =
font-weight: normal; letter-spacing: normal; line-height: normal; orphans: =
auto; text-align: start; text-indent: 0px; text-transform: none; white-spac=
e: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;=
" class=3D"">I have a working implementation to supplement this proposal, b=
ut I haven't mentioned it because it's a bit out of date.</div><div style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D"">It currently reflects the last iteration of the li=
brary. I'll be updating the implementation throughout this week, but curren=
tly you can take a look at<span class=3D"Apple-converted-space"> </spa=
n><a href=3D"https://github.com/mpark/variant" class=3D"">https://github.co=
m/mpark/variant</a></div></blockquote><div><br class=3D""></div><div>Oh, ni=
ce!</div><div><br class=3D""></div><div>I don=E2=80=99t see any mention of =
reference types, which are supported in N4542.</div><br class=3D""><blockqu=
ote type=3D"cite" class=3D""><blockquote class=3D"gmail_quote" style=3D"fon=
t-family: Helvetica; font-size: 12px; font-style: normal; font-variant: nor=
mal; font-weight: normal; letter-spacing: normal; line-height: normal; orph=
ans: auto; text-align: start; text-indent: 0px; text-transform: none; white=
-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width:=
0px; 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 sty=
le=3D"word-wrap: break-word;" class=3D""><div class=3D""><div class=3D"">I =
can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper lay=
ing out arguments and principles for their own sake, not a complete self-co=
ntained proposal going from ancient history up to standardese.</div></div><=
/div></blockquote><div style=3D"font-family: Helvetica; font-size: 12px; fo=
nt-style: normal; font-variant: normal; font-weight: normal; letter-spacing=
: normal; line-height: normal; orphans: auto; text-align: start; text-inden=
t: 0px; text-transform: none; white-space: normal; widows: auto; word-spaci=
ng: 0px; -webkit-text-stroke-width: 0px;" class=3D""><br class=3D""></div><=
div style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; f=
ont-variant: normal; font-weight: normal; letter-spacing: normal; line-heig=
ht: normal; orphans: auto; text-align: start; text-indent: 0px; text-transf=
orm: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-te=
xt-stroke-width: 0px;" class=3D"">Could you please elaborate a little on wh=
at you mean by "laying out arguments and principles for their own sake=E2=
=80=9D?</div><div style=3D"font-family: Helvetica; font-size: 12px; font-st=
yle: normal; font-variant: normal; font-weight: normal; letter-spacing: nor=
mal; line-height: normal; orphans: auto; text-align: start; text-indent: 0p=
x; text-transform: none; white-space: normal; widows: auto; word-spacing: 0=
px; -webkit-text-stroke-width: 0px;" class=3D""></div></blockquote><div><br=
class=3D""></div><div>Well, I presumed that no implementation would be for=
thcoming so close to the deadline, so I meant to encourage you to cut the f=
at and focus on new material. But, I agree that a comprehensive prototype d=
eserves a comprehensive proposal. Unfortunately I=E2=80=99m a bit busy this=
week to review your library in detail, but best luck to you!</div></div><b=
r class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_BBA49961-8B46-4411-AE62-3FE6D40AD7E4--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 21 Sep 2015 20:24:18 +0800
Raw View
--Apple-Mail=_4F6BA13D-0C57-4CC7-9555-53978ED947F8
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9321, at 8:18 PM, David Krauss <potswa@mac.com> =
wrote:
>=20
> Agreed; variant assignment failure should work the same as any, function,=
array, or any non-node-based handle class. I=E2=80=99m surprised this is e=
ven being considered as a problem in particular.
Ah, oops, all those examples either aren=E2=80=99t erasures or are nullable=
..
Anyway, undefined behavior sounds good enough to me. Throwing move construc=
tors are evil, and not something that well-behaved programmers should pay f=
or.
--=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/.
--Apple-Mail=_4F6BA13D-0C57-4CC7-9555-53978ED947F8
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9321, at 8:18 PM, David Krauss <<a href=3D"mailto:potswa@mac.com"=
class=3D"">potswa@mac.com</a>> wrote:</div><br class=3D"Apple-interchan=
ge-newline"><div class=3D""><span style=3D"font-family: Helvetica; font-siz=
e: 12px; font-style: normal; font-variant: normal; font-weight: normal; let=
ter-spacing: normal; line-height: normal; orphans: auto; text-align: start;=
text-indent: 0px; text-transform: none; white-space: normal; widows: auto;=
word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: i=
nline !important;" class=3D"">Agreed;<span class=3D"Apple-converted-space">=
</span></span><font face=3D"Courier" class=3D"" style=3D"font-size: 1=
2px; font-style: normal; font-variant: normal; font-weight: normal; letter-=
spacing: normal; line-height: normal; orphans: auto; text-align: start; tex=
t-indent: 0px; text-transform: none; white-space: normal; widows: auto; wor=
d-spacing: 0px; -webkit-text-stroke-width: 0px;">variant</font><span style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px; float: none; display: inline !important;" class=3D""><span cla=
ss=3D"Apple-converted-space"> </span>assignment failure should work th=
e same as<span class=3D"Apple-converted-space"> </span></span><font fa=
ce=3D"Courier" class=3D"" style=3D"font-size: 12px; font-style: normal; fon=
t-variant: normal; font-weight: normal; letter-spacing: normal; line-height=
: normal; orphans: auto; text-align: start; text-indent: 0px; text-transfor=
m: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text=
-stroke-width: 0px;">any</font><span style=3D"font-family: Helvetica; font-=
size: 12px; font-style: normal; font-variant: normal; font-weight: normal; =
letter-spacing: normal; line-height: normal; orphans: auto; text-align: sta=
rt; text-indent: 0px; text-transform: none; white-space: normal; widows: au=
to; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display=
: inline !important;" class=3D"">,<span class=3D"Apple-converted-space">&nb=
sp;</span></span><font face=3D"Courier" class=3D"" style=3D"font-size: 12px=
; font-style: normal; font-variant: normal; font-weight: normal; letter-spa=
cing: normal; line-height: normal; orphans: auto; text-align: start; text-i=
ndent: 0px; text-transform: none; white-space: normal; widows: auto; word-s=
pacing: 0px; -webkit-text-stroke-width: 0px;">function</font><span style=3D=
"font-family: Helvetica; font-size: 12px; font-style: normal; font-variant:=
normal; font-weight: normal; letter-spacing: normal; line-height: normal; =
orphans: auto; text-align: start; text-indent: 0px; text-transform: none; w=
hite-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-wi=
dth: 0px; float: none; display: inline !important;" class=3D"">,<span class=
=3D"Apple-converted-space"> </span></span><font face=3D"Courier" class=
=3D"" style=3D"font-size: 12px; font-style: normal; font-variant: normal; f=
ont-weight: normal; letter-spacing: normal; line-height: normal; orphans: a=
uto; text-align: start; text-indent: 0px; text-transform: none; white-space=
: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"=
>array</font><span style=3D"font-family: Helvetica; font-size: 12px; font-s=
tyle: normal; font-variant: normal; font-weight: normal; letter-spacing: no=
rmal; line-height: normal; orphans: auto; text-align: start; text-indent: 0=
px; text-transform: none; white-space: normal; widows: auto; word-spacing: =
0px; -webkit-text-stroke-width: 0px; float: none; display: inline !importan=
t;" class=3D"">, or any non-node-based handle class. I=E2=80=99m surprised =
this is even being considered as a problem in particular.</span></div></blo=
ckquote></div><br class=3D""><div class=3D"">Ah, oops, all those examples e=
ither aren=E2=80=99t erasures or are nullable.</div><div class=3D""><br cla=
ss=3D""></div><div class=3D"">Anyway, undefined behavior sounds good enough=
to me. Throwing move constructors are evil, and not something that well-be=
haved programmers should pay for.</div><div class=3D""><br class=3D""></div=
></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_4F6BA13D-0C57-4CC7-9555-53978ED947F8--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 21 Sep 2015 05:40:11 -0700 (PDT)
Raw View
------=_Part_394_686833044.1442839211983
Content-Type: multipart/alternative;
boundary="----=_Part_395_108059597.1442839211983"
------=_Part_395_108059597.1442839211983
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 8:18:59 AM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9321, at 6:59 PM, Michael Park <mcy...@gmail.com=
<javascript:>>=20
> wrote:
>
>
> - The alternatives are discriminated by the index, rather than the=20
> type. This leads to the result that *variant<int, int>* carries 2=20
> distinct states of int,
> which means that index-based operations such as the index-based=20
> in-place constructor, and index-based *get* must be provided.
>
> They=E2=80=99re discriminated by either, but as mentioned, I don=E2=80=99=
t think numeric=20
> indexing is a good idea. (I guess you mean that unions can have=20
> different-named members of the same type, and numbers are like names.)
>
Personally, I don't like numeric indexing either, but I also never=20
understood why the committee allowed numeric indexing of tuples. The way I=
=20
see it, they're equally wrong, but if we're going to have one, we should=20
have the other for orthogonality's sake.
=20
> I=E2=80=99m not going back just now to review N4542, but I thought I saw =
it forbid=20
> including the same type twice.
>
Actually, it explicitly allows it; multiple repeated types are distinct=20
states. But it says that, for such a template, using a type-based getter=20
always fails; you have to access the element based on the index. Same goes=
=20
for emplacement construction.
=20
> Such a violation of a library precondition would result in UB.
>
Sorry that I was unclear about this. What I mean here is that a null state=
=20
> exists by the presence of the null state tag, null_t,
> but it's not special in the sense that variant does not change behavior i=
n=20
> its presence. It treats *null_t* as it would any other type.
> It *does not do* any of the following:
>
>
> Why not spell null_t as void?
>
Because `void` is not a normal C++ type.
=20
> null_t sounds like a type with a single value, perhaps one which can be=
=20
> compared to a variant or passed as a constructor overloading dispatch tag=
..
>
Exactly. And the "null" state of a variant should be able to do all of=20
those things.
The variant's "null" state should only be considered "null" by decree of=20
the user. The variant itself should only see it as just another state, just=
=20
as visitors should only see it as just another state. It's "null" because=
=20
the user decides that this value means that it has no value.
=20
> Any type, even such a special wacky one, should be supported within=20
> variant. (Which motivates avoidance of having special singletons in the=
=20
> first place.)
>
> The type with no values is void.
>
A variant in the "null" state has a value, just like a pointer in the=20
"null" state has a value. So even conceptually, `void` is the wrong thing.
`void` is not something we should try to use. It's something we should try=
=20
to *avoid* using.
--=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_395_108059597.1442839211983
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 21, 2015 at 8:18:59 AM UTC-4, David Krauss wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:bre=
ak-word"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=
=9321, at 6:59 PM, Michael Park <<a href=3D"javascript:" target=3D"_blan=
k" gdf-obfuscated-mailto=3D"008Fdhu5BQAJ" rel=3D"nofollow" onmousedown=3D"t=
his.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
javascript:';return true;">mcy...@gmail.com</a>> wrote:</div></block=
quote><blockquote type=3D"cite"><div><div style=3D"font-family:Helvetica;fo=
nt-size:12px;font-style:normal;font-variant:normal;font-weight:normal;lette=
r-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-t=
ransform:none;white-space:normal;word-spacing:0px"><ul><li>The alternatives=
are discriminated by the index, rather than the type. This leads to the re=
sult that=C2=A0<font face=3D"courier new, monospace"><b>variant<int, int=
></b></font><font face=3D"arial, sans-serif">=C2=A0carries 2 distinct st=
ates of=C2=A0</font><font style=3D"font-weight:bold" face=3D"courier new, m=
onospace">int</font><font face=3D"arial, sans-serif">,</font><br><font face=
=3D"arial, sans-serif">which means that index-based operations<span>=C2=A0<=
/span></font>such as the index-based in-place constructor, and index-based<=
span>=C2=A0</span><b>get</b>=C2=A0must be provided.</li></ul></div></div></=
blockquote><div>They=E2=80=99re discriminated by either, but as mentioned, =
I don=E2=80=99t think numeric indexing is a good idea. (I guess=C2=A0you me=
an that unions can have different-named members of the same type, and numbe=
rs are like names.)</div></div></div></blockquote><div><br>Personally, I do=
n't like numeric indexing either, but I also never understood why the c=
ommittee allowed numeric indexing of tuples. The way I see it, they're =
equally wrong, but if we're going to have one, we should have the other=
for orthogonality's sake.<br>=C2=A0</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 style=3D"word-wrap:break-word"><div><div></div><div>I=
=E2=80=99m not going back just now to review N4542, but I thought I saw it =
forbid including the same type twice.</div></div></div></blockquote><div><b=
r>Actually, it explicitly allows it; multiple repeated types are distinct s=
tates. But it says that, for such a template, using a type-based getter alw=
ays fails; you have to access the element based on the index. Same goes for=
emplacement construction.<br>=C2=A0</div><blockquote class=3D"gmail_quote"=
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-=
left: 1ex;"><div style=3D"word-wrap:break-word"><div><div>Such a violation =
of a library precondition would result in UB.</div></div></div></blockquote=
><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"=
word-wrap:break-word"><div><blockquote type=3D"cite"><div><div style=3D"fon=
t-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;fon=
t-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;t=
ext-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Sor=
ry that I was unclear about this. What I mean here is that a null state exi=
sts by the presence of the null state tag,=C2=A0<font style=3D"font-weight:=
bold" face=3D"courier new, monospace">null_t</font><font face=3D"arial, san=
s-serif">,</font></div><div style=3D"font-family:Helvetica;font-size:12px;f=
ont-style:normal;font-variant:normal;font-weight:normal;letter-spacing:norm=
al;line-height:normal;text-align:start;text-indent:0px;text-transform:none;=
white-space:normal;word-spacing:0px"><font face=3D"arial, sans-serif">but=
=C2=A0it's=C2=A0not special in the sense that variant does not change b=
ehavior in its presence. It treats<span>=C2=A0</span></font><font face=3D"c=
ourier new, monospace"><b>null_t</b></font><font face=3D"arial, sans-serif"=
><span>=C2=A0</span>as it would any other type.</font></div><div style=3D"f=
ont-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;f=
ont-weight:normal;letter-spacing:normal;line-height:normal;text-align:start=
;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><=
font face=3D"arial, sans-serif">It=C2=A0<b>does not do</b>=C2=A0any of the =
following:</font></div></div></blockquote><div><br></div>Why not spell <fon=
t face=3D"Courier">null_t</font> as <font face=3D"Courier">void</font>?</di=
v></div></blockquote><div><br>Because `void` is not a normal C++ type.<br>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word=
-wrap:break-word"><div><font face=3D"Courier">null_t</font> sounds like a t=
ype with a single value, perhaps one which can be compared to a <font face=
=3D"Courier">variant</font>=C2=A0or passed as a constructor overloading dis=
patch tag.</div></div></blockquote><div><br>Exactly. And the "null&quo=
t; state of a variant should be able to do all of those things.<br><br>The =
variant's "null" state should only be considered "null&q=
uot; by decree of the user. The variant itself should only see it as just a=
nother state, just as visitors should only see it as just another state. It=
's "null" because the user decides that this value means that=
it has no value.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;"><div style=3D"word-wrap:break-word"><div>Any type, even such a special w=
acky one, should be supported within=C2=A0<font face=3D"Courier">variant</f=
ont>. (Which motivates avoidance of having special singletons in the first =
place.)</div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div style=3D"word-wrap:break-word"><div><br></div><div>The type with no =
values is <font face=3D"Courier">void</font>.<br></div></div></blockquote><=
div><br>A variant in the "null" state has a value, just like a po=
inter in the "null" state has a value. So even conceptually, `voi=
d` is the wrong thing.<br><br>`void` is not something we should try to use.=
It's something we should try to <i>avoid</i> using.</div>
<p></p>
-- <br />
<br />
--- <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 />
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_395_108059597.1442839211983--
------=_Part_394_686833044.1442839211983--
.
Author: David Krauss <potswa@mac.com>
Date: Mon, 21 Sep 2015 20:40:44 +0800
Raw View
--Apple-Mail=_2CB011A4-511D-4101-A388-9E88AD1B678E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9321, at 8:15 PM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> Sort it based on what, exactly?
Implementation-defined. Probably, the collation of mangled type-names.
> Personally, I don't see why it's so important to have a few default behav=
iors based on the ordering in the list. If you're going to have default con=
struction that constructs one element, then the user should be able to cont=
rol what that default element is. Who cares what other languages do; this i=
s C++, and C++ has its own unique needs.
Sure, but specifying that by the order of the list is a bit impure. For tag=
ging types, we have tag types.
> If you don't want behavior based on the order of items in the list, fine;=
don't use those behaviors. Don't default-construct your variants.
You know that=E2=80=99s easier said than done, especially when the compiler=
won=E2=80=99t flag it for you.
> I don't think that `void` would be appropriate for the nullable type. Whi=
le you can get pointers to void, you can't get void references. It just doe=
sn't behave like a normal type. It would be better to define an explicit, e=
mpty type that would be treated by users as the empty type for variants.
No references is exactly the point. Why should the user be able to get a re=
ference the the nonexistent content of a disengaged variant?
> Also, I really prefer the current design, where there is a distinction be=
tween being empty and being in a state that the user considers empty. The f=
ormer can only happen as a consequence of a copy/move failure; it exists so=
lely for error handling as an unfortunate consequence of the C++ language.
I=E2=80=99ve not been involved in the variant debates, but this sounds craz=
y. I assume operator bool maps both empty states to false?
>> This is the work-in-progress in a Google Doc: Variant <https://docs.goog=
le.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Ds=
haring> and it is open for comments.
>=20
> The #1 problem with N4542, IMHO, is that it aggregates and idealizes some=
existing implementations without actually prototyping the result.
>=20
> To be fair, there's not much difference between Boost.Variant and N4542. =
The principle differences are the empty-as-error state and C++11/14 feature=
s. In principle, the visitation has been around for quite some time and has=
a lot of user-experience behind it.
>=20
> And it's not like std::any and std::optional didn't do more or less the s=
ame thing. Or std::shared_ptr, for that matter.
That doesn=E2=80=99t mean Boost always gets a free pass, or that those clas=
ses are out of the woods. (You mean experimental::any and experimental::opt=
ional.)
> It's a Boost component being introduced to the standard library.
>=20
> I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper=
laying out arguments and principles for their own sake, not a complete sel=
f-contained proposal going from ancient history up to standardese.
>=20
> That would make things take longer.
One section of N4542, which is the fourth revision in its sequence, is a re=
cord of straw poll votes being taken after the third revision. I think the =
committee should decide on design principles, given solid proposals and arg=
umentation, and then apply those principles to the various new erasure clas=
ses to promote their interoperability. Iterating on big proposals full of l=
ittle details doesn=E2=80=99t seem to be working.
--=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/.
--Apple-Mail=_2CB011A4-511D-4101-A388-9E88AD1B678E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9321, at 8:15 PM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D"">Sort it based on what, exactly?</div><=
/blockquote><div><br class=3D""></div><div>Implementation-defined. Probably=
, the collation of mangled type-names.</div><br class=3D""><blockquote type=
=3D"cite" class=3D""><div class=3D""><div style=3D"font-family: Helvetica; =
font-size: 12px; font-style: normal; font-variant: normal; font-weight: nor=
mal; letter-spacing: normal; line-height: normal; orphans: auto; text-align=
: start; text-indent: 0px; text-transform: none; white-space: normal; widow=
s: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D"">Per=
sonally, I don't see why it's so important to have a few default behaviors =
based on the ordering in the list. If you're going to have default construc=
tion that constructs one element, then the user should be able to control w=
hat that default element is. Who cares what other languages do; this is C++=
, and C++ has its own unique needs.<br class=3D""></div></div></blockquote>=
<div><br class=3D""></div><div>Sure, but specifying that by the order of th=
e list is a bit impure. For tagging types, we have tag types.</div><br clas=
s=3D""><blockquote type=3D"cite" class=3D""><div style=3D"font-family: Helv=
etica; font-size: 12px; font-style: normal; font-variant: normal; font-weig=
ht: normal; letter-spacing: normal; line-height: normal; orphans: auto; tex=
t-align: start; text-indent: 0px; text-transform: none; white-space: normal=
; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=
=3D"">If you don't want behavior based on the order of items in the list, f=
ine; don't use those behaviors. Don't default-construct your variants.<br c=
lass=3D""></div></blockquote><div><br class=3D""></div><div>You know that=
=E2=80=99s easier said than done, especially when the compiler won=E2=80=99=
t flag it for you.</div><br class=3D""><blockquote type=3D"cite" class=3D""=
><blockquote class=3D"gmail_quote" style=3D"font-family: Helvetica; font-si=
ze: 12px; font-style: normal; font-variant: normal; font-weight: normal; le=
tter-spacing: normal; line-height: normal; orphans: auto; text-align: start=
; text-indent: 0px; text-transform: none; white-space: normal; widows: auto=
; word-spacing: 0px; -webkit-text-stroke-width: 0px; 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 style=3D"word-wrap: break-word;=
" class=3D""><div class=3D""><div class=3D""></div></div></div></blockquote=
><div style=3D"font-family: Helvetica; font-size: 12px; font-style: normal;=
font-variant: normal; font-weight: normal; letter-spacing: normal; line-he=
ight: normal; orphans: auto; text-align: start; text-indent: 0px; text-tran=
sform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-=
text-stroke-width: 0px;" class=3D"">I don't think that `void` would be appr=
opriate for the nullable type. While you can get pointers to void, you can'=
t get void references. It just doesn't behave like a normal type. It would =
be better to define an explicit, empty type that would be treated by users =
as the empty type for variants.<br class=3D""></div></blockquote><div><br c=
lass=3D""></div><div>No references is exactly the point. Why should the use=
r be able to get a reference the the nonexistent content of a disengaged va=
riant?</div><br class=3D""><blockquote type=3D"cite" class=3D""><div style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D"">Also, I really prefer the current design, where th=
ere is a distinction between being empty and being in a state that the user=
considers empty. The former can only happen as a consequence of a copy/mov=
e failure; it exists<span class=3D"Apple-converted-space"> </span><i c=
lass=3D"">solely</i><span class=3D"Apple-converted-space"> </span>for =
error handling as an unfortunate consequence of the C++ language.<br class=
=3D""></div></blockquote><div><br class=3D""></div><div>I=E2=80=99ve not be=
en involved in the <font face=3D"Courier" class=3D"">variant</font>&nb=
sp;debates, but this sounds crazy. I assume <font face=3D"Courier" class=3D=
"">operator bool</font> maps both empty states to <font face=3D"Courier" cl=
ass=3D"">false</font>?</div><br class=3D""><blockquote type=3D"cite" class=
=3D""><blockquote class=3D"gmail_quote" style=3D"font-family: Helvetica; fo=
nt-size: 12px; font-style: normal; font-variant: normal; font-weight: norma=
l; letter-spacing: normal; line-height: normal; orphans: auto; text-align: =
start; text-indent: 0px; text-transform: none; white-space: normal; widows:=
auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0=
px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); bo=
rder-left-style: solid; padding-left: 1ex;"><div style=3D"word-wrap: break-=
word;" class=3D""><div class=3D""><blockquote type=3D"cite" class=3D""><div=
class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">This is the work-in=
-progress in a Google Doc: <a href=3D"https://docs.google.com/document=
/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Dsharing" target=
=3D"_blank" rel=3D"nofollow" class=3D"">Variant</a> and it is open for=
comments.</div><div class=3D""></div></div></div></blockquote><div class=
=3D""><br class=3D""></div><div class=3D"">The #1 problem with N4542, IMHO,=
is that it aggregates and idealizes some existing implementations without =
actually prototyping the result.</div></div></div></blockquote><div style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D""><br class=3D"">To be fair, there's not much differ=
ence between Boost.Variant and N4542. The principle differences are the emp=
ty-as-error state and C++11/14 features. In principle, the visitation has b=
een around for quite some time and has a lot of user-experience behind it.<=
br class=3D""><br class=3D"">And it's not like std::any and std::optional d=
idn't do more or less the same thing. Or std::shared_ptr, for that matter.<=
br class=3D""></div></blockquote><div><br class=3D""></div><div>That doesn=
=E2=80=99t mean Boost always gets a free pass, or that those classes are ou=
t of the woods. (You mean <font face=3D"Courier" class=3D"">experimental::a=
ny</font> and <font face=3D"Courier" class=3D"">experimental::optional</fon=
t>.)</div><br class=3D""><blockquote type=3D"cite" class=3D""><div style=3D=
"font-family: Helvetica; font-size: 12px; font-style: normal; font-variant:=
normal; font-weight: normal; letter-spacing: normal; line-height: normal; =
orphans: auto; text-align: start; text-indent: 0px; text-transform: none; w=
hite-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-wi=
dth: 0px;" class=3D"">It's a Boost component being introduced to the standa=
rd library.<br class=3D""><br class=3D""></div><blockquote class=3D"gmail_q=
uote" style=3D"font-family: Helvetica; font-size: 12px; font-style: normal;=
font-variant: normal; font-weight: normal; letter-spacing: normal; line-he=
ight: normal; orphans: auto; text-align: start; text-indent: 0px; text-tran=
sform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-=
text-stroke-width: 0px; margin: 0px 0px 0px 0.8ex; border-left-width: 1px; =
border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-le=
ft: 1ex;"><div style=3D"word-wrap: break-word;" class=3D""><div class=3D"">=
<div class=3D"">I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer =
to see a paper laying out arguments and principles for their own sake, not =
a complete self-contained proposal going from ancient history up to standar=
dese.<br class=3D""></div></div></div></blockquote><div style=3D"font-famil=
y: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; fo=
nt-weight: normal; letter-spacing: normal; line-height: normal; orphans: au=
to; text-align: start; text-indent: 0px; text-transform: none; white-space:=
normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" =
class=3D""><br class=3D"">That would make things take<span class=3D"Apple-c=
onverted-space"> </span><i class=3D"">longer</i>.<br class=3D""></div>=
</blockquote><br class=3D""></div><div>One section of N4542, which is the f=
ourth revision in its sequence, is a record of straw poll votes being taken=
after the third revision. I think the committee should decide on design pr=
inciples, given solid proposals and argumentation, and then apply those pri=
nciples to the various new erasure classes to promote their interoperabilit=
y. Iterating on big proposals full of little details doesn=E2=80=99t seem t=
o be working.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_2CB011A4-511D-4101-A388-9E88AD1B678E--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 21 Sep 2015 20:50:57 +0800
Raw View
--Apple-Mail=_E3E12BB8-F31E-4283-A4F8-BAD2EC70F418
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9321, at 8:40 PM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> Personally, I don't like numeric indexing either, but I also never unders=
tood why the committee allowed numeric indexing of tuples. The way I see it=
, they're equally wrong, but if we're going to have one, we should have the=
other for orthogonality's sake.
A tuple is an ordered sequence of values. It cannot be discriminated by typ=
es, because repetition of a type isn=E2=80=99t special. (Such discriminatio=
n has now been added, but it only works for special cases.)
A variant has a value of one of several types. As Michael noted, indexing t=
he types fundamentally changes their meaning. Now you don=E2=80=99t have a =
variant of one of several types, but one of several type-index pairs. The a=
mount of information in the variant value has been measurably increased.
> Actually, it explicitly allows it; multiple repeated types are distinct s=
tates. But it says that, for such a template, using a type-based getter alw=
ays fails; you have to access the element based on the index. Same goes for=
emplacement construction.
Oh, that=E2=80=99s broken. I don=E2=80=99t want a template that breaks with=
repeated types. Perhaps I want one template that works with repeated types=
, and another that diagnoses them, and allows type-based discrimination. Bu=
t repeated types don=E2=80=99t sound too appetizing at all, especially if t=
hey=E2=80=99re not simply deduplicated.
> A variant in the "null" state has a value, just like a pointer in the "nu=
ll" state has a value. So even conceptually, `void` is the wrong thing.
The variant has a value, but it does not hold a value. A variant in the spe=
cial error state you mentioned also has a value.
> `void` is not something we should try to use. It's something we should tr=
y to avoid using.
That doesn=E2=80=99t make sense. It=E2=80=99s not an anti-pattern; it=E2=80=
=99s a pure and valid concept. It represents something you can=E2=80=99t us=
e. It represents =E2=80=9Cnothing there.=E2=80=9D
--=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/.
--Apple-Mail=_E3E12BB8-F31E-4283-A4F8-BAD2EC70F418
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9321, at 8:40 PM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D"">Personally, I don't like numeric index=
ing either, but I also never understood why the committee allowed numeric i=
ndexing of tuples. The way I see it, they're equally wrong, but if we're go=
ing to have one, we should have the other for orthogonality's sake.</div></=
blockquote><div><br class=3D""></div><div>A tuple is an ordered sequence of=
values. It cannot be discriminated by types, because repetition of a type =
isn=E2=80=99t special. (Such discrimination has now been added, but it only=
works for special cases.)</div><div><br class=3D""></div><div>A variant ha=
s a value of one of several types. As Michael noted, indexing the types fun=
damentally changes their meaning. Now you don=E2=80=99t have a variant of o=
ne of several types, but one of several type-index pairs. The amount of inf=
ormation in the <font face=3D"Courier" class=3D"">variant</font> value has =
been measurably increased.</div><br class=3D""><blockquote type=3D"cite" cl=
ass=3D""><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wr=
ap:break-word" class=3D""><div class=3D""><div class=3D""></div></div></div=
></blockquote><div class=3D"">Actually, it explicitly allows it; multiple r=
epeated types are distinct states. But it says that, for such a template, u=
sing a type-based getter always fails; you have to access the element based=
on the index. Same goes for emplacement construction.<br class=3D""></div>=
</blockquote><div><br class=3D""></div><div>Oh, that=E2=80=99s broken. I do=
n=E2=80=99t want a template that breaks with repeated types. Perhaps I want=
one template that works with repeated types, and another that diagnoses th=
em, and allows type-based discrimination. But repeated types don=E2=80=99t =
sound too appetizing at all, especially if they=E2=80=99re not simply dedup=
licated.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div clas=
s=3D"">A variant in the "null" state has a value, just like a pointer in th=
e "null" state has a value. So even conceptually, `void` is the wrong thing=
..<br class=3D""></div></blockquote><div><br class=3D""></div><div>The <font=
face=3D"Courier" class=3D"">variant</font> <i class=3D"">has</i> a value, =
but it does not <i class=3D"">hold</i> a value. A variant in the speci=
al error state you mentioned also has a value.</div><br class=3D""><blockqu=
ote type=3D"cite" class=3D""><div class=3D"">`void` is not something we sho=
uld try to use. It's something we should try to <i class=3D"">avoid</i> usi=
ng.</div></blockquote><br class=3D""></div><div>That doesn=E2=80=99t make s=
ense. It=E2=80=99s not an anti-pattern; it=E2=80=99s a pure and valid conce=
pt. It represents something you can=E2=80=99t use. It represents =E2=80=9Cn=
othing there.=E2=80=9D</div><br class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_E3E12BB8-F31E-4283-A4F8-BAD2EC70F418--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Mon, 21 Sep 2015 14:58:16 +0100
Raw View
Hi,
In case anyone missed it, I wrote up a lot of my thoughts about variant
in a blog post a couple of months ago:
https://www.justsoftwaresolutions.co.uk/cplusplus/standardizing-variant.html
I posted an implementation on bitbucket:
https://bitbucket.org/anthonyw/variant
I strongly dislike the undefined-behaviour on empty property of the
N4542 variant. If we're going to allow an empty state it should have
defined behaviour.
Not allowing an empty state requires that you can always construct an
object of a type from the list, or you double-buffer. Both of these have
costs.
constexpr compatibility comes at a cost. My implementation is
constexpr-compatible, but it can end up bigger than a
non-constexpr-compatible implementation due to alignment issues.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Patrice Roy <patricer@gmail.com>
Date: Mon, 21 Sep 2015 11:58:14 -0400
Raw View
--001a113f8bf0f3348e052043f21c
Content-Type: text/plain; charset=UTF-8
Just a note, as it's an old issue and might not be a design goal for
variant, but if we seek to replace discriminated unions with this, not
supporting more than one occurrence of a given type might be a problem due
to type aliases in real code. If we forbid types that occur more than once
in a standard variant, then some union-based code in applications such as
low-level sockets stuff will not be part of the std::variant use-case.
Of course, maybe it's what we want, but it's something to think about.
Cheers!
2015-09-21 9:58 GMT-04:00 Anthony Williams <anthony.ajw@gmail.com>:
> Hi,
>
> In case anyone missed it, I wrote up a lot of my thoughts about variant
> in a blog post a couple of months ago:
>
>
> https://www.justsoftwaresolutions.co.uk/cplusplus/standardizing-variant.html
>
> I posted an implementation on bitbucket:
>
> https://bitbucket.org/anthonyw/variant
>
> I strongly dislike the undefined-behaviour on empty property of the
> N4542 variant. If we're going to allow an empty state it should have
> defined behaviour.
>
> Not allowing an empty state requires that you can always construct an
> object of a type from the list, or you double-buffer. Both of these have
> costs.
>
> constexpr compatibility comes at a cost. My implementation is
> constexpr-compatible, but it can end up bigger than a
> non-constexpr-compatible implementation due to alignment issues.
>
> Anthony
> --
> Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
> just::thread C++11 thread library http://www.stdthread.co.uk
> Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113f8bf0f3348e052043f21c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Just a note, as it's an old issue and might not b=
e a design goal for variant, but if we seek to replace discriminated unions=
with this, not supporting more than one occurrence of a given type might b=
e a problem due to type aliases in real code. If we forbid types that occur=
more than once in a standard variant, then some union-based code in applic=
ations such as low-level sockets stuff will not be part of the std::variant=
use-case.<br><br>Of course, maybe it's what we want, but it's some=
thing to think about.<br><br></div>Cheers!<br></div><div class=3D"gmail_ext=
ra"><br><div class=3D"gmail_quote">2015-09-21 9:58 GMT-04:00 Anthony Willia=
ms <span dir=3D"ltr"><<a href=3D"mailto:anthony.ajw@gmail.com" target=3D=
"_blank">anthony.ajw@gmail.com</a>></span>:<br><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex">Hi,<br>
<br>
In case anyone missed it, I wrote up a lot of my thoughts about variant<br>
in a blog post a couple of months ago:<br>
<br>
<a href=3D"https://www.justsoftwaresolutions.co.uk/cplusplus/standardizing-=
variant.html" rel=3D"noreferrer" target=3D"_blank">https://www.justsoftware=
solutions.co.uk/cplusplus/standardizing-variant.html</a><br>
<br>
I posted an implementation on bitbucket:<br>
<br>
<a href=3D"https://bitbucket.org/anthonyw/variant" rel=3D"noreferrer" targe=
t=3D"_blank">https://bitbucket.org/anthonyw/variant</a><br>
<br>
I strongly dislike the undefined-behaviour on empty property of the<br>
N4542 variant. If we're going to allow an empty state it should have<br=
>
defined behaviour.<br>
<br>
Not allowing an empty state requires that you can always construct an<br>
object of a type from the list, or you double-buffer. Both of these have<br=
>
costs.<br>
<br>
constexpr compatibility comes at a cost. My implementation is<br>
constexpr-compatible, but it can end up bigger than a<br>
non-constexpr-compatible implementation due to alignment issues.<br>
<span class=3D"HOEnZb"><font color=3D"#888888"><br>
Anthony<br>
--<br>
Author of C++ Concurrency in Action=C2=A0 =C2=A0 =C2=A0<a href=3D"http://ww=
w.stdthread.co.uk/book/" rel=3D"noreferrer" target=3D"_blank">http://www.st=
dthread.co.uk/book/</a><br>
just::thread C++11 thread library=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0<a href=3D"http://www.stdthread.co.uk" rel=3D"noreferrer" target=3D"_=
blank">http://www.stdthread.co.uk</a><br>
Just Software Solutions Ltd=C2=A0 =C2=A0 =C2=A0 =C2=A0<a href=3D"http://www=
..justsoftwaresolutions.co.uk" rel=3D"noreferrer" target=3D"_blank">http://w=
ww.justsoftwaresolutions.co.uk</a><br>
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976<br=
>
</font></span><div class=3D"HOEnZb"><div class=3D"h5"><br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--001a113f8bf0f3348e052043f21c--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Mon, 21 Sep 2015 17:03:49 +0100
Raw View
On 21/09/15 16:58, Patrice Roy wrote:
> Just a note, as it's an old issue and might not be a design goal for
> variant, but if we seek to replace discriminated unions with this, not
> supporting more than one occurrence of a given type might be a problem
> due to type aliases in real code. If we forbid types that occur more
> than once in a standard variant, then some union-based code in
> applications such as low-level sockets stuff will not be part of the
> std::variant use-case.
>
> Of course, maybe it's what we want, but it's something to think about.
Agreed. The basic example that's been passed around is
variant<size_t,unsigned long>, but people also raised the issue with
variant usage for low-level interfaces.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 21 Sep 2015 09:58:01 -0700
Raw View
--001a11c18226c56ddd052044c8d9
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcypark@gmail.com> wrote:
> Hello, I've been working on an alternative variant proposal. It's still
> very rough at this point but I've captured the big questions I wanted to
> answer, and would appreciate feedback from the community.
>
This is a bit divorced from the actual implementation issues. I'm also not
sure I follow the purpose of the relationship drawn to pointers/inheritance
in the proposal. I recommend cutting this. A variant is just a sum type and
deals with a closed set of types. Relating to inheritance is unnecessary
and confusing, and arguably inaccurate.
On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcypark@gmail.com> wrote:
> The following are some of the principles the design is based on:
> (1) *union* is not a good starting point for a discriminated union. I
> believe better starting points are:
> From C++: *enum* as a special case where each member is a unit
> type, and
> *class inheritance* where an abstract base class is a
> discriminated union of its derived classes.
> From other languages: Sum types from Haskell and ML or enum from
> Rust.
>
It needs to be a union for minimal constexpr-ness.
On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcypark@gmail.com> wrote:
> (2) The *order* of the types specified in *variant<Ts...>* should not
> change its behavior.
>
Why? Ordering actually ends up being important in usage, and so does
indexing by value. Without that, it's really difficult to do basic things,
such as portable serialization. If users want some kind of common ordering
for some reason, then they can wrap it themselves. Similarly, if
implementations can do that internally based on intrinsics or something to
reduce instantiations, they can, but at the top level they need some kind
of consistent and portable discriminator, otherwise you are missing some
important use cases.
On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcypark@gmail.com> wrote:
> * Default construction should not construct the first type. (2)
>
Why? If there there is default construction at all, it should be consistent
across library implementations for portability, and the rules should be
simple.
On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcypark@gmail.com> wrote:
> * There is no special treatment for the null state. (3)
>
I will personally always be against a null state because the rationale
doesn't hold up. I think it's a huge mistake that people believe it is
needed. If types involved are noexcept-movable, there is no need for the
empty state (this is already acknowledged). If there is a type involved
that has a move constructor that can through, we can just require that the
user has a noexcept-default-constructible type as one of the specified
fields, and we can simply default-construct that internally if a move
throws an exception. If neither of these is the case, then the variant can
simply be not movable (these requirements are not difficult to meet). This
avoids weakening the type's invariants with an unnecessary null state and
gives the user more control.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c18226c56ddd052044c8d9
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 M=
on, Sep 21, 2015 at 1:56 AM, Michael Park <span dir=3D"ltr"><<a href=3D"=
mailto:mcypark@gmail.com" target=3D"_blank">mcypark@gmail.com</a>></span=
> wrote:<br><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-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr">Hello, I've been working =
on an alternative variant proposal. It's still very rough at this point=
but I've captured the big questions I wanted to answer, and would appr=
eciate feedback from the community.</div></blockquote><div><br></div><div>T=
his is a bit divorced from the actual implementation issues. I'm also n=
ot sure I follow the purpose of the relationship drawn to pointers/inherita=
nce in the proposal. I recommend cutting this. A variant is just a sum type=
and deals with a closed set of types. Relating to inheritance is unnecessa=
ry and confusing, and arguably inaccurate.</div><div><br></div><div><br></d=
iv><div>On Mon, Sep 21, 2015 at 1:56 AM, Michael Park=C2=A0<span dir=3D"ltr=
"><<a href=3D"mailto:mcypark@gmail.com" target=3D"_blank">mcypark@gmail.=
com</a>></span>=C2=A0wrote:=C2=A0=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"><div dir=
=3D"ltr"><div>The following are some of the principles the design is based =
on:</div><div>=C2=A0 (1)=C2=A0<font face=3D"courier new, monospace"><b>unio=
n</b></font>=C2=A0is not a good starting point for a discriminated union. I=
believe better starting points are:</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0F=
rom C++:=C2=A0<font face=3D"courier new, monospace"><b>enum</b></font>=C2=
=A0as a special case where each member is a unit type, and</div><div>=C2=A0=
=C2=A0 =C2=A0 =C2=A0<b>class inheritance</b>=C2=A0where an abstract base c=
lass is a discriminated union of its derived classes.</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0From other languages: Sum types from Haskell and ML or=C2=
=A0<font face=3D"courier new, monospace" style=3D"font-weight:bold">enum</f=
ont><font face=3D"arial, sans-serif"><b>=C2=A0</b>from Rust.</font></div></=
div></blockquote><div><br></div><div>It needs to be a union for minimal con=
stexpr-ness.</div><div><br></div><div>On Mon, Sep 21, 2015 at 1:56 AM, Mich=
ael Park=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:mcypark@gmail.com" ta=
rget=3D"_blank">mcypark@gmail.com</a>></span>=C2=A0wrote:=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div>=C2=A0 (2) The=C2=A0<b>order</b>=C2=A0o=
f the types specified in=C2=A0<font face=3D"courier new, monospace"><b>vari=
ant<Ts...></b></font>=C2=A0should not change its behavior.</div></div=
></blockquote><div><br></div><div>Why? Ordering actually ends up being impo=
rtant in usage, and so does indexing by value. Without that, it's reall=
y difficult to do basic things, such as portable serialization. If users wa=
nt some kind of common ordering for some reason, then they can wrap it them=
selves. Similarly, if implementations can do that internally based on intri=
nsics or something to reduce instantiations, they can, but at the top level=
they need some kind of consistent and portable discriminator, otherwise yo=
u are missing some important use cases.</div><div><br></div><div>On Mon, Se=
p 21, 2015 at 1:56 AM, Michael Park=C2=A0<span dir=3D"ltr"><<a href=3D"m=
ailto:mcypark@gmail.com" target=3D"_blank">mcypark@gmail.com</a>></span>=
=C2=A0wrote:=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,20=
4);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>=C2=A0 *=
Default construction should not construct the first type. (2)</div></div><=
/blockquote><div><br></div><div>Why? If there there is default construction=
at all, it should be consistent across library implementations for portabi=
lity, and the rules should be simple.</div><div><br></div><div>On Mon, Sep =
21, 2015 at 1:56 AM, Michael Park=C2=A0<span dir=3D"ltr"><<a href=3D"mai=
lto:mcypark@gmail.com" target=3D"_blank">mcypark@gmail.com</a>></span>=
=C2=A0wrote:=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>=C2=A0 * The=
re is no special treatment for the null state. (3)</div></div></blockquote>=
<div><br></div><div>I will personally always be against a null state becaus=
e the rationale doesn't hold up. I think it's a huge mistake that p=
eople believe it is needed. If types involved are noexcept-movable, there i=
s no need for the empty state (this is already acknowledged). If there is a=
type involved that has a move constructor that can through, we can just re=
quire that the user has a noexcept-default-constructible type as one of the=
specified fields, and we can simply default-construct that internally if a=
move throws an exception. If neither of these is the case, then the varian=
t can simply be not movable (these requirements are not difficult to meet).=
This avoids weakening the type's invariants with an unnecessary null s=
tate and gives the user more control.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c18226c56ddd052044c8d9--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 21 Sep 2015 10:06:00 -0700 (PDT)
Raw View
------=_Part_804_1896502443.1442855160388
Content-Type: multipart/alternative;
boundary="----=_Part_805_349866955.1442855160395"
------=_Part_805_349866955.1442855160395
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 8:51:04 AM UTC-4, David Krauss wrote:
>
> On 2015=E2=80=9309=E2=80=9321, at 8:40 PM, Nicol Bolas <jmck...@gmail.com=
<javascript:>>=20
> wrote:
>
> Personally, I don't like numeric indexing either, but I also never=20
> understood why the committee allowed numeric indexing of tuples. The way =
I=20
> see it, they're equally wrong, but if we're going to have one, we should=
=20
> have the other for orthogonality's sake.
>
>
> A tuple is an ordered sequence of values. It cannot be discriminated by=
=20
> types, because repetition of a type isn=E2=80=99t special. (Such discrimi=
nation has=20
> now been added, but it only works for special cases.)
>
> A variant has a value of one of several types. As Michael noted, indexing=
=20
> the types fundamentally changes their meaning. Now you don=E2=80=99t have=
a variant=20
> of one of several types, but one of several type-index pairs. The amount =
of=20
> information in the variant value has been measurably increased.
>
Conceptually, perhaps. But not in any way that actually takes up storage or=
=20
anything. So it doesn't impact the quality of the variant's implementation.
And if someone can find a use for it, more power to them. Especially if it=
=20
allows them to put different typedefs in the same variant.
The only thing it does for the implementation is prevent it from=20
re-ordering the elements in the variant.
We should not create an arbitrary restriction on a C++ type, or choose not=
=20
to implement genuinely useful functionality, based on some external concept=
=20
of what a `variant` ought to be.
> Actually, it explicitly allows it; multiple repeated types are distinct=
=20
> states. But it says that, for such a template, using a type-based getter=
=20
> always fails; you have to access the element based on the index. Same goe=
s=20
> for emplacement construction.
>
>
> Oh, that=E2=80=99s broken. I don=E2=80=99t want a template that breaks wi=
th repeated=20
> types. Perhaps I want one template that works with repeated types, and=20
> another that diagnoses them, and allows type-based discrimination. But=20
> repeated types don=E2=80=99t sound too appetizing at all, especially if t=
hey=E2=80=99re not=20
> simply deduplicated.
>
Well, if duplicate types are "deduplicated", then what's the point in=20
allowing them at all? If you're not going to allow duplicate types to be=20
considered separate states, then there's no point in allowing them at all.
> A variant in the "null" state has a value, just like a pointer in the=20
> "null" state has a value. So even conceptually, `void` is the wrong thing=
..
>
>
> The variant *has* a value, but it does not *hold* a value. A variant in=
=20
> the special error state you mentioned also has a value.
>
=20
But the variant *does* hold a value. It holds a value that means "nothing=
=20
meaningful." That value, like "null" for pointers, is a value. It has all=
=20
of the rights, powers, and functions of a real C++ value. You can create=20
them, copy them, pass them around, and store them.
You can't do any of that with `void`.
> `void` is not something we should try to use. It's something we should tr=
y=20
> to *avoid* using.
>
>
> That doesn=E2=80=99t make sense. It=E2=80=99s not an anti-pattern; it=E2=
=80=99s a pure and valid=20
> concept. It represents something you can=E2=80=99t use. It represents =E2=
=80=9Cnothing=20
> there.=E2=80=9D
>
I can create a value of type `nullptr_t`. I can create a value of type=20
`nullopt_t`. I can create references to both of those.
I cannot create a value of type `void`. It is not a valid C++ type. It=20
lacks orthogonality with the behavior of C++ types. That lack of=20
orthogonality is what makes using it like this an anti-pattern.
Consider a simple copy visitor class for a variant. All it does is return a=
=20
copy of the value:
struct CopyVisitor
{
template<T> auto operator()(const T &t) const {return t;}
};
Well, you can't actually do that with `void`, can you? You can't get a=20
reference to `void`, and you can't return a copy of `void`. So you would=20
need to create a special overload *solely* to handle this case:
struct CopyVisitorAndVoid
{
template<T> auto operator()(const T &t) const {return t;}
void operator()() {return;}
};
What's more, CopyVisitor could have been a lambda; CopyVisitorAndVoid=20
cannot.
Template code has to deal with this kind of "what if T is void" question a=
=20
lot. The best answer: stop using `void`.
--=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_805_349866955.1442855160395
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 8:51:04 AM UTC-4, David Krauss wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"=
><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=9321, at 8:40=
PM, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" gdf-obfuscat=
ed-mailto=3D"qw99zNu6BQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
;javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;;return true;">jmck...@gmail.com</a>> wrote:</div><br><div>Personally, =
I don't like numeric indexing either, but I also never understood why t=
he committee allowed numeric indexing of tuples. The way I see it, they'=
;re equally wrong, but if we're going to have one, we should have the o=
ther for orthogonality's sake.</div></blockquote><div><br></div><div>A =
tuple is an ordered sequence of values. It cannot be discriminated by types=
, because repetition of a type isn=E2=80=99t special. (Such discrimination =
has now been added, but it only works for special cases.)</div><div><br></d=
iv><div>A variant has a value of one of several types. As Michael noted, in=
dexing the types fundamentally changes their meaning. Now you don=E2=80=99t=
have a variant of one of several types, but one of several type-index pair=
s. The amount of information in the <font face=3D"Courier">variant</font> v=
alue has been measurably increased.</div></div></div></blockquote><div><br>=
Conceptually, perhaps. But not in any way that actually takes up storage or=
anything. So it doesn't impact the quality of the variant's implem=
entation.<br><br>And if someone can find a use for it, more power to them. =
Especially if it allows them to put different typedefs in the same variant.=
<br><br>The only thing it does for the implementation is prevent it from re=
-ordering the elements in the variant.<br><br>We should not create an arbit=
rary restriction on a C++ type, or choose not to implement genuinely useful=
functionality, based on some external concept of what a `variant` ought to=
be.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"wo=
rd-wrap:break-word"><div><blockquote type=3D"cite"><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div style=3D"word-wrap:break-word"><div><div></div></div><=
/div></blockquote><div>Actually, it explicitly allows it; multiple repeated=
types are distinct states. But it says that, for such a template, using a =
type-based getter always fails; you have to access the element based on the=
index. Same goes for emplacement construction.<br></div></blockquote><div>=
<br></div><div>Oh, that=E2=80=99s broken. I don=E2=80=99t want a template t=
hat breaks with repeated types. Perhaps I want one template that works with=
repeated types, and another that diagnoses them, and allows type-based dis=
crimination. But repeated types don=E2=80=99t sound too appetizing at all, =
especially if they=E2=80=99re not simply deduplicated.</div></div></div></b=
lockquote><div><br>Well, if duplicate types are "deduplicated", t=
hen what's the point in allowing them at all? If you're not going t=
o allow duplicate types to be considered separate states, then there's =
no point in allowing them at all.<br></div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div style=3D"word-wrap:break-word"><div><blockquote type=3D"c=
ite"><div>A variant in the "null" state has a value, just like a =
pointer in the "null" state has a value. So even conceptually, `v=
oid` is the wrong thing.<br></div></blockquote><div><br></div><div>The <fon=
t face=3D"Courier">variant</font> <i>has</i> a value, but it does not <i>ho=
ld</i>=C2=A0a value. A variant in the special error state you mentioned als=
o has a value.</div></div></div></blockquote><div>=C2=A0</div><div>But the =
variant <i>does</i> hold a value. It holds a value that means "nothing=
meaningful." That value, like "null" for pointers, is a val=
ue. It has all of the rights, powers, and functions of a real C++ value. Yo=
u can create them, copy them, pass them around, and store them.<br><br>You =
can't do any of that with `void`.<br><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><br><blockquo=
te type=3D"cite"><div>`void` is not something we should try to use. It'=
s something we should try to <i>avoid</i> using.</div></blockquote><br></di=
v><div>That doesn=E2=80=99t make sense. It=E2=80=99s not an anti-pattern; i=
t=E2=80=99s a pure and valid concept. It represents something you can=E2=80=
=99t use. It represents =E2=80=9Cnothing there.=E2=80=9D<br></div></div></b=
lockquote><div><br>I can create a value of type `nullptr_t`. I can create a=
value of type `nullopt_t`. I can create references to both of those.<br><b=
r>I cannot create a value of type `void`. It is not a valid C++ type. It la=
cks orthogonality with the behavior of C++ types. That lack of orthogonalit=
y is what makes using it like this an anti-pattern.<br><br>Consider a simpl=
e copy visitor class for a variant. All it does is return a copy of the val=
ue:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">s=
truct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #606;" class=3D"styled-by-prettify">CopyVisitor</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">operator</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
()(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">t</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">{</span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> t<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">;}</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">};</span></div></code></d=
iv><br>Well, you can't actually do that with `void`, can you? You can&#=
39;t get a reference to `void`, and you can't return a copy of `void`. =
So you would need to create a special overload <i>solely</i> to handle this=
case:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250=
, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-=
width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">CopyVisito=
rAndVoid</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></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 </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">template</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">></span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">operator</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">()(</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">t</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> t</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 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">()()</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">return</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;}</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">};</span></div></code></div><br>What's more, CopyVisitor cou=
ld have been a lambda; CopyVisitorAndVoid cannot.<br><br>Template code has =
to deal with this kind of "what if T is void" question a lot. The=
best answer: stop using `void`.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_805_349866955.1442855160395--
------=_Part_804_1896502443.1442855160388--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 21 Sep 2015 10:30:51 -0700 (PDT)
Raw View
------=_Part_1531_1144262582.1442856651724
Content-Type: multipart/alternative;
boundary="----=_Part_1532_691884765.1442856651725"
------=_Part_1532_691884765.1442856651725
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 8:40:51 AM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9321, at 8:15 PM, Nicol Bolas <jmck...@gmail.com=
<javascript:>>=20
> wrote:
>
> Sort it based on what, exactly?
>
>
> Implementation-defined. Probably, the collation of mangled type-names.
>
If it's implementation-dependent... what does it matter if it sorts them or=
=20
not?
I think you're trying to get `variant<int, float>` and `variant<float,=20
int>` to be the same. Well, C++ doesn't allow that; different template=20
instantiations will be different types, period. Even if you sort the=20
parameter pack and derive from a base class instantiated on the sorted=20
parameter list, the two sister types in the hierarchy are still not the=20
same type.
You could try to make them seem like the same type by allowing copy and=20
move construction/assignment from one type to a matching type, as well as=
=20
provide implicit conversions from one to the other. But `std::is_same` will=
=20
never return true for them.
I just don't see the point of making variant implementations do all that=20
work, when you don't really get equal types out of it. You only get an=20
illusion of equality.
=20
> Personally, I don't see why it's so important to have a few default=20
> behaviors based on the ordering in the list. If you're going to have=20
> default construction that constructs one element, then the user should be=
=20
> able to control what that default element is. Who cares what other=20
> languages do; this is C++, and C++ has its own unique needs.
>
>
> Sure, but specifying that by the order of the list is a bit impure. For=
=20
> tagging types, we have tag types.
>
I don't know what you mean by "tag types". If you're talking about things=
=20
like iterator categories, those are way too intrusive to use, and can only=
=20
be used by certain special functions.
Also, what does it matter if it is "impure"? How do you even define=20
"purity" here?
> I don't think that `void` would be appropriate for the nullable type.=20
> While you can get pointers to void, you can't get void references. It jus=
t=20
> doesn't behave like a normal type. It would be better to define an=20
> explicit, empty type that would be treated by users as the empty type for=
=20
> variants.
>
>
> No references is exactly the point. Why should the user be able to get a=
=20
> reference the the nonexistent content of a disengaged variant?
>
Orthogonality. I covered why this is important in a previous post.=20
> Also, I really prefer the current design, where there is a distinction=20
> between being empty and being in a state that the user considers empty. T=
he=20
> former can only happen as a consequence of a copy/move failure; it exists=
=20
> *solely* for error handling as an unfortunate consequence of the C++=20
> language.
>
>
> I=E2=80=99ve not been involved in the variant debates, but this sounds cr=
azy. I=20
> assume operator bool maps both empty states to false?
>
The current proposal only has one "empty" state, and it can only be caused=
=20
by copy/move failure. The *user* can decide if a particular state=20
conceptually represents "being empty", but that's up to the user. The=20
current proposal does not provide some specific type that, when put into=20
the type list, is universally considered being empty.
> This is the work-in-progress in a Google Doc: Variant=20
>> <https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6Y=
iJHDhp48/edit?usp=3Dsharing> and=20
>> it is open for comments.
>>
>>
>> The #1 problem with N4542, IMHO, is that it aggregates and idealizes som=
e=20
>> existing implementations without actually prototyping the result.
>>
>
> To be fair, there's not much difference between Boost.Variant and N4542.=
=20
> The principle differences are the empty-as-error state and C++11/14=20
> features. In principle, the visitation has been around for quite some tim=
e=20
> and has a lot of user-experience behind it.
>
> And it's not like std::any and std::optional didn't do more or less the=
=20
> same thing. Or std::shared_ptr, for that matter.
>
>
> That doesn=E2=80=99t mean Boost always gets a free pass, or that those cl=
asses are=20
> out of the woods. (You mean experimental::any and experimental::optional.=
)
>
No, it does not. But it does explain why they started with the design they=
=20
did, and why they don't strictly *need* an established implementation of=20
exactly N4542 in order to proceed.
The standards committee likes to standardizes existing (C++) practice.=20
Boost.Any, Boost.Optional, and Boost.Variant are all existing practice.
What you're talking about is not.
> It's a Boost component being introduced to the standard library.
>
> I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper=
laying out=20
>> arguments and principles for their own sake, not a complete self-contain=
ed=20
>> proposal going from ancient history up to standardese.
>>
>
> That would make things take *longer*.
>
>
> One section of N4542, which is the fourth revision in its sequence, is a=
=20
> record of straw poll votes being taken after the third revision. I think=
=20
> the committee should decide on design principles, given solid proposals a=
nd=20
> argumentation, and then apply those principles to the various new erasure=
=20
> classes to promote their interoperability.
>
That's one way to look at it. Another way to look at it is to recognize=20
that the "various new erausre classes" are not all "erasure classes".=20
Neither `variant` nor `optional` is specifically about type erasure, so=20
your nomenclature is debatable. They represent distinct concepts with=20
minimally-overlapping use cases, and thus they do not strictly need to have=
=20
a unified interface.
=20
> Iterating on big proposals full of little details doesn=E2=80=99t seem to=
be=20
> working.
>
Everyone judges "working" based on whether it leads to the result they want=
..
You want `variant`, `any`, and `optional` to all share the same interface.=
=20
You want them all to be considered specializations of functional=20
programming "sum types" and therefore conceptually interchangeable to some=
=20
degree. Therefore, a process that doesn't lead to that is not "working" to=
=20
you.
I want `variant` to not be required to have an empty state (and if it=20
absolutely must, it must be orthogonal with all other types. IE: not=20
`void`). And thus, any process that leads to a `variant` without those=20
properties is not "working" to me.
We have `any` and `optional` in TS's. Given the construction and reception=
=20
of N4542, we will likely have `variant`, as well as probably all three in=
=20
C++17. These classes will fill good and useful niches in the C++ language.
That's the only objective definition of "working". So objectively speaking,=
=20
the process seems to be working.
--=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_1532_691884765.1442856651725
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, September 21, 2015 at 8:40:51 AM UTC-4, David K=
rauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word=
-wrap:break-word"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=930=
9=E2=80=9321, at 8:15 PM, Nicol Bolas <<a href=3D"javascript:" target=3D=
"_blank" gdf-obfuscated-mailto=3D"OARY70y6BQAJ" rel=3D"nofollow" onmousedow=
n=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=
=3D'javascript:';return true;">jmck...@gmail.com</a>> wrote:</di=
v><br><div>Sort it based on what, exactly?</div></blockquote><div><br></div=
><div>Implementation-defined. Probably, the collation of mangled type-names=
..<br></div></div></div></blockquote><div><br>If it's implementation-dep=
endent... what does it matter if it sorts them or not?<br><br>I think you&#=
39;re trying to get `variant<int, float>` and `variant<float, int&=
gt;` to be the same. Well, C++ doesn't allow that; different template i=
nstantiations will be different types, period. Even if you sort the paramet=
er pack and derive from a base class instantiated on the sorted parameter l=
ist, the two sister types in the hierarchy are still not the same type.<br>=
<br>You could try to make them seem like the same type by allowing copy and=
move construction/assignment from one type to a matching type, as well as =
provide implicit conversions from one to the other. But `std::is_same` will=
never return true for them.<br><br>I just don't see the point of makin=
g variant implementations do all that work, when you don't really get e=
qual types out of it. You only get an illusion of equality.<br>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-=
word"><div><div></div><blockquote type=3D"cite"><div><div style=3D"font-fam=
ily:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-wei=
ght:normal;letter-spacing:normal;line-height:normal;text-align:start;text-i=
ndent:0px;text-transform:none;white-space:normal;word-spacing:0px">Personal=
ly, I don't see why it's so important to have a few default behavio=
rs based on the ordering in the list. If you're going to have default c=
onstruction that constructs one element, then the user should be able to co=
ntrol what that default element is. Who cares what other languages do; this=
is C++, and C++ has its own unique needs.<br></div></div></blockquote><div=
><br></div><div>Sure, but specifying that by the order of the list is a bit=
impure. For tagging types, we have tag types.<br></div></div></div></block=
quote><div><br>I don't know what you mean by "tag types". If =
you're talking about things like iterator categories, those are way too=
intrusive to use, and can only be used by certain special functions.<br><b=
r>Also, what does it matter if it is "impure"? How do you even de=
fine "purity" here?<br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div style=3D"word-wrap:break-word"><div><blockquote type=3D"cite"=
><blockquote class=3D"gmail_quote" style=3D"font-family:Helvetica;font-size=
:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spaci=
ng:normal;line-height:normal;text-align:start;text-indent:0px;text-transfor=
m:none;white-space:normal;word-spacing:0px;margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div style=3D"word-wrap:break-word"><div><div></div></div>=
</div></blockquote><div style=3D"font-family:Helvetica;font-size:12px;font-=
style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;l=
ine-height:normal;text-align:start;text-indent:0px;text-transform:none;whit=
e-space:normal;word-spacing:0px">I don't think that `void` would be app=
ropriate for the nullable type. While you can get pointers to void, you can=
't get void references. It just doesn't behave like a normal type. =
It would be better to define an explicit, empty type that would be treated =
by users as the empty type for variants.<br></div></blockquote><div><br></d=
iv><div>No references is exactly the point. Why should the user be able to =
get a reference the the nonexistent content of a disengaged variant?<br></d=
iv></div></div></blockquote><div><br>Orthogonality. I covered why this is i=
mportant in a previous post. <br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div style=3D"word-wrap:break-word"><div><div></div><blockquote ty=
pe=3D"cite"><div style=3D"font-family:Helvetica;font-size:12px;font-style:n=
ormal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-hei=
ght:normal;text-align:start;text-indent:0px;text-transform:none;white-space=
:normal;word-spacing:0px">Also, I really prefer the current design, where t=
here is a distinction between being empty and being in a state that the use=
r considers empty. The former can only happen as a consequence of a copy/mo=
ve failure; it exists<span>=C2=A0</span><i>solely</i><span>=C2=A0</span>for=
error handling as an unfortunate consequence of the C++ language.<br></div=
></blockquote><div><br></div><div>I=E2=80=99ve not been involved in the=C2=
=A0<font face=3D"Courier">variant</font>=C2=A0debates, but this sounds craz=
y. I assume <font face=3D"Courier">operator bool</font> maps both empty sta=
tes to <font face=3D"Courier">false</font>?<br></div></div></div></blockquo=
te><div><br>The current proposal only has one "empty" state, and =
it can only be caused by copy/move failure. The <i>user</i> can decide if a=
particular state conceptually represents "being empty", but that=
's up to the user. The current proposal does not provide some specific =
type that, when put into the type list, is universally considered being emp=
ty.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"wor=
d-wrap:break-word"><div><div></div><blockquote type=3D"cite"><blockquote cl=
ass=3D"gmail_quote" style=3D"font-family:Helvetica;font-size:12px;font-styl=
e:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-=
height:normal;text-align:start;text-indent:0px;text-transform:none;white-sp=
ace:normal;word-spacing:0px;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 style=3D"word-wrap:break-word"><div><blockquote type=3D"cite"><div><=
div dir=3D"ltr"><div>This is the work-in-progress in a Google Doc:=C2=A0<a =
href=3D"https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75d=
Sq6YiJHDhp48/edit?usp=3Dsharing" rel=3D"nofollow" target=3D"_blank" onmouse=
down=3D"this.href=3D'https://docs.google.com/document/d/12PPuGwSel38YzX=
adItleMynl77nl75dSq6YiJHDhp48/edit?usp\75sharing';return true;" onclick=
=3D"this.href=3D'https://docs.google.com/document/d/12PPuGwSel38YzXadIt=
leMynl77nl75dSq6YiJHDhp48/edit?usp\75sharing';return true;">Variant</a>=
=C2=A0and it is open for comments.</div><div></div></div></div></blockquote=
><div><br></div><div>The #1 problem with N4542, IMHO, is that it aggregates=
and idealizes some existing implementations without actually prototyping t=
he result.</div></div></div></blockquote><div style=3D"font-family:Helvetic=
a;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;l=
etter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;te=
xt-transform:none;white-space:normal;word-spacing:0px"><br>To be fair, ther=
e's not much difference between Boost.Variant and N4542. The principle =
differences are the empty-as-error state and C++11/14 features. In principl=
e, the visitation has been around for quite some time and has a lot of user=
-experience behind it.<br><br>And it's not like std::any and std::optio=
nal didn't do more or less the same thing. Or std::shared_ptr, for that=
matter.<br></div></blockquote><div><br></div><div>That doesn=E2=80=99t mea=
n Boost always gets a free pass, or that those classes are out of the woods=
.. (You mean <font face=3D"Courier">experimental::any</font> and <font face=
=3D"Courier">experimental::optional</font>.)</div></div></div></blockquote>=
<div><br>No, it does not. But it does explain why they started with the des=
ign they did, and why they don't strictly <i>need</i> an established im=
plementation of exactly N4542 in order to proceed.<br><br>The standards com=
mittee likes to standardizes existing (C++) practice. Boost.Any, Boost.Opti=
onal, and Boost.Variant are all existing practice.<br><br>What you're t=
alking about is not.<br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div style=3D"word-wrap:break-word"><div><blockquote type=3D"cite"><div sty=
le=3D"font-family:Helvetica;font-size:12px;font-style:normal;font-variant:n=
ormal;font-weight:normal;letter-spacing:normal;line-height:normal;text-alig=
n:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing=
:0px">It's a Boost component being introduced to the standard library.<=
br><br></div><blockquote class=3D"gmail_quote" style=3D"font-family:Helveti=
ca;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;=
letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px;margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div style=3D"word-wrap:break-word"><div><div>=
I can=E2=80=99t speak for everyone, but I=E2=80=99d prefer to see a paper l=
aying out arguments and principles for their own sake, not a complete self-=
contained proposal going from ancient history up to standardese.<br></div><=
/div></div></blockquote><div style=3D"font-family:Helvetica;font-size:12px;=
font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:nor=
mal;line-height:normal;text-align:start;text-indent:0px;text-transform:none=
;white-space:normal;word-spacing:0px"><br>That would make things take<span>=
=C2=A0</span><i>longer</i>.<br></div></blockquote><br></div><div>One sectio=
n of N4542, which is the fourth revision in its sequence, is a record of st=
raw poll votes being taken after the third revision. I think the committee =
should decide on design principles, given solid proposals and argumentation=
, and then apply those principles to the various new erasure classes to pro=
mote their interoperability.</div></div></blockquote><div><br>That's on=
e way to look at it. Another way to look at it is to recognize that the &qu=
ot;various new erausre classes" are not all "erasure classes"=
;. Neither `variant` nor `optional` is specifically about type erasure, so =
your nomenclature is debatable. They represent distinct concepts with minim=
ally-overlapping use cases, and thus they do not strictly need to have a un=
ified interface.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div style=3D"word-wrap:break-word"><div>Iterating on big proposals full =
of little details doesn=E2=80=99t seem to be working.</div></div></blockquo=
te><div><br>Everyone judges "working" based on whether it leads t=
o the result they want.<br><br>You want `variant`, `any`, and `optional` to=
all share the same interface. You want them all to be considered specializ=
ations of functional programming "sum types" and therefore concep=
tually interchangeable to some degree. Therefore, a process that doesn'=
t lead to that is not "working" to you.<br><br>I want `variant` t=
o not be required to have an empty state (and if it absolutely must, it mus=
t be orthogonal with all other types. IE: not `void`). And thus, any proces=
s that leads to a `variant` without those properties is not "working&q=
uot; to me.<br><br>We have `any` and `optional` in TS's. Given the cons=
truction and reception of N4542, we will likely have `variant`, as well as =
probably all three in C++17. These classes will fill good and useful niches=
in the C++ language.<br><br>That's the only objective definition of &q=
uot;working". So objectively speaking, the process seems to be working=
..<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1532_691884765.1442856651725--
------=_Part_1531_1144262582.1442856651724--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 21 Sep 2015 14:07:16 -0400
Raw View
--001a11c3cffa6cac6c052045c0a2
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 21, 2015 at 4:56 AM, Michael Park <mcypark@gmail.com> wrote:
> Hello, I've been working on an alternative variant proposal. It's still
> very rough at this point but I've captured the big questions I wanted to
> answer, and would appreciate feedback from the community.
>
> The following are some of the principles the design is based on:
> (1) *union* is not a good starting point for a discriminated union. I
> believe better starting points are:
> From C++: *enum* as a special case where each member is a unit
> type, and
> *class inheritance* where an abstract base class is a
> discriminated union of its derived classes.
> From other languages: Sum types from Haskell and ML or enum from
> Rust.
> (2) The *order* of the types specified in *variant<Ts...>* should not
> change its behavior.
> (3) The API should be minimal, useful, and consistent.
>
> The following are few design decisions that fall out from the above
> principles:
> * The visitation interface is a *type_switch* expression which looks
> similar to a regular *switch* statement,
> as well as *match* expressions from functional languages. (1)
> * Default construction should not construct the first type. (2)
> * The members should be discriminated by type rather than the index.
> (2), (3)
> (i.e. *variant<int, string, int>* behaves equivalently to *variant<int,
> string>*)
> * There is no special treatment for the null state. (3)
>
> This is the work-in-progress in a Google Doc: Variant
> <https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=sharing> and
> it is open for comments.
>
> I'm in Seattle attending CppCon this week. Please reach out if you're also
> here and would like to provide feedback and/or have further design
> discussions!
>
> Thanks,
>
> MPark.
>
I find it a little bit hard to follow your proposal - you often list
various potential strategies, one of which is your chosen strategy. But it
isn't always clear which is the one you chose (or maybe you are choosing
more than one). Or possibly I'm just bad at reading and need to re-read
it. But giving your chosen strategy a Green title or something similar
might help.
I _think_ you are suggesting:
- "empty" state exists
- "empty" state is used for construction
- "empty" state is used for failed assignment(?)
- variant<int, string> == variant<string, int> (as much as possible)
- variant<int, string, int> == variant<int, string>
If it has an empty state, what's with the null_t stuff? I think that's
where I'm most confused.
If I use null_t as one of the types (ie variant<int, string, null_t>), and
assignment throws, does the variant become empty, or get the value of a
null_t?
If I use int (ie noexcept default constructible) as one of the types ie
variant<int, Foo, Bar> and assignment throws, does it become empty, or get
the value of int(0)? (ie is null_t more special than int?)
For default variant construction you mention:
"Assuming that default constructability is desirable, it would be
desirable for any variant to be default constructible. "
The logic is sound, but I'm not sure about the assumption. For some
classes (or some coding styles and guidelines), default construction is NOT
desirable. If I've decided (in spite of the annoyances) to make Foo not
default constructible and Bar not default constructible, I probably don't
want variant<Foo, Bar> to be default constructible.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c3cffa6cac6c052045c0a2
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 21, 2015 at 4:56 AM, Michael Park <span dir=3D"ltr"><<a =
href=3D"mailto:mcypark@gmail.com" target=3D"_blank">mcypark@gmail.com</a>&g=
t;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div =
dir=3D"ltr">Hello, I've been working on an alternative variant proposal=
.. It's still very rough at this point but I've captured the big que=
stions I wanted to answer, and would appreciate feedback from the community=
..<div><br></div><div>The following are some of the principles the design is=
based on:</div><div>=C2=A0 (1)=C2=A0<font face=3D"courier new, monospace">=
<b>union</b></font>=C2=A0is not a good starting point for a discriminated u=
nion. I believe better starting points are:</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0From C++:=C2=A0<font face=3D"courier new, monospace"><b>enum</b></fon=
t>=C2=A0as a special case where each member is a unit type, and</div><div>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0<b>class inheritance</b>=C2=A0where an abstract =
base class is a discriminated union of its derived classes.</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0From other languages: Sum types from Haskell and ML=
or=C2=A0<font style=3D"font-weight:bold" face=3D"courier new, monospace">e=
num</font><font face=3D"arial, sans-serif"><b>=C2=A0</b>from Rust.</font></=
div><div>=C2=A0 (2) The=C2=A0<b>order</b>=C2=A0of the types specified in=C2=
=A0<font face=3D"courier new, monospace"><b>variant<Ts...></b></font>=
=C2=A0should not change its behavior.</div><div>=C2=A0 (3) The API should b=
e minimal, useful, and consistent.</div><div><br></div><div>The following a=
re few design decisions that fall out from the above principles:</div><div>=
=C2=A0 * The visitation interface is a=C2=A0<b>type_switch</b>=C2=A0express=
ion which looks similar to a regular=C2=A0<b>switch</b>=C2=A0statement,</di=
v><div>=C2=A0 =C2=A0 as well as=C2=A0<b>match</b>=C2=A0expressions from fun=
ctional languages. (1)</div><div>=C2=A0 * Default construction should not c=
onstruct the first type. (2)</div><div>=C2=A0 * The members should be discr=
iminated by type rather than the index. (2), (3)</div><div>=C2=A0 =C2=A0 =
=C2=A0(i.e.=C2=A0<font face=3D"courier new, monospace"><b>variant<int, s=
tring, int></b></font>=C2=A0behaves equivalently to=C2=A0<b style=3D"fon=
t-family:"courier new",monospace">variant<int, string></b><=
font face=3D"arial, sans-serif">)</font></div><div>=C2=A0 * There is no spe=
cial treatment for the null state. (3)</div><div><br></div><div>This is the=
work-in-progress in a Google Doc:=C2=A0<a href=3D"https://docs.google.com/=
document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=3Dsharing"=
target=3D"_blank">Variant</a>=C2=A0and it is open for comments.</div><div>=
<br></div><div>I'm in Seattle attending CppCon this week. Please reach =
out if you're also here and would like to provide feedback and/or have =
further design discussions!</div><div><div><br></div><div>Thanks,</div><div=
><br></div><div>MPark.</div></div></div></blockquote><div><br><br></div><di=
v>I find it a little bit hard to follow your proposal - you often list vari=
ous potential strategies, one of which is your chosen strategy.=C2=A0 But i=
t isn't always clear which is the one you chose (or maybe you are choos=
ing more than one).=C2=A0 Or possibly I'm just bad at reading and need =
to re-read it.=C2=A0 But giving your chosen strategy a Green title or somet=
hing similar might help. <br><br></div><div>I _think_ you are suggesting:<b=
r><br></div><div>- "empty" state exists<br></div><div>- "emp=
ty" state is used for construction<br></div><div>- "empty" s=
tate is used for failed assignment(?)<br></div><div>- variant<int, strin=
g> =3D=3D variant<string, int> (as much as possible)<br></div><div=
>- variant<int, string, int> =3D=3D variant<int, string><br><br=
></div><div>If it has an empty state, what's with the null_t stuff? I t=
hink that's where I'm most confused.<br></div><div>If I use null_t =
as one of the types (ie variant<int, string, null_t>), and assignment=
throws, does the variant become empty, or get the value of a null_t?<br></=
div><div>If I use int (ie noexcept default constructible) as one of the typ=
es ie variant<int, Foo, Bar> and assignment throws, does it become em=
pty, or get the value of int(0)? (ie is null_t more special than int?)<br><=
br></div><div>For default variant construction you mention:<br><br><span st=
yle=3D"font-size:14.6667px;font-family:Arial;color:rgb(0,0,0);background-co=
lor:transparent;font-weight:400;font-style:normal;font-variant:normal;text-=
decoration:none;vertical-align:baseline" id=3D"docs-internal-guid-97b63cac-=
f109-5308-75e2-b0d4fd282a69">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 &qu=
ot;Assuming that default constructability is desirable, it would be desirab=
le for </span><span style=3D"font-size:14.6667px;font-family:Arial;color:rg=
b(0,0,0);background-color:transparent;font-weight:700;font-style:normal;fon=
t-variant:normal;text-decoration:none;vertical-align:baseline">any</span><s=
pan style=3D"font-size:14.6667px;font-family:Arial;color:rgb(0,0,0);backgro=
und-color:transparent;font-weight:400;font-style:normal;font-variant:normal=
;text-decoration:none;vertical-align:baseline"> </span><span style=3D"font-=
size:14.6667px;font-family:Consolas;color:rgb(0,0,0);background-color:trans=
parent;font-weight:400;font-style:normal;font-variant:normal;text-decoratio=
n:none;vertical-align:baseline">variant</span><span style=3D"font-size:14.6=
667px;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-=
weight:400;font-style:normal;font-variant:normal;text-decoration:none;verti=
cal-align:baseline"> to be default constructible. "</span><br></div></=
div><br></div><div class=3D"gmail_extra">The logic is sound, but I'm no=
t sure about the assumption.=C2=A0 For some classes (or some coding styles =
and guidelines), default construction is NOT desirable.=C2=A0 If I've d=
ecided (in spite of the annoyances) to make Foo not default constructible a=
nd Bar not default constructible, I probably don't want variant<Foo,=
Bar> to be default constructible.<br><br></div><div class=3D"gmail_extr=
a">Tony<br></div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_e=
xtra"><br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3cffa6cac6c052045c0a2--
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 22 Sep 2015 08:19:21 +0800
Raw View
--Apple-Mail=_BAEFA9A3-FF26-499B-9EAC-D14A492C84F2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9322, at 1:06 AM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> Conceptually, perhaps. But not in any way that actually takes up storage =
or anything. So it doesn't impact the quality of the variant's implementati=
on.
More states at runtime implies more code to handle the states.
> And if someone can find a use for it, more power to them. Especially if i=
t allows them to put different typedefs in the same variant.
>=20
> The only thing it does for the implementation is prevent it from re-order=
ing the elements in the variant.
No, it affects the semantics of having different typedefs in there. Why sho=
uldn=E2=80=99t it be allowed to retrieve a value given a typedef to its typ=
e? C++ (and C) don=E2=80=99t work by discriminating typedefs from the alias=
ed type; you=E2=80=99re inventing a need.
Also, users are pressured to use indexing if it=E2=80=99s more robust, whic=
h comes down to either magic numbers or naming the states after types.
> We should not create an arbitrary restriction on a C++ type, or choose no=
t to implement genuinely useful functionality, based on some external conce=
pt of what a `variant` ought to be.
We shouldn=E2=80=99t create a type with functionality defined by the arbitr=
ary internal details of a prototype implementation.
>=20
> Well, if duplicate types are "deduplicated", then what's the point in all=
owing them at all? If you're not going to allow duplicate types to be consi=
dered separate states, then there's no point in allowing them at all.
Indeed. If allowed, they make the template more tolerant, so you don=E2=80=
=99t need to worry that it will reject the type-list or fail to retrieve a =
value of a duplicate type.
> But the variant does hold a value. It holds a value that means "nothing m=
eaningful." That value, like "null" for pointers, is a value. It has all of=
the rights, powers, and functions of a real C++ value. You can create them=
, copy them, pass them around, and store them.
>=20
> You can't do any of that with `void`.
There is a wrapper object and there is an object inside the wrapper object.=
Two different things.
A disengaged wrapper holds no object at all. Whether that wrapper value is =
copyable or not depends on the wrapper. But you cannot get a reference to t=
he internal object; this is what distinguishes engagement from disengagemen=
t.
Copying a disengaged wrapper does not imply copying a void value.
> I can create a value of type `nullptr_t`. I can create a value of type `n=
ullopt_t`. I can create references to both of those.
>=20
> I cannot create a value of type `void`. It is not a valid C++ type. It la=
cks orthogonality with the behavior of C++ types. That lack of orthogonalit=
y is what makes using it like this an anti-pattern.
That=E2=80=99s the opposite of what orthogonality means. Your argument goes=
in the direction that disengagement is something that ordinary types shoul=
d accomplish. Should the user be able to define whether a given type implem=
ents engagement or disengagement? Perhaps exception types are all disengage=
d states?
> Consider a simple copy visitor class for a variant. All it does is return=
a copy of the value:
>=20
> struct CopyVisitor
> {
> template<T> auto operator()(const T &t) const {return t;}
> };
>=20
> Well, you can't actually do that with `void`, can you? You can't get a re=
ference to `void`, and you can't return a copy of `void`. So you would need=
to create a special overload solely to handle this case:
Attempting to get something that doesn=E2=80=99t exist is signaled by throw=
ing an exception. This looks like a job for bad_variant_access.
What can you do with null_t that=E2=80=99s generically uniform with things =
that represent actual values? Once you=E2=80=99ve returned null_t by value,=
now what? Will every user remember to support null_t in their visitor temp=
lates when it=E2=80=99s never mentioned in the type-list?
Use if(v) to avoid visiting disengaged wrappers.
> Template code has to deal with this kind of "what if T is void" question =
a lot. The best answer: stop using `void`.
=E2=80=9CReplace void with another type to represent no value =E2=80=94 but=
which has a value=E2=80=9D does not follow.
std::function and [boost|experimental]::any both use typeid(void) to expres=
s their disengaged states.
> On 2015=E2=80=9309=E2=80=9322, at 1:30 AM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> If it's implementation-dependent... what does it matter if it sorts them =
or not?
The sort order should be implementation-defined; the fact of sorting should=
not be.
> I think you're trying to get `variant<int, float>` and `variant<float, in=
t>` to be the same. Well, C++ doesn't allow that; different template instan=
tiations will be different types, period.
Not for alias templates. They implement many-to-one mapping just fine.
> I don't know what you mean by "tag types". If you're talking about things=
like iterator categories, those are way too intrusive to use, and can only=
be used by certain special functions.
>=20
> Also, what does it matter if it is "impure"? How do you even define "puri=
ty" here?
I find this:
std::variant< std::default_initial< int >, std::string > >
to be more expressive than this:
std::variant< int, std::string >
Defaulting to the first type is just weird and obtuse. It seems like an imp=
lementation detail being foisted on the user.
If default_initial< int > is defined to be an incomplete type (undefined cl=
ass), then there=E2=80=99s no inconsistency that variant wouldn=E2=80=99t b=
e able to hold it.
>=20
> Orthogonality. I covered why this is important in a previous post.=20
You=E2=80=99re arguing for non-orthogonality, or uniformity, that a disenga=
ged wrapper is really still holding something.
> The current proposal only has one "empty" state, and it can only be cause=
d by copy/move failure. The user can decide if a particular state conceptua=
lly represents "being empty", but that's up to the user. The current propos=
al does not provide some specific type that, when put into the type list, i=
s universally considered being empty.
N4542 has a function valid(), but no means to invalidate a variant.
So, it=E2=80=99s up to each user to define their own =E2=80=9Cdisengaged va=
lue=E2=80=9D type. That=E2=80=99s great for interoperability.
Also, std::monostate is described by N4542 as the type of an =E2=80=9Cempty=
state.=E2=80=9D I=E2=80=99m not reviewing in detail its exact semantics, j=
ust now.
> The standards committee likes to standardizes existing (C++) practice. Bo=
ost.Any, Boost.Optional, and Boost.Variant are all existing practice.
>=20
> What you're talking about is not.
Eggs.Variant has a disengaged default state expressed by typeid(void), and =
no distinction of duplicates. It=E2=80=99s even cited by N4542.
> That's one way to look at it. Another way to look at it is to recognize t=
hat the "various new erausre classes" are not all "erasure classes". Neithe=
r `variant` nor `optional` is specifically about type erasure, so your nome=
nclature is debatable. They represent distinct concepts with minimally-over=
lapping use cases, and thus they do not strictly need to have a unified int=
erface.
variant and any have more than minimal overlap, however you want to classif=
y them.
> Iterating on big proposals full of little details doesn=E2=80=99t seem to=
be working.
>=20
> Everyone judges "working" based on whether it leads to the result they wa=
nt.
I=E2=80=99m only judging by the number of iterations and the process used t=
o get from #3 to #4. Also, N4542 still contains enough errors and inconsist=
encies that #5 seems assured.
> We have `any` and `optional` in TS's. Given the construction and receptio=
n of N4542, we will likely have `variant`, as well as probably all three in=
C++17. These classes will fill good and useful niches in the C++ language.
>=20
> That's the only objective definition of "working". So objectively speakin=
g, the process seems to be working.
The objective definition of =E2=80=9Cwork=E2=80=9D is =E2=80=9Cpeople apply=
ing the necessary effort to achieve an end.=E2=80=9D The process is working=
because we are. I meant to disparage review sessions resulting in design-b=
y-committee, not anything broader.
TS=E2=80=99es exist to promote rapid, intense review, to speed the process =
=E2=80=94 whatever it really is. Debate over what remains on the table is c=
ommon in this sort of situation. It can take a large majority to change the=
direction of a draft specification, but Eggs.Variant seems to be getting m=
ore support than Boost.Variant, and no draft has even been accepted yet. No=
w we have another prototype as well.
--=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/.
--Apple-Mail=_BAEFA9A3-FF26-499B-9EAC-D14A492C84F2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9322, at 1:06 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D""><div class=3D"">Conceptually, perhaps.=
But not in any way that actually takes up storage or anything. So it doesn=
't impact the quality of the variant's implementation.<br class=3D""></div>=
</div></blockquote><div><br class=3D""></div><div>More states at runtime im=
plies more code to handle the states.</div><br class=3D""><blockquote type=
=3D"cite" class=3D""><div class=3D""><div class=3D"">And if someone can fin=
d a use for it, more power to them. Especially if it allows them to put dif=
ferent typedefs in the same variant.<br class=3D""><br class=3D"">The only =
thing it does for the implementation is prevent it from re-ordering the ele=
ments in the variant.<br class=3D""></div></div></blockquote><div><br class=
=3D""></div><div>No, it affects the semantics of having different typedefs =
in there. Why shouldn=E2=80=99t it be allowed to retrieve a value given a t=
ypedef to its type? C++ (and C) don=E2=80=99t work by discriminating typede=
fs from the aliased type; you=E2=80=99re inventing a need.</div><div><br cl=
ass=3D""></div><div>Also, users are pressured to use indexing if it=E2=80=
=99s more robust, which comes down to either magic numbers or naming the st=
ates after types.</div><br class=3D""><blockquote type=3D"cite" class=3D"">=
<div class=3D""><div class=3D"">We should not create an arbitrary restricti=
on on a C++ type, or choose not to implement genuinely useful functionality=
, based on some external concept of what a `variant` ought to be.<br class=
=3D""></div></div></blockquote><div><br class=3D""></div><div>We shouldn=E2=
=80=99t create a type with functionality defined by the arbitrary internal =
details of a prototype implementation.</div><br class=3D""><blockquote type=
=3D"cite" class=3D""><div class=3D""><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div style=3D"word-wrap:break-word" class=3D""><div class=3D""><bloc=
kquote type=3D"cite" class=3D""><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v style=3D"word-wrap:break-word" class=3D""><div class=3D""><div class=3D""=
></div></div></div></blockquote></blockquote></div></div></blockquote><div =
class=3D"">Well, if duplicate types are "deduplicated", then what's the poi=
nt in allowing them at all? If you're not going to allow duplicate types to=
be considered separate states, then there's no point in allowing them at a=
ll.<br class=3D""></div></div></blockquote><div><br class=3D""></div><div>I=
ndeed. If allowed, they make the template more tolerant, so you don=E2=80=
=99t need to worry that it will reject the type-list or fail to retrieve a =
value of a duplicate type.</div><br class=3D""><blockquote type=3D"cite" cl=
ass=3D""><div class=3D"">But the variant <i class=3D"">does</i> hold a valu=
e. It holds a value that means "nothing meaningful." That value, like "null=
" for pointers, is a value. It has all of the rights, powers, and functions=
of a real C++ value. You can create them, copy them, pass them around, and=
store them.<br class=3D""><br class=3D"">You can't do any of that with `vo=
id`.</div></blockquote><div><br class=3D""></div><div>There is a wrapper ob=
ject and there is an object inside the wrapper object. Two different things=
..</div><div><br class=3D""></div><div>A disengaged wrapper holds no object =
at all. Whether that wrapper value is copyable or not depends on the wrappe=
r. But you cannot get a reference to the internal object; this is what dist=
inguishes engagement from disengagement.</div><div><br class=3D""></div><di=
v>Copying a disengaged wrapper does not imply copying a <font face=3D"Couri=
er" class=3D"">void</font> value.</div><br class=3D""><blockquote type=3D"c=
ite" class=3D""><div class=3D""><div class=3D"">I can create a value of typ=
e `nullptr_t`. I can create a value of type `nullopt_t`. I can create refer=
ences to both of those.<br class=3D""><br class=3D"">I cannot create a valu=
e of type `void`. It is not a valid C++ type. It lacks orthogonality with t=
he behavior of C++ types. That lack of orthogonality is what makes using it=
like this an anti-pattern.<br class=3D""></div></div></blockquote><div><br=
class=3D""></div><div>That=E2=80=99s the opposite of what orthogonality me=
ans. Your argument goes in the direction that disengagement is something th=
at ordinary types should accomplish. Should the user be able to define whet=
her a given type implements engagement or disengagement? Perhaps exception =
types are all disengaged states?</div><br class=3D""><blockquote type=3D"ci=
te" class=3D""><div class=3D""><div class=3D"">Consider a simple copy visit=
or class for a variant. All it does is return a copy of the value:<br class=
=3D""><br class=3D""><div class=3D"prettyprint" style=3D"background-color: =
rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; =
border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">struct</span> <span s=
tyle=3D"color: #606;" class=3D"styled-by-prettify">CopyVisitor</span><br cl=
ass=3D""><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<br class=3D""> <span style=3D"color: #008;" class=3D"styled-by-prett=
ify">template</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y"><</span>T<span style=3D"color: #660;" class=3D"styled-by-prettify">&g=
t;</span> <span style=3D"color: #008;" class=3D"styled-by-prettify">auto</s=
pan> <span style=3D"color: #008;" class=3D"styled-by-prettify">operator</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">()(</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">const</span> T <span =
style=3D"color: #660;" class=3D"styled-by-prettify">&</span>t<span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span> <span style=3D"col=
or: #008;" class=3D"styled-by-prettify">const</span> <span style=3D"color: =
#660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">return</span> t<span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;}</span><br class=3D""><span style=3D"color: #660=
;" class=3D"styled-by-prettify">};</span></code></div><br class=3D"">Well, =
you can't actually do that with `void`, can you? You can't get a reference =
to `void`, and you can't return a copy of `void`. So you would need to crea=
te a special overload <i class=3D"">solely</i> to handle this case:<br clas=
s=3D""></div></div></blockquote><div><br class=3D""></div><div>Attempting t=
o get something that doesn=E2=80=99t exist is signaled by throwing an excep=
tion. This looks like a job for <font face=3D"Courier" class=3D"">bad_varia=
nt_access</font>.</div><div><br class=3D""></div><div>What can you do with =
<font face=3D"Courier" class=3D"">null_t</font> that=E2=80=99s generically =
uniform with things that represent actual values? Once you=E2=80=99ve retur=
ned <font face=3D"Courier" class=3D"">null_t</font> by value, now what? Wil=
l every user remember to support <font face=3D"Courier" class=3D"">null_t</=
font> in their visitor templates when it=E2=80=99s never mentioned in the t=
ype-list?</div><div><br class=3D""></div><div>Use <font face=3D"Courier" cl=
ass=3D"">if(v)</font> to avoid visiting disengaged wrappers.</div><br class=
=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div class=3D"">=
Template code has to deal with this kind of "what if T is void" question a =
lot. The best answer: stop using `void`.</div></div></blockquote><br class=
=3D""></div><div>=E2=80=9CReplace <font face=3D"Courier" class=3D"">void</f=
ont> with another type to represent no value =E2=80=94 but which has a valu=
e=E2=80=9D does not follow.</div><br class=3D""><div class=3D""><font face=
=3D"Courier" class=3D"">std::function</font> and <font face=3D"Courier" cla=
ss=3D"">[boost|experimental]::any</font> both use <font face=3D"Courier" cl=
ass=3D"">typeid(void)</font> to express their disengaged states.</div><div =
class=3D""><br class=3D""></div><div class=3D""><br class=3D""></div><div c=
lass=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=
=80=9309=E2=80=9322, at 1:30 AM, Nicol Bolas <<a href=3D"mailto:jmckesso=
n@gmail.com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=
=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">=
<div class=3D"">If it's implementation-dependent... what does it matter if =
it sorts them or not?<br class=3D""></div></div></div></blockquote><div cla=
ss=3D""><br class=3D""></div><div class=3D"">The sort order should be imple=
mentation-defined; the fact of sorting should not be.</div><br class=3D""><=
blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=
=3D""><div class=3D"">I think you're trying to get `variant<int, float&g=
t;` and `variant<float, int>` to be the same. Well, C++ doesn't allow=
that; different template instantiations will be different types, period. <=
/div></div></div></blockquote><div class=3D""><br class=3D""></div><div cla=
ss=3D"">Not for alias templates. They implement many-to-one mapping just fi=
ne.</div><div class=3D""><br class=3D""></div><blockquote type=3D"cite" cla=
ss=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">I don't=
know what you mean by "tag types". If you're talking about things like ite=
rator categories, those are way too intrusive to use, and can only be used =
by certain special functions.<br class=3D""><br class=3D"">Also, what does =
it matter if it is "impure"? How do you even define "purity" here?<br class=
=3D""></div></div></div></blockquote><div class=3D""><br class=3D""></div><=
div class=3D"">I find this:</div><div class=3D""><br class=3D""></div><div =
class=3D""><font face=3D"Courier" class=3D"">std::variant< std::default_=
initial< int >, std::string > ></font></div><div class=3D""><br=
class=3D""></div><div class=3D"">to be more expressive than this:</div><di=
v class=3D""><br class=3D""></div><div class=3D""><span style=3D"font-famil=
y: Courier;" class=3D"">std::</span><font face=3D"Courier" class=3D"">varia=
nt< int, std::string ></font></div><div class=3D""><br class=3D""></d=
iv><div class=3D"">Defaulting to the first type is just weird and obtuse. I=
t seems like an implementation detail being foisted on the user.</div><div =
class=3D""><br class=3D""></div><div class=3D"">If <font face=3D"Courier" c=
lass=3D"">default_initial< int ></font> is defined to be an incomplet=
e type (undefined class), then there=E2=80=99s no inconsistency that varian=
t wouldn=E2=80=99t be able to hold it.</div><br class=3D""><blockquote type=
=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-wid=
th: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; p=
adding-left: 1ex;"><div class=3D"" style=3D"word-wrap: break-word;"><div cl=
ass=3D""><blockquote type=3D"cite" class=3D""><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-lef=
t-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;">=
<div class=3D"" style=3D"word-wrap: break-word;"><div class=3D""><div class=
=3D""></div></div></div></blockquote></blockquote></div></div></blockquote>=
<div class=3D"">Orthogonality. I covered why this is important in a previou=
s post. <br class=3D""></div></div></div></blockquote><div class=3D"">=
<br class=3D""></div><div class=3D"">You=E2=80=99re arguing for <i class=3D=
"">non</i>-orthogonality, or uniformity, that a disengaged wrapper is reall=
y still holding something.</div><br class=3D""><blockquote type=3D"cite" cl=
ass=3D""><div class=3D""><div dir=3D"ltr" class=3D""><blockquote class=3D"g=
mail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-width: 1px; bor=
der-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left:=
1ex;"><div class=3D"" style=3D"word-wrap: break-word;"><div class=3D""><di=
v class=3D""></div></div></div></blockquote><div class=3D"">The current pro=
posal only has one "empty" state, and it can only be caused by copy/move fa=
ilure. The <i class=3D"">user</i> can decide if a particular stat=
e conceptually represents "being empty", but that's up to the user. The cur=
rent proposal does not provide some specific type that, when put into the t=
ype list, is universally considered being empty.<br class=3D""></div></div>=
</div></blockquote><div class=3D""><br class=3D""></div><div class=3D"">N45=
42 has a function <font face=3D"Courier" class=3D"">valid()</font>, but no =
means to invalidate a variant.</div><div class=3D""><br class=3D""></div><d=
iv class=3D"">So, it=E2=80=99s up to each user to define their own =E2=80=
=9Cdisengaged value=E2=80=9D type. That=E2=80=99s great for interoperabilit=
y.</div><div class=3D""><br class=3D""></div><div class=3D"">Also, <font fa=
ce=3D"Courier" class=3D"">std::monostate</font> is described by N4542 as th=
e type of an =E2=80=9Cempty state.=E2=80=9D I=E2=80=99m not reviewing in de=
tail its exact semantics, just now.</div><br class=3D""><blockquote type=3D=
"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><blockquote c=
lass=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; padd=
ing-left: 1ex;"><div class=3D"" style=3D"word-wrap: break-word;"><div class=
=3D""><div class=3D""></div></div></div></blockquote><div class=3D"">The st=
andards committee likes to standardizes existing (C++) practice. Boost.Any,=
Boost.Optional, and Boost.Variant are all existing practice.<br class=3D""=
><br class=3D"">What you're talking about is not.<br class=3D""></div></div=
></div></blockquote><div class=3D""><br class=3D""></div><div class=3D"">Eg=
gs.Variant has a disengaged default state expressed by <font face=3D"Courie=
r" class=3D"">typeid(void)</font>, and no distinction of duplicates. It=E2=
=80=99s even cited by N4542.</div><br class=3D""><blockquote type=3D"cite" =
class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">That=
's one way to look at it. Another way to look at it is to recognize that th=
e "various new erausre classes" are not all "erasure classes". Neither `var=
iant` nor `optional` is specifically about type erasure, so your nomenclatu=
re is debatable. They represent distinct concepts with minimally-overlappin=
g use cases, and thus they do not strictly need to have a unified interface=
..<br class=3D""></div></div></div></blockquote><div class=3D""><br class=3D=
""></div><div class=3D""><font face=3D"Courier" class=3D"">variant</font> a=
nd <font face=3D"Courier" class=3D"">any</font> have more than minimal over=
lap, however you want to classify them.</div><br class=3D""><blockquote typ=
e=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-wi=
dth: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; =
padding-left: 1ex;"><div class=3D"" style=3D"word-wrap: break-word;"><div c=
lass=3D"">Iterating on big proposals full of little details doesn=E2=80=99t=
seem to be working.</div></div></blockquote><div class=3D""><br class=3D""=
>Everyone judges "working" based on whether it leads to the result they wan=
t.<br class=3D""></div></div></div></blockquote><div class=3D""><br class=
=3D""></div><div class=3D"">I=E2=80=99m only judging by the number of itera=
tions and the process used to get from #3 to #4. Also, N4542 still contains=
enough errors and inconsistencies that #5 seems assured.</div><br class=3D=
""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" cl=
ass=3D""><div class=3D"">We have `any` and `optional` in TS's. Given the co=
nstruction and reception of N4542, we will likely have `variant`, as well a=
s probably all three in C++17. These classes will fill good and useful nich=
es in the C++ language.<br class=3D""></div></div></div></blockquote><block=
quote type=3D"cite" class=3D""><br class=3D""></blockquote><blockquote type=
=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class=
=3D"">That's the only objective definition of "working". So objectively spe=
aking, the process seems to be working.<br class=3D""></div></div></div></b=
lockquote></div><div class=3D""><div class=3D""><div dir=3D"ltr" class=3D""=
><div class=3D""><br class=3D""></div><div class=3D"">The objective definit=
ion of =E2=80=9Cwork=E2=80=9D is =E2=80=9Cpeople applying the necessary eff=
ort to achieve an end.=E2=80=9D The process is working because we are. I me=
ant to disparage review sessions resulting in design-by-committee, not anyt=
hing broader.</div><div class=3D""><br class=3D""></div><div class=3D"">TS=
=E2=80=99es exist to promote rapid, intense review, to speed the process =
=E2=80=94 whatever it really is. Debate over what remains on the table is c=
ommon in this sort of situation. It can take a large majority to change the=
direction of a draft specification, but Eggs.Variant seems to be getting m=
ore support than Boost.Variant, and no draft has even been accepted yet. No=
w we have another prototype as well.</div><div class=3D""><br class=3D""></=
div></div></div></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_BAEFA9A3-FF26-499B-9EAC-D14A492C84F2--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Mon, 21 Sep 2015 21:42:46 -0300
Raw View
On 9/21/2015 9:19 PM, David Krauss wrote:
>
>> On 2015=E2=80=9309=E2=80=9322, at 1:06 AM, Nicol Bolas <jmckesson@gmail.=
com
>> <mailto:jmckesson@gmail.com>> wrote:
>>
>> The standards committee likes to standardizes existing (C++) practice.
>> Boost.Any, Boost.Optional, and Boost.Variant are all existing practice.
>>
>> What you're talking about is not.
>
> Eggs.Variant has a disengaged default state expressed by typeid(void),
> and no distinction of duplicates. It=E2=80=99s even cited by N4542.
I'm not sure if I'm readying this correctly, in Eggs.Variant duplicated=20
types are distinct members. Maybe that's what you mean by "no=20
distinction of duplicates", maybe you mean that duplicates are not=20
distinct, I don't know... So to be explicit:
As a discriminated union to replace low-level uses of `union`,=20
Eggs.Variant has to treat `eggs::variant<int, int>` as having two=20
distinct members of type `int`.
I've found this with raw `union`s as both distinct members with the same=20
type, as well as a single member that changes meaning based on the value=20
of the discriminator (yuck). This was also raised as to support generic=20
programing, the discriminator of a discriminated union is meaningful and=20
contributes to its value.
For these reason, functionality is presented both as type based (for=20
when you absolutely know the types you are dealing with and they are=20
guaranteed to be distinct, like `std::string` and `std::vector`) as well=20
as index based (for when you have duplicated distinct types or you just=20
don't know, aliases, generic contexts, etc).
Either approach can be build on top of the other with a lot of syntactic=20
noise but no real performance overhead. I went with supporting=20
duplicated types as distinct members because that's what a `union` does:
union { int x; int y; };
That said, I'd rather use names (meaning!) than either indices or types,=20
raw `union`s still beat my solution there. Using named constants for=20
indices helps some, but introduces another point where things can=20
possiblie go wrong. There's some work going on on tagged types that, if=20
transparently supported, could be promising to close the gap.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 22 Sep 2015 09:25:35 +0800
Raw View
--Apple-Mail=_90205EFC-CBDE-4126-9ECA-E52C350EB722
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9322, at 8:42 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I'm not sure if I'm readying this correctly, in Eggs.Variant duplicated t=
ypes are distinct members. Maybe that's what you mean by "no distinction of=
duplicates", maybe you mean that duplicates are not distinct, I don't know=
.... So to be explicit:
Sorry, I saw =E2=80=9CT shall occur exactly once in Ts...=E2=80=9D and jump=
ed the gun.
> I've found this with raw `union`s as both distinct members with the same =
type, as well as a single member that changes meaning based on the value of=
the discriminator (yuck). This was also raised as to support generic progr=
aming, the discriminator of a discriminated union is meaningful and contrib=
utes to its value.
It sounds like discriminated unions (going back to C) and sum types (in fun=
ctional languages) are different concepts. But, note that discriminated uni=
ons don=E2=80=99t necessarily have a 1:1 mapping between discriminator valu=
es and member names. For a type that represents a FSM (with some variables =
specific to each =E2=80=9Cmodal=E2=80=9D state), I might not even want cons=
ecutive numbering. It makes more sense to have a list of index-type pairs, =
forbidding repeated indexes.
> For these reason, functionality is presented both as type based (for when=
you absolutely know the types you are dealing with and they are guaranteed=
to be distinct, like `std::string` and `std::vector`) as well as index bas=
ed (for when you have duplicated distinct types or you just don't know, ali=
ases, generic contexts, etc).
I prefer an interface that works 100% with definite meaning over one with c=
ontingencies for cases where =E2=80=9Cyou just don=E2=80=99t know.=E2=80=9D
> That said, I'd rather use names (meaning!) than either indices or types, =
raw `union`s still beat my solution there. Using named constants for indice=
s helps some, but introduces another point where things can possiblie go wr=
ong. There's some work going on on tagged types that, if transparently supp=
orted, could be promising to close the gap.
Strong typedefs? Yes, that would be a good solution.
--=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/.
--Apple-Mail=_90205EFC-CBDE-4126-9ECA-E52C350EB722
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9322, at 8:42 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"mai=
lto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:<=
/div><br class=3D"Apple-interchange-newline"><div class=3D"">I'm not sure i=
f I'm readying this correctly, in Eggs.Variant duplicated types are distinc=
t members. Maybe that's what you mean by "no distinction of duplicates", ma=
ybe you mean that duplicates are not distinct, I don't know... So to be exp=
licit:<br class=3D""></div></blockquote><div><br class=3D""></div><div>Sorr=
y, I saw =E2=80=9C<code class=3D"">T</code> shall occur exactly once in <co=
de class=3D"">Ts...<font face=3D"Helvetica" class=3D"">=E2=80=9D and jumped=
the gun.</font></code></div><br class=3D""><blockquote type=3D"cite" class=
=3D""><div class=3D"">I've found this with raw `union`s as both distinct me=
mbers with the same type, as well as a single member that changes meaning b=
ased on the value of the discriminator (yuck). This was also raised as to s=
upport generic programing, the discriminator of a discriminated union is me=
aningful and contributes to its value.<br class=3D""></div></blockquote><di=
v><br class=3D""></div><div>It sounds like discriminated unions (going back=
to C) and sum types (in functional languages) are different concepts. But,=
note that discriminated unions don=E2=80=99t necessarily have a 1:1 mappin=
g between discriminator values and member names. For a type that represents=
a FSM (with some variables specific to each =E2=80=9Cmodal=E2=80=9D state)=
, I might not even want consecutive numbering. It makes more sense to have =
a list of index-type pairs, forbidding repeated indexes.</div><br class=3D"=
"><blockquote type=3D"cite" class=3D""><div class=3D"">For these reason, fu=
nctionality is presented both as type based (for when you absolutely know t=
he types you are dealing with and they are guaranteed to be distinct, like =
`std::string` and `std::vector`) as well as index based (for when you have =
duplicated distinct types or you just don't know, aliases, generic contexts=
, etc).<br class=3D""></div></blockquote><div><br class=3D""></div><div>I p=
refer an interface that works 100% with definite meaning over one with cont=
ingencies for cases where =E2=80=9Cyou just don=E2=80=99t know.=E2=80=9D</d=
iv><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">That=
said, I'd rather use names (meaning!) than either indices or types, raw `u=
nion`s still beat my solution there. Using named constants for indices help=
s some, but introduces another point where things can possiblie go wrong. T=
here's some work going on on tagged types that, if transparently supported,=
could be promising to close the gap.<br class=3D""></div></blockquote><div=
><br class=3D""></div><div>Strong typedefs? Yes, that would be a good solut=
ion.</div></div><br class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_90205EFC-CBDE-4126-9ECA-E52C350EB722--
.
Author: Larry Evans <cppljevans@suddenlink.net>
Date: Mon, 21 Sep 2015 20:43:59 -0500
Raw View
On 09/21/2015 03:56 AM, Michael Park wrote:
> Hello, I've been working on an alternative variant proposal. It's still
> very rough at this point but I've captured the big questions I wanted to
> answer, and would appreciate feedback from the community.
[snip]
> * The members should be discriminated by type rather than the index.
[snip]
The following post:
http://article.gmane.org/gmane.comp.lib.boost.devel/168974
suggests there's a need for descrimination by index.
Also, it exists type type theory:
https://en.wikipedia.org/wiki/Tagged_union
which suggests to me that there is some utility in it.
-regards,
Larry
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Mon, 21 Sep 2015 22:49:44 -0300
Raw View
On 9/21/2015 10:25 PM, David Krauss wrote:
>
>> On 2015=E2=80=9309=E2=80=9322, at 8:42 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> I've found this with raw `union`s as both distinct members with the
>> same type, as well as a single member that changes meaning based on
>> the value of the discriminator (yuck). This was also raised as to
>> support generic programing, the discriminator of a discriminated union
>> is meaningful and contributes to its value.
>
> It sounds like discriminated unions (going back to C) and sum types (in
> functional languages) are different concepts.
Definitively.
>> For these reason, functionality is presented both as type based (for
>> when you absolutely know the types you are dealing with and they are
>> guaranteed to be distinct, like `std::string` and `std::vector`) as
>> well as index based (for when you have duplicated distinct types or
>> you just don't know, aliases, generic contexts, etc).
>
> I prefer an interface that works 100% with definite meaning over one
> with contingencies for cases where =E2=80=9Cyou just don=E2=80=99t know.=
=E2=80=9D
I completely agree. The index-based interface is the one that works 100%=20
with definite meaning. The type-based interface is syntax sugar for a=20
limited use case, where you do now.
This is also a good argument as to why magic types should not have=20
special meaning (or rather there should not be magic types). You see=20
`variant<T, U>`, what does it mean? How many members does the variant=20
have? What is the result of default constructor? What are the emplace=20
semantics? What if both `T` and `U` are specializations of this=20
`default_construct<X>` special tag? Etc. For a discriminated union the=20
answer to those and other questions are straight-forward and do not=20
depend on the particulars of `T` nor `U`, giving 100% definite meaning.=20
For a particular implementation of the sum type concept, it "depends".
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Michael Park <mcypark@gmail.com>
Date: Mon, 21 Sep 2015 20:10:58 -0700 (PDT)
Raw View
------=_Part_6036_327251650.1442891458606
Content-Type: multipart/alternative;
boundary="----=_Part_6037_1381231698.1442891458606"
------=_Part_6037_1381231698.1442891458606
Content-Type: text/plain; charset=UTF-8
On Monday, September 21, 2015 at 9:58:03 AM UTC-7, Matt Calabrese wrote:
>
> On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcy...@gmail.com
> <javascript:>> wrote:
>
>> Hello, I've been working on an alternative variant proposal. It's still
>> very rough at this point but I've captured the big questions I wanted to
>> answer, and would appreciate feedback from the community.
>>
>
> This is a bit divorced from the actual implementation issues. I'm also not
> sure I follow the purpose of the relationship drawn to pointers/inheritance
> in the proposal. I recommend cutting this. A variant is just a sum type and
> deals with a closed set of types. Relating to inheritance is unnecessary
> and confusing, and arguably inaccurate.
>
Thanks for the feedback, I'll try to simplify the discussion a little bit.
> On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcy...@gmail.com
> <javascript:>> wrote:
>
>> The following are some of the principles the design is based on:
>> (1) *union* is not a good starting point for a discriminated union. I
>> believe better starting points are:
>> From C++: *enum* as a special case where each member is a unit
>> type, and
>> *class inheritance* where an abstract base class is a
>> discriminated union of its derived classes.
>> From other languages: Sum types from Haskell and ML or enum from
>> Rust.
>>
>
> It needs to be a union for minimal constexpr-ness.
>
As I mentioned above, I agree that *union* is the required storage
mechanism as far as implementation is concerned. Semantically however, I
don't believe that it needs to model a *union*.
> On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcy...@gmail.com
> <javascript:>> wrote:
>
>> (2) The *order* of the types specified in *variant<Ts...>* should not
>> change its behavior.
>>
>
> Why? Ordering actually ends up being important in usage, and so does
> indexing by value. Without that, it's really difficult to do basic things,
> such as portable serialization. If users want some kind of common ordering
> for some reason, then they can wrap it themselves. Similarly, if
> implementations can do that internally based on intrinsics or something to
> reduce instantiations, they can, but at the top level they need some kind
> of consistent and portable discriminator, otherwise you are missing some
> important use cases.
>
> On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcy...@gmail.com
> <javascript:>> wrote:
>
>> * Default construction should not construct the first type. (2)
>>
>
> Why? If there there is default construction at all, it should be
> consistent across library implementations for portability, and the rules
> should be simple.
>
I was basing this on the principle that order shouldn't matter. I think the
rule can be consistent and simple by default constructing into the valid,
unspecified state.
I argue that this is no different than *int i;* being in an unusable state.
The expectation is that such *int* be assigned to something before it is
used,
or the general guideline of course is to explicitly initialize it to
something. I believe the same applies to a default-constructed variant.
Assign it to something before it is used, but always prefer to explicitly
initialize it.
> On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <mcy...@gmail.com
> <javascript:>> wrote:
>
>> * There is no special treatment for the null state. (3)
>>
>
> I will personally always be against a null state because the rationale
> doesn't hold up. I think it's a huge mistake that people believe it is
> needed. If types involved are noexcept-movable, there is no need for the
> empty state (this is already acknowledged). If there is a type involved
> that has a move constructor that can through, we can just require that the
> user has a noexcept-default-constructible type as one of the specified
> fields, and we can simply default-construct that internally if a move
> throws an exception. If neither of these is the case, then the variant can
> simply be not movable (these requirements are not difficult to meet). This
> avoids weakening the type's invariants with an unnecessary null state and
> gives the user more control.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6037_1381231698.1442891458606
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 21, 2015 at 9:58:03 AM UTC-7, Matt Calabrese w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><di=
v class=3D"gmail_quote">On Mon, Sep 21, 2015 at 1:56 AM, Michael Park <span=
dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-m=
ailto=3D"3DEqFlbIBQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'jav=
ascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;">mcy...@gmail.com</a>></span> wrote:<br><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">Hello, I've been working on an alternative variant proposa=
l. It's still very rough at this point but I've captured the big qu=
estions I wanted to answer, and would appreciate feedback from the communit=
y.</div></blockquote><div><br></div><div>This is a bit divorced from the ac=
tual implementation issues. I'm also not sure I follow the purpose of t=
he relationship drawn to pointers/inheritance in the proposal. I recommend =
cutting this. A variant is just a sum type and deals with a closed set of t=
ypes. Relating to inheritance is unnecessary and confusing, and arguably in=
accurate.</div></div></div></div></blockquote><div><br></div><div>Thanks fo=
r the feedback, I'll try to simplify the discussion a little bit.</div>=
<div>=C2=A0</div><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><div class=3D"gmail_quote"><div>On Mon, Sep 21, 2015 at 1:56 AM, M=
ichael Park=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_b=
lank" gdf-obfuscated-mailto=3D"3DEqFlbIBQAJ" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D=
'javascript:';return true;">mcy...@gmail.com</a>></span>=C2=A0<w=
br>wrote:=C2=A0=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>The follo=
wing are some of the principles the design is based on:</div><div>=C2=A0 (1=
)=C2=A0<font face=3D"courier new, monospace"><b>union</b></font>=C2=A0is no=
t a good starting point for a discriminated union. I believe better startin=
g points are:</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0From C++:=C2=A0<font fac=
e=3D"courier new, monospace"><b>enum</b></font>=C2=A0as a special case wher=
e each member is a unit type, and</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0<b>c=
lass inheritance</b>=C2=A0where an abstract base class is a discriminated u=
nion of its derived classes.</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0From othe=
r languages: Sum types from Haskell and ML or=C2=A0<font face=3D"courier ne=
w, monospace" style=3D"font-weight:bold">enum</font><font face=3D"arial, sa=
ns-serif"><b>=C2=A0</b>from Rust.</font></div></div></blockquote><div><br><=
/div><div>It needs to be a union for minimal constexpr-ness.</div><div></di=
v></div></div></div></blockquote><div><br></div><div>As I mentioned above, =
I agree that <b style=3D"font-family: 'courier new', monospace;">un=
ion</b><font face=3D"arial, sans-serif">=C2=A0is the required storage mecha=
nism as far as implementation is concerned. Semantically however, I don'=
;t believe that it needs to model a </font><font face=3D"courier new, monos=
pace"><b>union</b></font><font face=3D"arial, sans-serif">.</font></div><di=
v>=C2=A0=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>On Mon, Sep 21, 20=
15 at 1:56 AM, Michael Park=C2=A0<span dir=3D"ltr"><<a href=3D"javascrip=
t:" target=3D"_blank" gdf-obfuscated-mailto=3D"3DEqFlbIBQAJ" rel=3D"nofollo=
w" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=
=3D"this.href=3D'javascript:';return true;">mcy...@gmail.com</a>>=
;</span>=C2=A0<wbr>wrote:=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div=
>=C2=A0 (2) The=C2=A0<b>order</b>=C2=A0of the types specified in=C2=A0<font=
face=3D"courier new, monospace"><b>variant<Ts...></b></font>=C2=A0sh=
ould not change its behavior.</div></div></blockquote><div><br></div><div>W=
hy? Ordering actually ends up being important in usage, and so does indexin=
g by value. Without that, it's really difficult to do basic things, suc=
h as portable serialization. If users want some kind of common ordering for=
some reason, then they can wrap it themselves. Similarly, if implementatio=
ns can do that internally based on intrinsics or something to reduce instan=
tiations, they can, but at the top level they need some kind of consistent =
and portable discriminator, otherwise you are missing some important use ca=
ses.=C2=A0</div></div></div></div></blockquote><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail=
_quote"><div>On Mon, Sep 21, 2015 at 1:56 AM, Michael Park=C2=A0<span dir=
=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailt=
o=3D"3DEqFlbIBQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">mcy...@gmail.com</a>></span>=C2=A0<wbr>wrote:=C2=A0<br></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div>=C2=A0 * Default construction should no=
t construct the first type. (2)</div></div></blockquote><div><br></div><div=
>Why? If there there is default construction at all, it should be consisten=
t across library implementations for portability, and the rules should be s=
imple.</div></div></div></div></blockquote><div>=C2=A0</div><div>I was basi=
ng this on the principle that order shouldn't matter. I think the rule =
can be consistent and simple by default constructing into the valid, unspec=
ified state.</div><div>I argue that this is no different than <b>int i;</b>=
=C2=A0being in an unusable state. The expectation is that such <b>int</b>=
=C2=A0be assigned to something before it is used,</div><div>or the general =
guideline of course is to explicitly initialize it to something. I believe =
the same applies to a default-constructed variant.</div><div>Assign it to s=
omething before it is used, but always prefer to explicitly initialize it.<=
/div><div>=C2=A0</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><div class=3D"gmail_quote"><div></div><div>On Mon, Sep 21, 20=
15 at 1:56 AM, Michael Park=C2=A0<span dir=3D"ltr"><<a href=3D"javascrip=
t:" target=3D"_blank" gdf-obfuscated-mailto=3D"3DEqFlbIBQAJ" rel=3D"nofollo=
w" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=
=3D"this.href=3D'javascript:';return true;">mcy...@gmail.com</a>>=
;</span>=C2=A0<wbr>wrote:=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div=
>=C2=A0 * There is no special treatment for the null state. (3)</div></div>=
</blockquote><div><br></div><div>I will personally always be against a null=
state because the rationale doesn't hold up. I think it's a huge m=
istake that people believe it is needed. If types involved are noexcept-mov=
able, there is no need for the empty state (this is already acknowledged). =
If there is a type involved that has a move constructor that can through, w=
e can just require that the user has a noexcept-default-constructible type =
as one of the specified fields, and we can simply default-construct that in=
ternally if a move throws an exception. If neither of these is the case, th=
en the variant can simply be not movable (these requirements are not diffic=
ult to meet). This avoids weakening the type's invariants with an unnec=
essary null state and gives the user more control.</div></div></div></div>
</blockquote>
<p></p>
-- <br />
<br />
--- <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 />
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_6037_1381231698.1442891458606--
------=_Part_6036_327251650.1442891458606--
.
Author: Michael Park <mcypark@gmail.com>
Date: Mon, 21 Sep 2015 20:46:14 -0700 (PDT)
Raw View
------=_Part_68_45107686.1442893574647
Content-Type: multipart/alternative;
boundary="----=_Part_69_1177435616.1442893574649"
------=_Part_69_1177435616.1442893574649
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 10:06:00 AM UTC-7, Nicol Bolas wrote:
>
> On Monday, September 21, 2015 at 8:51:04 AM UTC-4, David Krauss wrote:
>>
>> On 2015=E2=80=9309=E2=80=9321, at 8:40 PM, Nicol Bolas <jmck...@gmail.co=
m> wrote:
>>
>> Personally, I don't like numeric indexing either, but I also never=20
>> understood why the committee allowed numeric indexing of tuples. The way=
I=20
>> see it, they're equally wrong, but if we're going to have one, we should=
=20
>> have the other for orthogonality's sake.
>>
>>
>> A tuple is an ordered sequence of values. It cannot be discriminated by=
=20
>> types, because repetition of a type isn=E2=80=99t special. (Such discrim=
ination has=20
>> now been added, but it only works for special cases.)
>>
>> A variant has a value of one of several types. As Michael noted, indexin=
g=20
>> the types fundamentally changes their meaning. Now you don=E2=80=99t hav=
e a variant=20
>> of one of several types, but one of several type-index pairs. The amount=
of=20
>> information in the variant value has been measurably increased.
>>
>
> Conceptually, perhaps. But not in any way that actually takes up storage=
=20
> or anything. So it doesn't impact the quality of the variant's=20
> implementation.
>
> And if someone can find a use for it, more power to them. Especially if i=
t=20
> allows them to put different typedefs in the same variant.
>
> The only thing it does for the implementation is prevent it from=20
> re-ordering the elements in the variant.
>
> We should not create an arbitrary restriction on a C++ type, or choose no=
t=20
> to implement genuinely useful functionality, based on some external conce=
pt=20
> of what a `variant` ought to be.
>
I think once you get to a *variant* with duplicate types, you get to a=20
point where you don't get any benefit from using a *variant* over a *union*=
..
Given *variant<int, int>*, the only way to initialize it is with=20
index-based constructor: *variant<int, int> v{in_place<0>, 42};*
and to retrieve the value, index-based get would be used: *get<0>(v)*.
I argue that this is no better than *union { int x; int y; } u; *initializi=
ng=20
with *u.x =3D 42;* and retrieving by u.x.
I suppose you do get the runtime type-check from *get*, but in terms of=20
usability, the user still needs to keep track of which member is active.
Furthermore, while the *name =3D> index* transition seems natural, it's not=
=20
actually the same thing.
In *union { X x; Y y; } u;* the expression *u.x* refers to the same *x* eve=
n=20
if we were to re-order the members as *union { Y y; X x; } u;*
This is not the case with *variant<X, Y> v;* as the expression *get<0>(v)* =
refers=20
to a different value if the order changes: *variant<Y, X>*.
Note on the other hand, that *get<X>(v)* retrieves the same value=20
regardless of the order as desired.
For *variant* to be better than *union*, visitation on such variant must be=
=20
allowed. But how would it be supported?
Should the order of the handlers matter?
*variant<int, int> v{in_place<0>, 42};*
*type_switch (v) (*
* [](int a) { /* handle first int */ },*
* [](int b) { /* handle second int */ }*=20
*);*
Or should they be required to be tagged with their index?
*variant<int, int> v{in_place<0>, 42};*
*type_switch (v) (*
* [](tag<int, 0> a) { /* handle first int */ },*
* [](tag<int, 1> b) { /* handle second int */ }*=20
*);*
I think this becomes unnecessarily complicated for a problem that would be=
=20
better solved by introducing new types that
wrap these *int*s which can provide meaningful names anyway.=20
> Actually, it explicitly allows it; multiple repeated types are distinct=
=20
>> states. But it says that, for such a template, using a type-based getter=
=20
>> always fails; you have to access the element based on the index. Same go=
es=20
>> for emplacement construction.
>>
>>
>> Oh, that=E2=80=99s broken. I don=E2=80=99t want a template that breaks w=
ith repeated=20
>> types. Perhaps I want one template that works with repeated types, and=
=20
>> another that diagnoses them, and allows type-based discrimination. But=
=20
>> repeated types don=E2=80=99t sound too appetizing at all, especially if =
they=E2=80=99re not=20
>> simply deduplicated.
>>
>
> Well, if duplicate types are "deduplicated", then what's the point in=20
> allowing them at all? If you're not going to allow duplicate types to be=
=20
> considered separate states, then there's no point in allowing them at all=
..
>
The point of allowing them is to facilitate generic programming. Otherwise=
=20
it would be required that the user would need to deduplicate anytime they=
=20
have a *variant<Ts...>*.
> A variant in the "null" state has a value, just like a pointer in the=20
>> "null" state has a value. So even conceptually, `void` is the wrong thin=
g.
>>
>>
>> The variant *has* a value, but it does not *hold* a value. A variant in=
=20
>> the special error state you mentioned also has a value.
>>
> =20
> But the variant *does* hold a value. It holds a value that means "nothing=
=20
> meaningful." That value, like "null" for pointers, is a value. It has all=
=20
> of the rights, powers, and functions of a real C++ value. You can create=
=20
> them, copy them, pass them around, and store them.
>
> You can't do any of that with `void`.
>
>
>> `void` is not something we should try to use. It's something we should=
=20
>> try to *avoid* using.
>>
>>
>> That doesn=E2=80=99t make sense. It=E2=80=99s not an anti-pattern; it=E2=
=80=99s a pure and valid=20
>> concept. It represents something you can=E2=80=99t use. It represents =
=E2=80=9Cnothing=20
>> there.=E2=80=9D
>>
>
> I can create a value of type `nullptr_t`. I can create a value of type=20
> `nullopt_t`. I can create references to both of those.
>
> I cannot create a value of type `void`. It is not a valid C++ type. It=20
> lacks orthogonality with the behavior of C++ types. That lack of=20
> orthogonality is what makes using it like this an anti-pattern.
>
> Consider a simple copy visitor class for a variant. All it does is return=
=20
> a copy of the value:
>
> struct CopyVisitor
> {
> template<T> auto operator()(const T &t) const {return t;}
> };
>
> Well, you can't actually do that with `void`, can you? You can't get a=20
> reference to `void`, and you can't return a copy of `void`. So you would=
=20
> need to create a special overload *solely* to handle this case:
>
> struct CopyVisitorAndVoid
> {
> template<T> auto operator()(const T &t) const {return t;}
> void operator()() {return;}
> };
>
> What's more, CopyVisitor could have been a lambda; CopyVisitorAndVoid=20
> cannot.
>
> Template code has to deal with this kind of "what if T is void" question =
a=20
> lot. The best answer: stop using `void`.
>
I agree that *void* cannot be used. In the single dispatch case, it's not=
=20
even that bad. However, it becomes a real problem when considering=20
multi-dispatch.
The following does not work:
*variant<int, string, void> v{42};*
*variant<int, void> w{42};*
*type_switch (v, w) (*
* [](int, int) { ... },*
* [](int, void) { ... },*
* [](string, int) { ... },*
* [](string, void) { ... },*=20
* [](void, int) { ... },*
* [](void, void) { ... }*
*);*
--=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_69_1177435616.1442893574649
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 21, 2015 at 10:06:00 AM UTC-7, Nicol Bolas wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;">On Monday, September 21, 20=
15 at 8:51:04 AM UTC-4, David Krauss wrote:<blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div style=3D"word-wrap:break-word"><div><blockquote type=3D"cite">=
<div>On 2015=E2=80=9309=E2=80=9321, at 8:40 PM, Nicol Bolas <<a rel=3D"n=
ofollow">jmck...@gmail.com</a>> wrote:</div><br><div>Personally, I don&#=
39;t like numeric indexing either, but I also never understood why the comm=
ittee allowed numeric indexing of tuples. The way I see it, they're equ=
ally wrong, but if we're going to have one, we should have the other fo=
r orthogonality's sake.</div></blockquote><div><br></div><div>A tuple i=
s an ordered sequence of values. It cannot be discriminated by types, becau=
se repetition of a type isn=E2=80=99t special. (Such discrimination has now=
been added, but it only works for special cases.)</div><div><br></div><div=
>A variant has a value of one of several types. As Michael noted, indexing =
the types fundamentally changes their meaning. Now you don=E2=80=99t have a=
variant of one of several types, but one of several type-index pairs. The =
amount of information in the <font face=3D"Courier">variant</font> value ha=
s been measurably increased.</div></div></div></blockquote><div><br>Concept=
ually, perhaps. But not in any way that actually takes up storage or anythi=
ng. So it doesn't impact the quality of the variant's implementatio=
n.<br><br>And if someone can find a use for it, more power to them. Especia=
lly if it allows them to put different typedefs in the same variant.<br><br=
>The only thing it does for the implementation is prevent it from re-orderi=
ng the elements in the variant.<br><br>We should not create an arbitrary re=
striction on a C++ type, or choose not to implement genuinely useful functi=
onality, based on some external concept of what a `variant` ought to be.<br=
></div></blockquote><div><br></div><div>I think once you get to a=C2=A0<fon=
t face=3D"courier new, monospace"><b>variant</b></font>=C2=A0with duplicate=
types, you get to a point where you don't get any benefit from using a=
=C2=A0<font face=3D"courier new, monospace"><b>variant</b></font>=C2=A0over=
a=C2=A0<font face=3D"courier new, monospace"><b>union</b></font>.</div><di=
v><font face=3D"arial, sans-serif"><br></font></div><div><font face=3D"aria=
l, sans-serif">Given=C2=A0</font><b style=3D"font-family: 'courier new&=
#39;, monospace;">variant<int, int></b><font face=3D"arial, sans-seri=
f">, the only way to initialize it is with index-based constructor:=C2=A0</=
font><font face=3D"courier new, monospace"><b>variant<int, int> v{in_=
place<0>, 42};</b></font></div><div><font face=3D"arial, sans-serif">=
and to retrieve the value, index-based=C2=A0</font><font face=3D"courier ne=
w, monospace" style=3D"font-weight: bold;">get</font><font face=3D"arial, s=
ans-serif">=C2=A0would be used</font><font face=3D"arial, sans-serif">:=C2=
=A0</font><b style=3D"font-family: 'courier new', monospace;">get&l=
t;0>(v)</b><font face=3D"arial, sans-serif">.</font></div><div><font fac=
e=3D"arial, sans-serif"><br></font></div><div><font face=3D"arial, sans-ser=
if">I argue that this is no better than=C2=A0</font><b><font face=3D"courie=
r new, monospace">union { int x; int y; } u;</font>=C2=A0</b><font face=3D"=
arial, sans-serif">initializing with=C2=A0</font><b><font face=3D"courier n=
ew, monospace">u.x =3D 42;</font></b><b style=3D"font-family: arial, sans-s=
erif;">=C2=A0</b><font face=3D"arial, sans-serif">and retrieving by=C2=A0</=
font><font face=3D"courier new, monospace" style=3D"font-weight: bold;">u.x=
</font><font face=3D"arial, sans-serif">.</font></div><div><font face=3D"ar=
ial, sans-serif">I suppose you do get the runtime type-check from=C2=A0</fo=
nt><b><font face=3D"courier new, monospace">get</font></b><font face=3D"ari=
al, sans-serif">, but in terms of usability, the user still needs to keep t=
rack of which member is active.</font></div><div><font face=3D"arial, sans-=
serif"><br></font></div><div><font face=3D"arial, sans-serif">Furthermore, =
while the=C2=A0<b>name =3D> index</b>=C2=A0transition seems natural, it&=
#39;s not actually the same thing.</font></div><div><font face=3D"arial, sa=
ns-serif">In=C2=A0</font><b style=3D"font-family: 'courier new', mo=
nospace;">union { X x; Y y; } u;</b><font face=3D"arial, sans-serif">=C2=A0=
the expression=C2=A0</font><b style=3D"font-family: 'courier new', =
monospace;">u.x</b><font face=3D"arial, sans-serif">=C2=A0refers to the sam=
e=C2=A0</font><b style=3D"font-family: 'courier new', monospace;">x=
</b><font face=3D"arial, sans-serif">=C2=A0even if we were to re-order the =
members as=C2=A0</font><font face=3D"courier new, monospace"><b>union { Y y=
; X x; } u;</b></font><br></div><div><font face=3D"arial, sans-serif">This =
is not the case with=C2=A0</font><b style=3D"font-family: 'courier new&=
#39;, monospace;">variant<X, Y> v;</b><font face=3D"arial, sans-serif=
">=C2=A0as the expression=C2=A0</font><font size=3D"2"><b style=3D"font-fam=
ily: 'courier new', monospace;">get<0>(v)</b><font face=3D"ar=
ial, sans-serif">=C2=A0refers to a different value if the order changes:=C2=
=A0</font><b style=3D"font-family: 'courier new', monospace;">varia=
nt<Y, X></b><font face=3D"arial, sans-serif">.</font></font></div><di=
v><font size=3D"2"><font face=3D"arial, sans-serif">Note on the other hand,=
that </font><font face=3D"courier new, monospace"><b>get<X>(v)</b></=
font><font face=3D"arial, sans-serif"> retrieves the same value regardless =
of the order as desired.</font></font></div><div><br></div><div><div><font =
face=3D"arial, sans-serif">For </font><b><font face=3D"courier new, monospa=
ce">variant</font></b><font face=3D"arial, sans-serif"> to be better than=
=C2=A0</font><b><font face=3D"courier new, monospace">union</font></b><font=
face=3D"arial, sans-serif">, visitation on such variant must be allowed. B=
ut how would it be supported?</font></div><div><font face=3D"arial, sans-se=
rif">Should the order of the handlers matter?</font></div><div><br></div></=
div><blockquote style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><=
div><div><font face=3D"courier new, monospace"><b>variant<int, int> v=
{in_place<0>, 42};</b></font></div></div><div><div><font face=3D"cour=
ier new, monospace"><b>type_switch (v) (</b></font></div></div><div><div><f=
ont face=3D"courier new, monospace"><b>=C2=A0 [](int a) { /* handle first i=
nt */ },</b></font></div></div></blockquote><div><b style=3D"font-family: &=
#39;courier new', monospace;">=C2=A0 =C2=A0 =C2=A0 =C2=A0[](int b) { /*=
handle second int */ }</b>=C2=A0</div><blockquote style=3D"margin: 0 0 0 4=
0px; border: none; padding: 0px;"><div><div><font face=3D"courier new, mono=
space"><b>);</b></font></div></div></blockquote><div><div><br></div><div>Or=
should they be required to be tagged with their index?</div></div><div><br=
></div><blockquote style=3D"margin: 0 0 0 40px; border: none; padding: 0px;=
"><div><b style=3D"font-family: 'courier new', monospace;">variant&=
lt;int, int> v{in_place<0>, 42};</b></div></blockquote><blockquote=
style=3D"margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div><font=
face=3D"courier new, monospace"><b>type_switch (v) (</b></font></div><div>=
<font face=3D"courier new, monospace"><b>=C2=A0 [](tag<int, 0> a) { /=
* handle first int */ },</b></font></div></blockquote><div><b style=3D"font=
-family: 'courier new', monospace;">=C2=A0 =C2=A0 =C2=A0 =C2=A0[](t=
ag<int, 1> b) { /* handle second int */ }</b>=C2=A0</div><blockquote =
style=3D"margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face=
=3D"courier new, monospace"><b>);</b></font></blockquote><div><br></div><di=
v>I think this becomes unnecessarily complicated for a problem that would b=
e better solved by introducing new types that</div><div>wrap these <b><font=
face=3D"courier new, monospace">int</font></b>s which can provide meaningf=
ul names anyway.=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap:br=
eak-word"><div><blockquote type=3D"cite"><blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div style=3D"word-wrap:break-word"><div><div></div></div></div></blo=
ckquote><div>Actually, it explicitly allows it; multiple repeated types are=
distinct states. But it says that, for such a template, using a type-based=
getter always fails; you have to access the element based on the index. Sa=
me goes for emplacement construction.<br></div></blockquote><div><br></div>=
<div>Oh, that=E2=80=99s broken. I don=E2=80=99t want a template that breaks=
with repeated types. Perhaps I want one template that works with repeated =
types, and another that diagnoses them, and allows type-based discriminatio=
n. But repeated types don=E2=80=99t sound too appetizing at all, especially=
if they=E2=80=99re not simply deduplicated.</div></div></div></blockquote>=
<div><br>Well, if duplicate types are "deduplicated", then what&#=
39;s the point in allowing them at all? If you're not going to allow du=
plicate types to be considered separate states, then there's no point i=
n allowing them at all.<br></div></blockquote><div><br></div><div>The point=
of allowing them is to facilitate generic programming. Otherwise it would =
be required that the user would need to deduplicate anytime they have a=C2=
=A0<font face=3D"courier new, monospace"><b>variant<Ts...></b></font>=
..</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div></div><blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-word"><div><block=
quote type=3D"cite"><div>A variant in the "null" state has a valu=
e, just like a pointer in the "null" state has a value. So even c=
onceptually, `void` is the wrong thing.<br></div></blockquote><div><br></di=
v><div>The <font face=3D"Courier">variant</font> <i>has</i> a value, but it=
does not <i>hold</i>=C2=A0a value. A variant in the special error state yo=
u mentioned also has a value.</div></div></div></blockquote><div>=C2=A0</di=
v><div>But the variant <i>does</i> hold a value. It holds a value that mean=
s "nothing meaningful." That value, like "null" for poi=
nters, is a value. It has all of the rights, powers, and functions of a rea=
l C++ value. You can create them, copy them, pass them around, and store th=
em.<br><br>You can't do any of that with `void`.<br><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-word"><div><br=
><blockquote type=3D"cite"><div>`void` is not something we should try to us=
e. It's something we should try to <i>avoid</i> using.</div></blockquot=
e><br></div><div>That doesn=E2=80=99t make sense. It=E2=80=99s not an anti-=
pattern; it=E2=80=99s a pure and valid concept. It represents something you=
can=E2=80=99t use. It represents =E2=80=9Cnothing there.=E2=80=9D<br></div=
></div></blockquote><div><br>I can create a value of type `nullptr_t`. I ca=
n create a value of type `nullopt_t`. I can create references to both of th=
ose.<br><br>I cannot create a value of type `void`. It is not a valid C++ t=
ype. It lacks orthogonality with the behavior of C++ types. That lack of or=
thogonality is what makes using it like this an anti-pattern.<br><br>Consid=
er a simple copy visitor class for a variant. All it does is return a copy =
of the value:<br><br><div style=3D"background-color:rgb(250,250,250);border=
-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break=
-word"><code><div><span style=3D"color:#008">struct</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#606">CopyVisitor</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">template</span=
><span style=3D"color:#660"><</span><span style=3D"color:#000">T</span><=
span style=3D"color:#660">></span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#008">auto</span><span style=3D"color:#000"> </span><span=
style=3D"color:#008">operator</span><span style=3D"color:#660">()(</span><=
span style=3D"color:#008">const</span><span style=3D"color:#000"> T </span>=
<span style=3D"color:#660">&</span><span style=3D"color:#000">t</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">const</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">{</span><span style=3D"color:#008">return</span><span s=
tyle=3D"color:#000"> t</span><span style=3D"color:#660">;}</span><span styl=
e=3D"color:#000"><br></span><span style=3D"color:#660">};</span></div></cod=
e></div><br>Well, you can't actually do that with `void`, can you? You =
can't get a reference to `void`, and you can't return a copy of `vo=
id`. So you would need to create a special overload <i>solely</i> to handle=
this case:<br><br><div style=3D"background-color:rgb(250,250,250);border-c=
olor:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-w=
ord"><code><div><span style=3D"color:#008">struct</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#606">CopyVisitorAndVoid</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span sty=
le=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">template</sp=
an><span style=3D"color:#660"><</span><span style=3D"color:#000">T</span=
><span style=3D"color:#660">></span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">auto</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#008">operator</span><span style=3D"color:#660">()(</span=
><span style=3D"color:#008">const</span><span style=3D"color:#000"> T </spa=
n><span style=3D"color:#660">&</span><span style=3D"color:#000">t</span=
><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#008">const</span><span style=3D"color:#000"> </span><span=
style=3D"color:#660">{</span><span style=3D"color:#008">return</span><span=
style=3D"color:#000"> t</span><span style=3D"color:#660">;}</span><span st=
yle=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">void</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#008">operator</spa=
n><span style=3D"color:#660">()()</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">{</span><span style=3D"color:#008">return</span>=
<span style=3D"color:#660">;}</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">};</span></div></code></div><br>What's more, =
CopyVisitor could have been a lambda; CopyVisitorAndVoid cannot.<br><br>Tem=
plate code has to deal with this kind of "what if T is void" ques=
tion a lot. The best answer: stop using `void`.<br></div></blockquote><div>=
<br></div><div>I agree that <b><font face=3D"courier new, monospace">void</=
font></b>=C2=A0cannot be used. In the single dispatch case, it's not ev=
en that bad. However, it becomes a real problem when considering multi-disp=
atch.</div><div>The following does not work:</div><div><br></div><blockquot=
e style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><font face=
=3D"courier new, monospace"><b>variant<int, string, void> v{42};</b><=
/font></div><div><font face=3D"courier new, monospace"><b>variant<int, v=
oid> w{42};</b></font></div><div><font face=3D"courier new, monospace"><=
b>type_switch (v, w) (</b></font></div><div><font face=3D"courier new, mono=
space"><b>=C2=A0 [](int, int) { ... },</b></font></div></blockquote><blockq=
uote style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><b styl=
e=3D"font-family: 'courier new', monospace;">=C2=A0 [](int, void) {=
... },</b></div></blockquote><blockquote style=3D"margin: 0 0 0 40px; bord=
er: none; padding: 0px;"><div><b style=3D"font-family: 'courier new'=
;, monospace;">=C2=A0 [](string, int) { ... },</b></div></blockquote><block=
quote style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><b sty=
le=3D"font-family: 'courier new', monospace;">=C2=A0 [](string, voi=
d) { ... },</b>=C2=A0</div></blockquote><blockquote style=3D"margin: 0px 0p=
x 0px 40px; border: none; padding: 0px;"><b style=3D"font-family: 'cour=
ier new', monospace;">=C2=A0 [](void, int) { ... },</b></blockquote><bl=
ockquote style=3D"margin: 0px 0px 0px 40px; border: none; padding: 0px;"><b=
style=3D"font-family: 'courier new', monospace;">=C2=A0 [](void, v=
oid) { ... }</b></blockquote><blockquote style=3D"margin: 0 0 0 40px; borde=
r: none; padding: 0px;"><div><font face=3D"courier new, monospace"><b>);</b=
></font></div></blockquote>
<p></p>
-- <br />
<br />
--- <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 />
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_69_1177435616.1442893574649--
------=_Part_68_45107686.1442893574647--
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 22 Sep 2015 12:51:50 +0800
Raw View
--Apple-Mail=_3267EC03-563E-4988-90EB-76A8A99339B1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9322, at 9:49 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> On 9/21/2015 10:25 PM, David Krauss wrote:
>>=20
>> I prefer an interface that works 100% with definite meaning over one
>> with contingencies for cases where =E2=80=9Cyou just don=E2=80=99t know.=
=E2=80=9D
>=20
> I completely agree. The index-based interface is the one that works 100% =
with definite meaning. The type-based interface is syntax sugar for a limit=
ed use case, where you do now.
That=E2=80=99s saying that 80% of it works 100% of the time, or that 100% w=
orks 80% of the time. The type-based accessor is part of the same class int=
erface.
I can=E2=80=99t imagine wanting to use indexes, or making the effort to def=
ine the constants needed to do indexing properly. Given a variant<string, i=
nt>, I=E2=80=99m reaching for get<string>, not get<0>. So, for me, the soon=
er variant<string, string> throws an error, the better.
Or, let it Just Work=E2=84=A2. If selecting the first element is good enoug=
h for default construction (though I=E2=80=99m not saying it=E2=80=99s so),=
then selecting the first T is good enough for a type-based getter. Simply =
presume that the user is using type-based interface consistently and never =
indexing.
> This is also a good argument as to why magic types should not have specia=
l meaning (or rather there should not be magic types). You see `variant<T, =
U>`, what does it mean? How many members does the variant have? What is the=
result of default constructor? What are the emplace semantics? What if bot=
h `T` and `U` are specializations of this `default_construct<X>` special ta=
g? Etc. For a discriminated union the answer to those and other questions a=
re straight-forward and do not depend on the particulars of `T` nor `U`, gi=
ving 100% definite meaning. For a particular implementation of the sum type=
concept, it "depends=E2=80=9D.
Magic is bad. But a variety of user preferences have to be signaled somehow=
..
I think the best way through is to create an essential subset of sum-type f=
unctionality, and then enable the other features by magic and/or separate c=
lasses.
--=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/.
--Apple-Mail=_3267EC03-563E-4988-90EB-76A8A99339B1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9322, at 9:49 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"mai=
lto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:<=
/div><br class=3D"Apple-interchange-newline"><div class=3D"">On 9/21/2015 1=
0:25 PM, David Krauss wrote:<br class=3D""><blockquote type=3D"cite" class=
=3D""><br class=3D""></blockquote><blockquote type=3D"cite" class=3D"">I pr=
efer an interface that works 100% with definite meaning over one<br class=
=3D"">with contingencies for cases where =E2=80=9Cyou just don=E2=80=99t kn=
ow.=E2=80=9D<br class=3D""></blockquote><br class=3D"">I completely agree. =
The index-based interface is the one that works 100% with definite meaning.=
The type-based interface is syntax sugar for a limited use case, where you=
do now.<br class=3D""></div></blockquote><div><br class=3D""></div><div>Th=
at=E2=80=99s saying that 80% of it works 100% of the time, or that 100% wor=
ks 80% of the time. The type-based accessor is part of the same class inter=
face.</div><div><br class=3D""></div><div>I can=E2=80=99t imagine wanting t=
o use indexes, or making the effort to define the constants needed to do in=
dexing properly. Given a <font face=3D"Courier" class=3D"">variant<strin=
g, int></font>, I=E2=80=99m reaching for <font face=3D"Courier" class=3D=
"">get<string></font>, not <font face=3D"Courier" class=3D"">get=
<0></font>. So, for me, the sooner <font face=3D"Courier" class=3D"">=
variant<string, string></font> throws an error, the better.</div=
><div><br class=3D""></div><div>Or, let it Just Work=E2=84=A2. If selecting=
the first element is good enough for default construction (though I=E2=80=
=99m not saying it=E2=80=99s so), then selecting the first <font face=3D"Co=
urier" class=3D"">T</font> is good enough for a type-based getter. Simply p=
resume that the user is using type-based interface consistently and never i=
ndexing.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div clas=
s=3D"">This is also a good argument as to why magic types should not have s=
pecial meaning (or rather there should not be magic types). You see `varian=
t<T, U>`, what does it mean? How many members does the variant have? =
What is the result of default constructor? What are the emplace semantics? =
What if both `T` and `U` are specializations of this `default_construct<=
X>` special tag? Etc. For a discriminated union the answer to those and =
other questions are straight-forward and do not depend on the particulars o=
f `T` nor `U`, giving 100% definite meaning. For a particular implementatio=
n of the sum type concept, it "depends=E2=80=9D.<br class=3D""></div></bloc=
kquote></div><br class=3D""><div class=3D"">Magic is bad. But a variety of =
user preferences have to be signaled somehow.</div><div class=3D""><br clas=
s=3D""></div><div class=3D"">I think the best way through is to create an e=
ssential subset of sum-type functionality, and then enable the other featur=
es by magic and/or separate classes.</div><div class=3D""><br class=3D""></=
div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_3267EC03-563E-4988-90EB-76A8A99339B1--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Tue, 22 Sep 2015 09:15:47 +0200
Raw View
Le 22/09/15 02:19, David Krauss a =C3=A9crit :
>> On 2015=E2=80=9309=E2=80=9322, at 1:06 AM, Nicol Bolas <jmckesson@gmail.=
com> wrote:
>>
>> Conceptually, perhaps. But not in any way that actually takes up storage=
or anything. So it doesn't impact the quality of the variant's implementat=
ion.
> More states at runtime implies more code to handle the states.
Right, but
if(v) ...
else ....
is not better.
>
>> And if someone can find a use for it, more power to them. Especially if =
it allows them to put different typedefs in the same variant.
>>
>> The only thing it does for the implementation is prevent it from re-orde=
ring the elements in the variant.
> No, it affects the semantics of having different typedefs in there. Why s=
houldn=E2=80=99t it be allowed to retrieve a value given a typedef to its t=
ype? C++ (and C) don=E2=80=99t work by discriminating typedefs from the ali=
ased type; you=E2=80=99re inventing a need.
>
> Also, users are pressured to use indexing if it=E2=80=99s more robust, wh=
ich comes down to either magic numbers or naming the states after types.
I agree that supporting duplicated types will force the use of indexes.
>
>> We should not create an arbitrary restriction on a C++ type, or choose n=
ot to implement genuinely useful functionality, based on some external conc=
ept of what a `variant` ought to be.
> We shouldn=E2=80=99t create a type with functionality defined by the arbi=
trary internal details of a prototype implementation.
+1
>
>> Well, if duplicate types are "deduplicated", then what's the point in al=
lowing them at all? If you're not going to allow duplicate types to be cons=
idered separate states, then there's no point in allowing them at all.
> Indeed. If allowed, they make the template more tolerant, so you don=E2=
=80=99t need to worry that it will reject the type-list or fail to retrieve=
a value of a duplicate type.
>
>> But the variant does hold a value. It holds a value that means "nothing =
meaningful." That value, like "null" for pointers, is a value. It has all o=
f the rights, powers, and functions of a real C++ value. You can create the=
m, copy them, pass them around, and store them.
>>
>> You can't do any of that with `void`.
> There is a wrapper object and there is an object inside the wrapper objec=
t. Two different things.
>
> A disengaged wrapper holds no object at all. Whether that wrapper value i=
s copyable or not depends on the wrapper. But you cannot get a reference to=
the internal object; this is what distinguishes engagement from disengagem=
ent.
The current variant with monostate doesn't design a disengaged variant.=20
monostate is not a special type.
eggs::variant<Ts...> supports disengaged variants and IIRC I agree that=20
you can not get a reference to the internal object.
Let me refer to a nullable variant optionals<Ts...>.
This is also the case for optional<T>. We need to make a difference=20
between sum types (that don't support disengagement and possibly valued=20
types that support it). As shared pointer have nullptr_t, optional<T>=20
has nullopt_t, if discriminated_union is a nullable type
>
> Copying a disengaged wrapper does not imply copying a void value.
Agreed.
>
>> I can create a value of type `nullptr_t`. I can create a value of type `=
nullopt_t`. I can create references to both of those.
>>
>> I cannot create a value of type `void`. It is not a valid C++ type. It l=
acks orthogonality with the behavior of C++ types. That lack of orthogonali=
ty is what makes using it like this an anti-pattern.
> That=E2=80=99s the opposite of what orthogonality means. Your argument go=
es in the direction that disengagement is something that ordinary types sho=
uld accomplish.
Only nullable types support it.
> Should the user be able to define whether a given type implements engagem=
ent or disengagement?
I believed that the committee is not supporting policies.
> Perhaps exception types are all disengaged states?
>
>> Consider a simple copy visitor class for a variant. All it does is retur=
n a copy of the value:
>>
>> struct CopyVisitor
>> {
>> template<T> auto operator()(const T &t) const {return t;}
>> };
>>
>> Well, you can't actually do that with `void`, can you? You can't get a r=
eference to `void`, and you can't return a copy of `void`. So you would nee=
d to create a special overload solely to handle this case:
I agree, nullable types should have an associated null_t, as nullopt_t.=20
This make easier the visitation when there is no engagement.
> Attempting to get something that doesn=E2=80=99t exist is signaled by thr=
owing an exception. This looks like a job for bad_variant_access.
>
> What can you do with null_t that=E2=80=99s generically uniform with thing=
s that represent actual values? Once you=E2=80=99ve returned null_t by valu=
e, now what? Will every user remember to support null_t in their visitor te=
mplates when it=E2=80=99s never mentioned in the type-list?
a nullable type should have associated always a null_t
>
> Use if(v) to avoid visiting disengaged wrappers.
Why you don't want to visit them? a disengaged wrapper has a valid value.
>> Template code has to deal with this kind of "what if T is void" question=
a lot. The best answer: stop using `void`.
> =E2=80=9CReplace void with another type to represent no value =E2=80=94 b=
ut which has a value=E2=80=9D does not follow.
>
> std::function and [boost|experimental]::any both use typeid(void) to expr=
ess their disengaged states.
Right, and I believe that we need to make this more homogeneous. I'm for=20
a null_t for any named none_t. I've not think about std::function. I=20
need to think about this typeid(void) thing. If we had a nullable=20
variant (but we don't have it yet) we should have also a nullvar_t.
>> On 2015=E2=80=9309=E2=80=9322, at 1:30 AM, Nicol Bolas <jmckesson@gmail.=
com> wrote:
>>
>> If it's implementation-dependent... what does it matter if it sorts them=
or not?
> The sort order should be implementation-defined; the fact of sorting shou=
ld not be.
>
>> I think you're trying to get `variant<int, float>` and `variant<float, i=
nt>` to be the same. Well, C++ doesn't allow that; different template insta=
ntiations will be different types, period.
> Not for alias templates. They implement many-to-one mapping just fine.
>
>> I don't know what you mean by "tag types". If you're talking about thing=
s like iterator categories, those are way too intrusive to use, and can onl=
y be used by certain special functions.
>>
>> Also, what does it matter if it is "impure"? How do you even define "pur=
ity" here?
> I find this:
>
> std::variant< std::default_initial< int >, std::string > >
>
> to be more expressive than this:
>
> std::variant< int, std::string >
>
> Defaulting to the first type is just weird and obtuse. It seems like an i=
mplementation detail being foisted on the user.
>
> If default_initial< int > is defined to be an incomplete type (undefined =
class), then there=E2=80=99s no inconsistency that variant wouldn=E2=80=99t=
be able to hold it.
I wouldn't mix the policy tags and the alternative types
std::variant< int, std::string, policy<defaults<int>> >
policy<> can not be a possible alternative
But I don't think the committee is looking for policies based classes.
>> Orthogonality. I covered why this is important in a previous post.
> You=E2=80=99re arguing for non-orthogonality, or uniformity, that a disen=
gaged wrapper is really still holding something.
>
>> The current proposal only has one "empty" state, and it can only be caus=
ed by copy/move failure. The user can decide if a particular state conceptu=
ally represents "being empty", but that's up to the user. The current propo=
sal does not provide some specific type that, when put into the type list, =
is universally considered being empty.
> N4542 has a function valid(), but no means to invalidate a variant.
>
> So, it=E2=80=99s up to each user to define their own =E2=80=9Cdisengaged =
value=E2=80=9D type. That=E2=80=99s great for interoperability.
>
> Also, std::monostate is described by N4542 as the type of an =E2=80=9Cemp=
ty state.=E2=80=9D I=E2=80=99m not reviewing in detail its exact semantics,=
just now.
If we can interoperability for nullable sum types we need=20
optionals<Ts...> with associated null_t nullopt_t.
>
>> The standards committee likes to standardizes existing (C++) practice. B=
oost.Any, Boost.Optional, and Boost.Variant are all existing practice.
>>
>> What you're talking about is not.
> Eggs.Variant has a disengaged default state expressed by typeid(void), an=
d no distinction of duplicates. It=E2=80=99s even cited by N4542.
>
>> That's one way to look at it. Another way to look at it is to recognize =
that the "various new erausre classes" are not all "erasure classes". Neith=
er `variant` nor `optional` is specifically about type erasure, so your nom=
enclature is debatable. They represent distinct concepts with minimally-ove=
rlapping use cases, and thus they do not strictly need to have a unified in=
terface.
> variant and any have more than minimal overlap, however you want to class=
ify them.
Agreed.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Michael Park <mcypark@gmail.com>
Date: Tue, 22 Sep 2015 00:47:20 -0700 (PDT)
Raw View
------=_Part_6364_1835018873.1442908040883
Content-Type: multipart/alternative;
boundary="----=_Part_6365_495426792.1442908040884"
------=_Part_6365_495426792.1442908040884
Content-Type: text/plain; charset=UTF-8
On Monday, September 21, 2015 at 11:07:18 AM UTC-7, Tony V E wrote:
>
>
>
> On Mon, Sep 21, 2015 at 4:56 AM, Michael Park <mcy...@gmail.com
> <javascript:>> wrote:
>
>> Hello, I've been working on an alternative variant proposal. It's still
>> very rough at this point but I've captured the big questions I wanted to
>> answer, and would appreciate feedback from the community.
>>
>> The following are some of the principles the design is based on:
>> (1) *union* is not a good starting point for a discriminated union. I
>> believe better starting points are:
>> From C++: *enum* as a special case where each member is a unit
>> type, and
>> *class inheritance* where an abstract base class is a
>> discriminated union of its derived classes.
>> From other languages: Sum types from Haskell and ML or enum from
>> Rust.
>> (2) The *order* of the types specified in *variant<Ts...>* should not
>> change its behavior.
>> (3) The API should be minimal, useful, and consistent.
>>
>> The following are few design decisions that fall out from the above
>> principles:
>> * The visitation interface is a *type_switch* expression which looks
>> similar to a regular *switch* statement,
>> as well as *match* expressions from functional languages. (1)
>> * Default construction should not construct the first type. (2)
>> * The members should be discriminated by type rather than the index.
>> (2), (3)
>> (i.e. *variant<int, string, int>* behaves equivalently to *variant<int,
>> string>*)
>> * There is no special treatment for the null state. (3)
>>
>> This is the work-in-progress in a Google Doc: Variant
>> <https://docs.google.com/document/d/12PPuGwSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp=sharing> and
>> it is open for comments.
>>
>> I'm in Seattle attending CppCon this week. Please reach out if you're
>> also here and would like to provide feedback and/or have further design
>> discussions!
>>
>> Thanks,
>>
>> MPark.
>>
>
>
> I find it a little bit hard to follow your proposal - you often list
> various potential strategies, one of which is your chosen strategy. But it
> isn't always clear which is the one you chose (or maybe you are choosing
> more than one). Or possibly I'm just bad at reading and need to re-read
> it. But giving your chosen strategy a Green title or something similar
> might help.
>
Sorry about that, and thanks for the feedback! I had the chosen strategy
slightly bluer than others, but it must've been hard to see. I've changed
it such that the chosen strategy is blue and the others are grey.
> I _think_ you are suggesting:
>
> - "empty" state exists
> - "empty" state is used for construction
> - "empty" state is used for failed assignment(?)
> - variant<int, string> == variant<string, int> (as much as possible)
> - variant<int, string, int> == variant<int, string>
>
All of the above are accurate.
If it has an empty state, what's with the null_t stuff? I think that's
> where I'm most confused.
>
The distinction is that every variant has an empty state which is
considered valid, but unspecified, but nullability is opt-in with *null_t*.
That is,
*void F(const variant<int, std::string>& v) {*
* type_switch (v) (*
* [](int) { /* handle int */ },*
* [](const std::string&) { /* handle string */ },*
* );*
*}*
As opposed to:
*void F(const variant<int, std::string, std::null_t>& v) {*
* type_switch (v) (*
* [](int) { /* handle int */ },*
* [](const std::string&) { /* handle string */ },*
* [](std::null_t) { /* handle null */ },*
* );*
*}*
If I use null_t as one of the types (ie variant<int, string, null_t>), and
> assignment throws, does the variant become empty, or get the value of a
> null_t?
>
It becomes empty even in the presence of *null_t*. I argue that we don't
want to set the value of *null_t* in the *Special Behavior for std::null_t*
section.
> If I use int (ie noexcept default constructible) as one of the types ie
> variant<int, Foo, Bar> and assignment throws, does it become empty, or get
> the value of int(0)? (ie is null_t more special than int?)
>
It becomes empty. As proposed, *std::null_t* gets absolutely no special
treatment from *variant**.*
> For default variant construction you mention:
>
> "Assuming that default constructability is desirable, it would be
> desirable for any variant to be default constructible. "
>
> The logic is sound, but I'm not sure about the assumption. For some
> classes (or some coding styles and guidelines), default construction is NOT
> desirable. If I've decided (in spite of the annoyances) to make Foo not
> default constructible and Bar not default constructible, I probably don't
> want variant<Foo, Bar> to be default constructible.
>
Interesting, thanks for mentioning. I'll think about it more.
> Tony
>
>
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6365_495426792.1442908040884
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 21, 2015 at 11:07:18 AM UTC-7, Tony V E wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><div><br>=
<div class=3D"gmail_quote">On Mon, Sep 21, 2015 at 4:56 AM, Michael Park <s=
pan dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscate=
d-mailto=3D"I6J1ex3MBQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;return true;">mcy...@gmail.com</a>></span> wrote:<br><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rg=
b(204,204,204);padding-left:1ex"><div dir=3D"ltr">Hello, I've been work=
ing on an alternative variant proposal. It's still very rough at this p=
oint but I've captured the big questions I wanted to answer, and would =
appreciate feedback from the community.<div><br></div><div>The following ar=
e some of the principles the design is based on:</div><div>=C2=A0 (1)=C2=A0=
<font face=3D"courier new, monospace"><b>union</b></font>=C2=A0is not a goo=
d starting point for a discriminated union. I believe better starting point=
s are:</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0From C++:=C2=A0<font face=3D"co=
urier new, monospace"><b>enum</b></font>=C2=A0as a special case where each =
member is a unit type, and</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0<b>class in=
heritance</b>=C2=A0where an abstract base class is a discriminated union of=
its derived classes.</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0From other langu=
ages: Sum types from Haskell and ML or=C2=A0<font style=3D"font-weight:bold=
" face=3D"courier new, monospace">enum</font><font face=3D"arial, sans-seri=
f"><b>=C2=A0</b>from Rust.</font></div><div>=C2=A0 (2) The=C2=A0<b>order</b=
>=C2=A0of the types specified in=C2=A0<font face=3D"courier new, monospace"=
><b>variant<Ts...></b></font>=C2=A0should not change its behavior.</d=
iv><div>=C2=A0 (3) The API should be minimal, useful, and consistent.</div>=
<div><br></div><div>The following are few design decisions that fall out fr=
om the above principles:</div><div>=C2=A0 * The visitation interface is a=
=C2=A0<b>type_switch</b>=C2=A0expression which looks similar to a regular=
=C2=A0<b>switch</b>=C2=A0statement,</div><div>=C2=A0 =C2=A0 as well as=C2=
=A0<b>match</b>=C2=A0expressions from functional languages. (1)</div><div>=
=C2=A0 * Default construction should not construct the first type. (2)</div=
><div>=C2=A0 * The members should be discriminated by type rather than the =
index. (2), (3)</div><div>=C2=A0 =C2=A0 =C2=A0(i.e.=C2=A0<font face=3D"cour=
ier new, monospace"><b>variant<int, string, int></b></font>=C2=A0beha=
ves equivalently to=C2=A0<b style=3D"font-family:"courier new",mo=
nospace">variant<int, string></b><font face=3D"arial, sans-serif">)</=
font></div><div>=C2=A0 * There is no special treatment for the null state. =
(3)</div><div><br></div><div>This is the work-in-progress in a Google Doc:=
=C2=A0<a href=3D"https://docs.google.com/document/d/12PPuGwSel38YzXadItleMy=
nl77nl75dSq6YiJHDhp48/edit?usp=3Dsharing" target=3D"_blank" rel=3D"nofollow=
" onmousedown=3D"this.href=3D'https://docs.google.com/document/d/12PPuG=
wSel38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp\75sharing';return true;=
" onclick=3D"this.href=3D'https://docs.google.com/document/d/12PPuGwSel=
38YzXadItleMynl77nl75dSq6YiJHDhp48/edit?usp\75sharing';return true;">Va=
riant</a>=C2=A0and it is open for comments.</div><div><br></div><div>I'=
m in Seattle attending CppCon this week. Please reach out if you're als=
o here and would like to provide feedback and/or have further design discus=
sions!</div><div><div><br></div><div>Thanks,</div><div><br></div><div>MPark=
..</div></div></div></blockquote><div><br><br></div><div>I find it a little =
bit hard to follow your proposal - you often list various potential strateg=
ies, one of which is your chosen strategy.=C2=A0 But it isn't always cl=
ear which is the one you chose (or maybe you are choosing more than one).=
=C2=A0 Or possibly I'm just bad at reading and need to re-read it.=C2=
=A0 But giving your chosen strategy a Green title or something similar migh=
t help.<br></div></div></div></div></blockquote><div><br></div><div>Sorry a=
bout that, and thanks for the feedback! I had the chosen strategy slightly =
bluer than others, but it must've been hard to see. I've changed it=
such that the chosen strategy is blue and the others are grey.</div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><div class=3D"gmail_quote"><div>I _think_ you are suggesting:<br><br></=
div><div>- "empty" state exists<br></div><div>- "empty"=
state is used for construction<br></div><div>- "empty" state is =
used for failed assignment(?)<br></div><div>- variant<int, string> =
=3D=3D variant<string, int> (as much as possible)<br></div><div>- var=
iant<int, string, int> =3D=3D variant<int, string></div></div><=
/div></div></blockquote><div><br></div><div>All of the above are accurate.<=
/div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>If it has an empty=
state, what's with the null_t stuff? I think that's where I'm =
most confused.<br></div></div></div></div></blockquote><div><br></div><div>=
The distinction is that every variant has an empty state which is considere=
d valid, but unspecified, but nullability is opt-in with <b style=3D"font-f=
amily: 'courier new', monospace;">null_t</b><font face=3D"arial, sa=
ns-serif">.</font></div><div><font face=3D"arial, sans-serif"><br></font></=
div><div><font face=3D"arial, sans-serif">That is,</font></div><blockquote =
style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><b><font fac=
e=3D"courier new, monospace"><br></font></b></div><div><b><font face=3D"cou=
rier new, monospace">void F(const variant<int, std::string>& v) {=
</font></b></div><div><b><font face=3D"courier new, monospace">=C2=A0 type_=
switch (v) (</font></b></div><div><b><font face=3D"courier new, monospace">=
=C2=A0 =C2=A0 [](int) { /* handle int */ },</font></b></div><div><b><font f=
ace=3D"courier new, monospace">=C2=A0 =C2=A0 [](const std::string&) { /=
* handle string */ },</font></b></div><div><b><font face=3D"courier new, mo=
nospace">=C2=A0 );</font></b></div><div><b><font face=3D"courier new, monos=
pace">}</font></b></div></blockquote><div><br></div><div>As opposed to:</di=
v><div><br></div><blockquote style=3D"margin: 0 0 0 40px; border: none; pad=
ding: 0px;"><div><div><b><font face=3D"courier new, monospace">void F(const=
variant<int, std::string, std::null_t>& v) {</font></b></div></d=
iv><div><div><b><font face=3D"courier new, monospace">=C2=A0 type_switch (v=
) (</font></b></div></div><div><div><b><font face=3D"courier new, monospace=
">=C2=A0 =C2=A0 [](int) { /* handle int */ },</font></b></div></div><div><d=
iv><b><font face=3D"courier new, monospace">=C2=A0 =C2=A0 [](const std::str=
ing&) { /* handle string */ },</font></b></div></div></blockquote><bloc=
kquote style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><div>=
<b><font face=3D"courier new, monospace">=C2=A0 =C2=A0 [](std::null_t) { /*=
handle null */ },</font></b></div></div></blockquote><blockquote style=3D"=
margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><b><font face=3D=
"courier new, monospace">=C2=A0 );</font></b></div></div><div><div><b><font=
face=3D"courier new, monospace">}</font></b></div></div></blockquote><div>=
<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"><di=
v><div class=3D"gmail_quote"><div></div><div>If I use null_t as one of the =
types (ie variant<int, string, null_t>), and assignment throws, does =
the variant become empty, or get the value of a null_t?<br></div></div></di=
v></div></blockquote><div><br></div><div>It becomes empty even in the prese=
nce of <b style=3D"font-family: 'courier new', monospace;">null_t</=
b><font face=3D"arial, sans-serif">. I argue that we don't want to set =
the value of </font><b style=3D"font-family: 'courier new', monospa=
ce;">null_t</b><font face=3D"arial, sans-serif">=C2=A0in the </font><b styl=
e=3D"font-family: 'courier new', monospace;">Special Behavior for s=
td::null_t</b><font face=3D"arial, sans-serif">=C2=A0section.</font></div><=
div>=C2=A0</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"lt=
r"><div><div class=3D"gmail_quote"><div></div><div>If I use int (ie noexcep=
t default constructible) as one of the types ie variant<int, Foo, Bar>=
; and assignment throws, does it become empty, or get the value of int(0)? =
(ie is null_t more special than int?)<br></div></div></div></div></blockquo=
te><div><br></div><div><font face=3D"arial, sans-serif">It becomes empty. A=
s proposed,=C2=A0</font><b style=3D"font-family: 'courier new', mon=
ospace;">std::null_t</b><font face=3D"arial, sans-serif">=C2=A0gets absolut=
ely no special treatment from </font><b style=3D"font-family: 'courier =
new', monospace;">variant</b><b><font face=3D"arial, sans-serif">.</fon=
t></b></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>For default=
variant construction you mention:<br><br><span style=3D"font-size:14.6667p=
x;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weig=
ht:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-=
align:baseline">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 "Assuming t=
hat default constructability is desirable, it would be desirable for </span=
><span style=3D"font-size:14.6667px;font-family:Arial;color:rgb(0,0,0);back=
ground-color:transparent;font-weight:700;font-style:normal;font-variant:nor=
mal;text-decoration:none;vertical-align:baseline">any</span><span style=3D"=
font-size:14.6667px;font-family:Arial;color:rgb(0,0,0);background-color:tra=
nsparent;font-weight:400;font-style:normal;font-variant:normal;text-decorat=
ion:none;vertical-align:baseline"> </span><span style=3D"font-size:14.6667p=
x;font-family:Consolas;color:rgb(0,0,0);background-color:transparent;font-w=
eight:400;font-style:normal;font-variant:normal;text-decoration:none;vertic=
al-align:baseline">variant</span><span style=3D"font-size:14.6667px;font-fa=
mily:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:400;fo=
nt-style:normal;font-variant:normal;text-decoration:none;vertical-align:bas=
eline"> to be default constructible. "</span><br></div></div><br></div=
><div>The logic is sound, but I'm not sure about the assumption.=C2=A0 =
For some classes (or some coding styles and guidelines), default constructi=
on is NOT desirable.=C2=A0 If I've decided (in spite of the annoyances)=
to make Foo not default constructible and Bar not default constructible, I=
probably don't want variant<Foo, Bar> to be default constructibl=
e.<br></div></div></blockquote><div><br></div><div>Interesting, thanks for =
mentioning. I'll think about it more.</div><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Tony<br></div><div>=
<br></div><div><br><br></div></div>
</blockquote>
<p></p>
-- <br />
<br />
--- <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 />
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_6365_495426792.1442908040884--
------=_Part_6364_1835018873.1442908040883--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Tue, 22 Sep 2015 09:22:25 +0100
Raw View
On 22/09/15 04:46, Michael Park wrote:
> I think once you get to a *variant* with duplicate types, you get to a
> point where you don't get any benefit from using a *variant* over a *union*.
>
> Given *variant<int, int>*, the only way to initialize it is with
> index-based constructor: *variant<int, int> v{in_place<0>, 42};*
> and to retrieve the value, index-based get would be used: *get<0>(v)*.
My implementation (https://bitbucket.org/anthonyw/variant) supports
duplicated types with type-based indexing:
se::variant<int,int> v(42);
assert(se::get<int>(v)==42);
assert(v.index()==0);
assert(se::get<0>(v)==42);
se::variant<int,int> v2(se::emplaced_index_t<1>(),42);
assert(v2.index()==1);
assert(se::get<1>(v2)==42);
assert(se::get<int>(v2)==42);
If you have a variant with duplicated types, and you ask for type T then
if the variant contains a type T then you get it. If you care which T it
is, then you need to check the index.
If you put a T in a variant with duplicated types then it will set the
index to the lowest index that is type T. If you care which index value
is used, set it.
> For *variant*to be better than *union*, visitation on such variant must
> be allowed. But how would it be supported?
With my implementation, the same visitor function will be called for
whichever type T is stored.
If you care about which T it is, then you need to check the index, or
tag the types to make them different.
>> A variant in the "null" state has a value, just like a pointer
>> in the "null" state has a value. So even conceptually, `void`
>> is the wrong thing.
>
> The variant /has/ a value, but it does not /hold/ a value. A
> variant in the special error state you mentioned also has a value.
>
>
> But the variant /does/ hold a value. It holds a value that means
> "nothing meaningful." That value, like "null" for pointers, is a
> value. It has all of the rights, powers, and functions of a real C++
> value. You can create them, copy them, pass them around, and store them.
>
> You can't do any of that with `void`.
Agreed. My current implementation has an empty_t when empty, which can
be retrieved/queried/etc. just like any other value. I'm not sure that's
the best plan, I was just exploring.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Larry Evans <cppljevans@suddenlink.net>
Date: Tue, 22 Sep 2015 04:39:23 -0500
Raw View
On 09/21/2015 10:46 PM, Michael Park wrote:
>
>
[snip]
>
> I think once you get to a *variant* with duplicate types, you get to a
> point where you don't get any benefit from using a *variant* over a
*union*.
>
> Given *variant<int, int>*, the only way to initialize it is with
> index-based constructor: *variant<int, int> v{in_place<0>, 42};*
> and to retrieve the value, index-based get would be used: *get<0>(v)*.
>
> I argue that this is no better than *union { int x; int y; }
> u; *initializing with *u.x = 42;** *and retrieving by u.x.
Except that the variant has the index() function to indicate
which type is actually active, relieving the programmer from
having to remember that.
> I suppose you do get the runtime type-check from *get*, but in terms of
> usability, the user still needs to keep track of which
> member is active.
True, but in the case of union, there no way the user can
query the union to make sure what he believes is the active
member is actually the active member; thus, the proposed
*variant<int,int>* is better than *union{ int x; int y;}*.
>
> Furthermore, while the *name => index* transition seems natural, it's
> not actually the same thing.
> In *union { X x; Y y; } u;* the expression *u.x* refers to the
> same *x* even if we were to re-order the members as *union { Y y; X x;
} u;*
> This is not the case with *variant<X, Y> v;* as the
> expression *get<0>(v)* refers to a different value if the order
> changes: *variant<Y, X>*.
> Note on the other hand, that *get<X>(v)*retrieves the same value
> regardless of the order as desired.
But this mapping of *name => index* can be implemented in a
map-like way, as demonstrated by:
https://gist.github.com/cppljevans/5abee6f5a8deb4f472f9
>
> For *variant*to be better than *union*, visitation on such variant must
> be allowed. But how would it be supported?
> Should the order of the handlers matter?
>
> *variant<int, int> v{in_place<0>, 42};*
> *type_switch (v) (*
> * [](int a) { /* handle first int */ },*
>
> * [](int b) { /* handle second int */ }*
>
> *);*
>
>
> Or should they be required to be tagged with their index?
>
> *variant<int, int> v{in_place<0>, 42};*
>
> *type_switch (v) (*
> * [](tag<int, 0> a) { /* handle first int */ },*
>
> * [](tag<int, 1> b) { /* handle second int */ }*
>
> *);*
>
I think so.
>
> I think this becomes unnecessarily complicated for a problem that would
> be better solved by introducing new types that
> wrap these *int*s which can provide meaningful names
> anyway.
Does this mean that instead of:
* using v_int_int_t= *
* variant *
* < int *
* , int *
* >; *
you would provide wrappers, such as the key_val at:
https://gist.github.com/cppljevans/8e545e8d83946cd74311#file-mapastuple-cpp-L14
and use:
* enum v_indices{v_ndx0,v_ndx1}; *
* using v_int_int_t= *
* variant *
* < key_val<std::integral_constant<v_indices,v_ndx0>,int> *
* , key_val<std::integral_constant<v_indices,v_ndx1>,int> *
* >; *
to assure no duplicate types? Then, to access the v_ndx1
element:
* using v_ndx1_int_t= *
* key_val<std::integral_constant<v_indices,1>,int>; *
* v_int_int_t v_int_int_v= *
* v_ndx1_int_t{}; *
* v_ndx1_int_t v_ndx1_int_v= *
* get<v_ndx1_int_t>(v_int_int_v); *
Is this one example of what you mean by "wrap these *int*s"?
[snip]
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Michael Park <mcypark@gmail.com>
Date: Tue, 22 Sep 2015 03:07:09 -0700 (PDT)
Raw View
------=_Part_6484_1798802908.1442916429335
Content-Type: multipart/alternative;
boundary="----=_Part_6485_105077183.1442916429335"
------=_Part_6485_105077183.1442916429335
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 22, 2015 at 2:39:33 AM UTC-7, Larry Evans wrote:
>
> On 09/21/2015 10:46 PM, Michael Park wrote:
> >
> >
> [snip]
>
> >
> > I think once you get to a *variant* with duplicate types, you get to a
> > point where you don't get any benefit from using a *variant* over a
> *union*.
> >
> > Given *variant<int, int>*, the only way to initialize it is with
> > index-based constructor: *variant<int, int> v{in_place<0>, 42};*
> > and to retrieve the value, index-based get would be used: *get<0>(v)*.
> >
> > I argue that this is no better than *union { int x; int y; }
> > u; *initializing with *u.x = 42;** *and retrieving by u.x.
>
> Except that the variant has the index() function to indicate
> which type is actually active, relieving the programmer from
> having to remember that.
>
> > I suppose you do get the runtime type-check from *get*, but in terms of
> > usability, the user still needs to keep track of which
> > member is active.
>
> True, but in the case of union, there no way the user can
> query the union to make sure what he believes is the active
> member is actually the active member; thus, the proposed
> *variant<int,int>* is better than *union{ int x; int y;}*.
>
> >
> > Furthermore, while the *name => index* transition seems natural, it's
> > not actually the same thing.
> > In *union { X x; Y y; } u;* the expression *u.x* refers to the
> > same *x* even if we were to re-order the members as *union { Y y; X x;
> } u;*
> > This is not the case with *variant<X, Y> v;* as the
> > expression *get<0>(v)* refers to a different value if the order
> > changes: *variant<Y, X>*.
> > Note on the other hand, that *get<X>(v)*retrieves the same value
> > regardless of the order as desired.
>
> But this mapping of *name => index* can be implemented in a
> map-like way, as demonstrated by:
>
> https://gist.github.com/cppljevans/5abee6f5a8deb4f472f9
>
> >
> > For *variant*to be better than *union*, visitation on such variant must
> > be allowed. But how would it be supported?
> > Should the order of the handlers matter?
> >
> > *variant<int, int> v{in_place<0>, 42};*
> > *type_switch (v) (*
> > * [](int a) { /* handle first int */ },*
> >
> > * [](int b) { /* handle second int */ }*
> >
> > *);*
> >
> >
> > Or should they be required to be tagged with their index?
> >
> > *variant<int, int> v{in_place<0>, 42};*
> >
> > *type_switch (v) (*
> > * [](tag<int, 0> a) { /* handle first int */ },*
> >
> > * [](tag<int, 1> b) { /* handle second int */ }*
> >
> > *);*
> >
>
> I think so.
>
> >
> > I think this becomes unnecessarily complicated for a problem that would
> > be better solved by introducing new types that
> > wrap these *int*s which can provide meaningful names
> > anyway.
>
> Does this mean that instead of:
>
> * using v_int_int_t= *
> * variant *
> * < int *
> * , int *
> * >; *
>
> you would provide wrappers, such as the key_val at:
>
>
>
> https://gist.github.com/cppljevans/8e545e8d83946cd74311#file-mapastuple-cpp-L14
>
> and use:
>
> * enum v_indices{v_ndx0,v_ndx1}; *
> * using v_int_int_t= *
> * variant *
> * < key_val<std::integral_constant<v_indices,v_ndx0>,int> *
> * , key_val<std::integral_constant<v_indices,v_ndx1>,int> *
> * >; *
>
> to assure no duplicate types? Then, to access the v_ndx1
> element:
>
> * using v_ndx1_int_t= *
> * key_val<std::integral_constant<v_indices,1>,int>; *
> * v_int_int_t v_int_int_v= *
> * v_ndx1_int_t{}; *
> * v_ndx1_int_t v_ndx1_int_v= *
> * get<v_ndx1_int_t>(v_int_int_v); *
>
> Is this one example of what you mean by "wrap these *int*s"?
>
I suppose it's possible to do that, but I meant actually is to introduce
new types since (at least as of yet) we don't have strongly-typed type
alias. I suppose an somewhat contrived example would be if we represented a
student's grade by either a level or a percentage. We can introduce new
types *Level* and *Percentage* (1) to distinguish the types, (2) to provide
meaningful names for each *int*.
*struct Level { int level; };*
*struct Percentage { int percentage; };*
*using Grade = variant<Level, Percentage>;*
[snip]
>
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6485_105077183.1442916429335
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Tuesday, September 22, 2015 at 2:39:33 AM UTC-7, Larry Evans wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;">On 09/21/2015 10:46 PM, Mic=
hael Park wrote:
<br>>
<br>>
<br>[snip]
<br>
<br>>
<br>> I think once you get to a *variant* with duplicate types, you get =
to a
<br>> point where you don't get any benefit from using a *variant* o=
ver a
<br>*union*.
<br>>
<br>> Given *variant<int, int>*, the only way to initialize it is =
with
<br>> index-based constructor: *variant<int, int> v{in_place<0&=
gt;, 42};*
<br>> and to retrieve the value, index-based get would be used: *get<=
0>(v)*.
<br>>
<br>> I argue that this is no better than *union { int x; int y; }
<br>> u; *initializing with *u.x =3D 42;** *and retrieving by u.x.
<br>
<br>Except that the variant has the index() function to indicate
<br>which type is actually active, relieving the programmer from
<br>having to remember that.
<br>
<br>> I suppose you do get the runtime type-check from *get*, but in ter=
ms of
<br>> usability, the user still needs to keep track of which
<br>> member is active.
<br>
<br>True, but in the case of union, there no way the user can
<br>query the union to make sure what he believes is the active
<br>member is actually the active member; thus, the proposed
<br>*variant<int,int>* is better than *union{ int x; int y;}*.
<br>
<br>>
<br>> Furthermore, while the *name =3D> index* transition seems natur=
al, it's
<br>> not actually the same thing.
<br>> In *union { X x; Y y; } u;* the expression *u.x* refers to the
<br>> same *x* even if we were to re-order the members as *union { Y y; =
X x;
<br>} u;*
<br>> This is not the case with *variant<X, Y> v;* as the
<br>> expression *get<0>(v)* refers to a different value if the or=
der
<br>> changes: *variant<Y, X>*.
<br>> Note on the other hand, that *get<X>(v)*retrieves the same v=
alue
<br>> regardless of the order as desired.
<br>
<br>But this mapping of *name =3D> index* can be implemented in a
<br>map-like way, as demonstrated by:
<br>
<br><a href=3D"https://gist.github.com/cppljevans/5abee6f5a8deb4f472f9" tar=
get=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www=
..google.com/url?q\75https%3A%2F%2Fgist.github.com%2Fcppljevans%2F5abee6f5a8=
deb4f472f9\46sa\75D\46sntz\0751\46usg\75AFQjCNExggEeRVhyusL6uDUUYPYG9k7R5w&=
#39;;return true;" onclick=3D"this.href=3D'https://www.google.com/url?q=
\75https%3A%2F%2Fgist.github.com%2Fcppljevans%2F5abee6f5a8deb4f472f9\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNExggEeRVhyusL6uDUUYPYG9k7R5w';return true;=
">https://gist.github.com/<wbr>cppljevans/<wbr>5abee6f5a8deb4f472f9</a>
<br>
<br>>
<br>> For *variant*to be better than *union*, visitation on such variant=
must
<br>> be allowed. But how would it be supported?
<br>> Should the order of the handlers matter?
<br>>
<br>> =C2=A0 =C2=A0 *variant<int, int> v{in_place<0>, 42};*
<br>> =C2=A0 =C2=A0 *type_switch (v) (*
<br>> =C2=A0 =C2=A0 * =C2=A0[](int a) { /* handle first int */ },*
<br>>
<br>> * =C2=A0 =C2=A0 =C2=A0 [](int b) { /* handle second int */ }*
<br>>
<br>> =C2=A0 =C2=A0 *);*
<br>>
<br>>
<br>> Or should they be required to be tagged with their index?
<br>>
<br>> =C2=A0 =C2=A0 *variant<int, int> v{in_place<0>, 42};*
<br>>
<br>> =C2=A0 =C2=A0 *type_switch (v) (*
<br>> =C2=A0 =C2=A0 * =C2=A0[](tag<int, 0> a) { /* handle first in=
t */ },*
<br>>
<br>> * =C2=A0 =C2=A0 =C2=A0 [](tag<int, 1> b) { /* handle second =
int */ }*
<br>>
<br>> =C2=A0 =C2=A0 *);*
<br>>
<br>
<br>I think so.
<br>
<br>>
<br>> I think this becomes unnecessarily complicated for a problem that =
would
<br>> be better solved by introducing new types that
<br>> wrap these *int*s which can provide meaningful names
<br>> anyway.
<br>
<br>Does this mean that instead of:
<br>
<br>=C2=A0 * using v_int_int_t=3D *
<br>=C2=A0 * =C2=A0 variant =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*
<br>=C2=A0 * =C2=A0 < int =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*
<br>=C2=A0 * =C2=A0 , int =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*
<br>=C2=A0 * =C2=A0 >; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
*
<br>
<br>you would provide wrappers, such as the key_val at:
<br>
<br>
<br><a href=3D"https://gist.github.com/cppljevans/8e545e8d83946cd74311#file=
-mapastuple-cpp-L14" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'https://www.google.com/url?q\75https%3A%2F%2Fgist.github.com%2=
Fcppljevans%2F8e545e8d83946cd74311%23file-mapastuple-cpp-L14\46sa\75D\46snt=
z\0751\46usg\75AFQjCNHzvXmdQ-00Qr5cfUNMXg-g9sOcdQ';return true;" onclic=
k=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fgist.git=
hub.com%2Fcppljevans%2F8e545e8d83946cd74311%23file-mapastuple-cpp-L14\46sa\=
75D\46sntz\0751\46usg\75AFQjCNHzvXmdQ-00Qr5cfUNMXg-g9sOcdQ';return true=
;">https://gist.github.com/<wbr>cppljevans/<wbr>8e545e8d83946cd74311#file-<=
wbr>mapastuple-cpp-L14</a>
<br>
<br>and use:
<br>
<br>=C2=A0 * =C2=A0enum v_indices{v_ndx0,v_ndx1}; *
<br>=C2=A0 * =C2=A0using v_int_int_t=3D *
<br>=C2=A0 * =C2=A0 =C2=A0variant *
<br>=C2=A0 * =C2=A0 =C2=A0< key_val<std::integral_<wbr>constant<v_=
indices,v_ndx0>,<wbr>int> *
<br>=C2=A0 * =C2=A0 =C2=A0, key_val<std::integral_<wbr>constant<v_ind=
ices,v_ndx1>,<wbr>int> *
<br>=C2=A0 * =C2=A0 =C2=A0>; *
<br>
<br>to assure no duplicate types? Then, to access the v_ndx1
<br>element:
<br>
<br>=C2=A0 * =C2=A0using v_ndx1_int_t=3D *
<br>=C2=A0 * =C2=A0 =C2=A0key_val<std::integral_<wbr>constant<v_indic=
es,1>,int>; =C2=A0*
<br>=C2=A0 * =C2=A0v_int_int_t v_int_int_v=3D *
<br>=C2=A0 * =C2=A0 =C2=A0v_ndx1_int_t{}; *
<br>=C2=A0 * =C2=A0v_ndx1_int_t v_ndx1_int_v=3D *
<br>=C2=A0 * =C2=A0 =C2=A0get<v_ndx1_int_t>(v_int_int_<wbr>v); *
<br>
<br>Is this one example of what you mean by "wrap these *int*s"?
<br></blockquote><div><br></div><div>I suppose it's possible to do that=
, but I meant actually is to introduce new types since (at least as of yet)=
we don't have strongly-typed type alias. I suppose an somewhat contriv=
ed example would be if we represented a student's grade by either a lev=
el or a percentage. W<font face=3D"arial, sans-serif">e can introduce new t=
ypes </font><font face=3D"courier new, monospace"><b>Level</b></font><font =
face=3D"arial, sans-serif"> and </font><b style=3D"font-family: 'courie=
r new', monospace;">Percentage</b><font face=3D"arial, sans-serif">=C2=
=A0(1) to distinguish the types, (2) to provide meaningful names for each <=
/font><b><font face=3D"courier new, monospace">int</font></b><font face=3D"=
arial, sans-serif">.</font></div><div><b><font face=3D"courier new, monospa=
ce"><br></font></b></div><div><blockquote style=3D"margin: 0 0 0 40px; bord=
er: none; padding: 0px;"><div><b><font face=3D"courier new, monospace">stru=
ct Level { int level; };</font></b></div></blockquote></div><blockquote sty=
le=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><b><font f=
ace=3D"courier new, monospace">struct Percentage { int percentage; };</font=
></b></div></div></blockquote><div><b><font face=3D"courier new, monospace"=
><br></font></b></div><blockquote style=3D"margin: 0 0 0 40px; border: none=
; padding: 0px;"><div><b><font face=3D"courier new, monospace">using Grade =
=3D variant<Level, Percentage>;</font></b></div></blockquote><div><br=
></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;">[snip]
<br>
<br>
<br></blockquote>
<p></p>
-- <br />
<br />
--- <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 />
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_6485_105077183.1442916429335--
------=_Part_6484_1798802908.1442916429335--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Tue, 22 Sep 2015 09:17:01 -0300
Raw View
On 9/22/2015 1:51 AM, David Krauss wrote:
>
>> On 2015=E2=80=9309=E2=80=9322, at 9:49 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> On 9/21/2015 10:25 PM, David Krauss wrote:
>>>
>>> I prefer an interface that works 100% with definite meaning over one
>>> with contingencies for cases where =E2=80=9Cyou just don=E2=80=99t know=
..=E2=80=9D
>>
>> I completely agree. The index-based interface is the one that works
>> 100% with definite meaning. The type-based interface is syntax sugar
>> for a limited use case, where you do now.
>
> That=E2=80=99s saying that 80% of it works 100% of the time, or that 100%=
works
> 80% of the time. The type-based accessor is part of the same class
> interface.
This seems like a forced way to phrase it. The interface works 100% of=20
the time, 20% of the interface has stricter requirements than the rest.=20
This is no different than `std::get<T>` on tuple, or `operator=3D=3D` on=20
`std::vector`, and I cannot imagine it being surprising. Consider:
struct foo {};
std::vector<foo> vs, us;
bool eq =3D (vs =3D=3D us);
How do you expect that to work? Or are you suggesting that equality=20
comparison should be removed from `vector` because it has stricter=20
requirements?
> I can=E2=80=99t imagine wanting to use indexes, or making the effort to d=
efine
> the constants needed to do indexing properly. Given a variant<string,
> int>, I=E2=80=99m reaching for get<string>, not get<0>. So, for me, the s=
ooner
> variant<string, string> throws an error, the better.
It seems to me you are still thinking sum types, not unions. For a quick=20
example consider `std::future<R>`, which somehow points to a shared=20
state that is either empty or contains a result. This result can either=20
be a value of type `R`, an exception, a function that produces the=20
value, etc. Simplifying, here's how that is sometimes implemented:
union {
R value;
std::exception_ptr exception;
// ... deferred;
};
int which;
Note, in particular, that `R` could be `std::exception_ptr`.
> Or, let it Just Work=E2=84=A2. If selecting the first element is good eno=
ugh for
> default construction (though I=E2=80=99m not saying it=E2=80=99s so), the=
n selecting the
> first T is good enough for a type-based getter. Simply presume that the
> user is using type-based interface consistently and never indexing.
Furthermore note that when retrieving the value of a future, if the=20
first member of type `std::exception_ptr` is active then a reference to=20
it should be returned, while if the second member of type=20
`std::exception_ptr` is active then it should be rethrown.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Tue, 22 Sep 2015 09:32:57 -0300
Raw View
On 9/22/2015 12:46 AM, Michael Park wrote:
> I think once you get to a *variant* with duplicate types, you get to a
> point where you don't get any benefit from using a *variant* over a *unio=
n*.
>
> Given *variant<int, int>*, the only way to initialize it is with
> index-based constructor: *variant<int, int> v{in_place<0>, 42};*
> and to retrieve the value, index-based get would be used: *get<0>(v)*.
>
> I argue that this is no better than *union { int x; int y; } u;
You seem to be ignoring the fact that there's a discriminator involved.
Change `int` to `std::string`, and the union version does not give you=20
copy/move constructors, copy/move assignment operators, not even a=20
destructor! All these require the discriminator once there's=20
non-trivially-copyable members in the `union`.
If a discriminated `union` were a first class language construct, then I=20
would agree there would be no much different to such variant (well, you=20
get relational operators too, but that's being worked on).
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Tue, 22 Sep 2015 09:42:08 -0300
Raw View
On 9/22/2015 9:32 AM, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
> On 9/22/2015 12:46 AM, Michael Park wrote:
>> I think once you get to a *variant* with duplicate types, you get to a
>> point where you don't get any benefit from using a *variant* over a
>> *union*.
>>
>> Given *variant<int, int>*, the only way to initialize it is with
>> index-based constructor: *variant<int, int> v{in_place<0>, 42};*
>> and to retrieve the value, index-based get would be used: *get<0>(v)*.
>>
>> I argue that this is no better than *union { int x; int y; } u;
>
> You seem to be ignoring the fact that there's a discriminator involved.
>
> Change `int` to `std::string`, and the union version does not give you
> copy/move constructors, copy/move assignment operators, not even a
> destructor! All these require the discriminator once there's
> non-trivially-copyable members in the `union`.
Sorry, that's incorrect. I only care about trivially-copyable members,=20
the standard actually cares about the triviality of each special member=20
function.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 05:52:15 -0700 (PDT)
Raw View
------=_Part_6296_1626891608.1442926335435
Content-Type: multipart/alternative;
boundary="----=_Part_6297_1535078293.1442926335435"
------=_Part_6297_1535078293.1442926335435
Content-Type: text/plain; charset=UTF-8
On Monday, September 21, 2015 at 12:58:03 PM UTC-4, Matt Calabrese wrote:
>
> I will personally always be against a null state because the rationale
> doesn't hold up. I think it's a huge mistake that people believe it is
> needed. If types involved are noexcept-movable, there is no need for the
> empty state (this is already acknowledged). If there is a type involved
> that has a move constructor that can through, we can just require that the
> user has a noexcept-default-constructible type as one of the specified
> fields, and we can simply default-construct that internally if a move
> throws an exception. If neither of these is the case, then the variant can
> simply be not movable (these requirements are not difficult to meet). This
> avoids weakening the type's invariants with an unnecessary null state and
> gives the user more control.
>
I completely understand your feelings here. I think "never empty" was one
of the best decisions made by Boost.Variant.
At the same time, I don't think your solution is reasonable. A user has no
way of telling if a `variant` is in a state because the user put it there
or due to a failure to copy/move. That's bad.
I really like the N4542 approach of "empty as error condition". I like it
because you can ensure that a `variant` never becomes empty simply by
putting copy/move constructors in it that don't ever throw. Therefore, if
you put throwing copy/move objects in it, it's up to you to check for
errors. And if you don't bother to check for errors, on your head be it.
This gives everyone enough freedom to do what they need to do. Those who
need to check for copy/move errors can do so. And those who don't, won't.
And you don't needlessly gimp `variant`'s interface in some use cases.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6297_1535078293.1442926335435
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 21, 2015 at 12:58:03 PM UTC-4, Matt Calabrese =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote"><div></div><div>I will personally always be agains=
t a null state because the rationale doesn't hold up. I think it's =
a huge mistake that people believe it is needed. If types involved are noex=
cept-movable, there is no need for the empty state (this is already acknowl=
edged). If there is a type involved that has a move constructor that can th=
rough, we can just require that the user has a noexcept-default-constructib=
le type as one of the specified fields, and we can simply default-construct=
that internally if a move throws an exception. If neither of these is the =
case, then the variant can simply be not movable (these requirements are no=
t difficult to meet). This avoids weakening the type's invariants with =
an unnecessary null state and gives the user more control.</div></div></div=
></div></blockquote><div><br>I completely understand your feelings here. I =
think "never empty" was one of the best decisions made by Boost.V=
ariant.<br><br>At the same time, I don't think your solution is reasona=
ble. A user has no way of telling if a `variant` is in a state because the =
user put it there or due to a failure to copy/move. That's bad.<br><br>=
I really like the N4542 approach of "empty as error condition". I=
like it because you can ensure that a `variant` never becomes empty simply=
by putting copy/move constructors in it that don't ever throw. Therefo=
re, if you put throwing copy/move objects in it, it's up to you to chec=
k for errors. And if you don't bother to check for errors, on your head=
be it.<br><br>This gives everyone enough freedom to do what they need to d=
o. Those who need to check for copy/move errors can do so. And those who do=
n't, won't. And you don't needlessly gimp `variant`'s inter=
face in some use cases.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_6297_1535078293.1442926335435--
------=_Part_6296_1626891608.1442926335435--
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 22 Sep 2015 21:07:25 +0800
Raw View
--Apple-Mail=_98F33658-1702-4E7D-9B11-F3463E8DF653
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9322, at 8:17 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> This seems like a forced way to phrase it. The interface works 100% of th=
e time, 20% of the interface has stricter requirements than the rest. This =
is no different than `std::get<T>` on tuple, or `operator=3D=3D` on `std::v=
ector`, and I cannot imagine it being surprising. Consider:
std::tuple is never a sum type (at least, in sane usage), so there=E2=80=99=
s no alternative model that std::get<T> could conceivably follow.
vector::operator=3D=3D is covariant with its value_type, as are many of its=
other properties.
The rule for variant type-list duplicates is arbitrary, unrelated to other =
rules in the language, and unintuitive from the =E2=80=9Csum type=E2=80=9D =
perspective =E2=80=94 which is solidly grounded in theory, if not C program=
ming tradition.
It=E2=80=99s more brittle. Given a variant<int, T> where T varies with the =
enclosing library interface, the user can get<T> for any T besides int, and=
the library can=E2=80=99t stop them from doing so. This doesn=E2=80=99t de=
pend on properties of int, unlike your example foo. If the library decides =
to change and use unsigned as the value of the <0> state, now that=E2=80=99=
s the cursed type.
>> I can=E2=80=99t imagine wanting to use indexes, or making the effort to =
define
>> the constants needed to do indexing properly. Given a variant<string,
>> int>, I=E2=80=99m reaching for get<string>, not get<0>. So, for me, the =
sooner
>> variant<string, string> throws an error, the better.
>=20
> It seems to me you are still thinking sum types, not unions.
Yes. I think I=E2=80=99ll continue to use union for genuine discriminated u=
nions, which usually have constraints to determine the layout and the value=
s of the discriminator.
I=E2=80=99ll be interested when there=E2=80=99s a discriminated_union templ=
ate that can store the discriminator in a bitfield.
> Furthermore note that when retrieving the value of a future, if the first=
member of type `std::exception_ptr` is active then a reference to it shoul=
d be returned, while if the second member of type `std::exception_ptr` is a=
ctive then it should be rethrown.
Perhaps variant should not be general enough to implement future (or anyone=
wishing to do so should just use a strong typedef-alike).
=E2=80=94=E2=80=94=E2=80=94
Given that a user asking for get<T> just wants a T without caring about any=
state-machine, the problem is solvable. Stay on the good side of the stric=
t aliasing rule by mapping all discriminator values to the first T in the l=
ist. Check get<T> against all matching discriminator values. This makes no =
behavioral difference except to bless all type-discriminated usage, and the=
performance should be 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/.
--Apple-Mail=_98F33658-1702-4E7D-9B11-F3463E8DF653
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9322, at 8:17 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"mai=
lto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:<=
/div><br class=3D"Apple-interchange-newline"><div class=3D"">This seems lik=
e a forced way to phrase it. The interface works 100% of the time, 20% of t=
he interface has stricter requirements than the rest. This is no different =
than `std::get<T>` on tuple, or `operator=3D=3D` on `std::vector`, an=
d I cannot imagine it being surprising. Consider:<br class=3D""></div></blo=
ckquote><div><br class=3D""></div><div><font face=3D"Courier" class=3D"">st=
d::tuple</font> is never a sum type (at least, in sane usage), so ther=
e=E2=80=99s no alternative model that <font face=3D"Courier" class=3D"=
">std::get<T></font> could conceivably follow.</div><div><br class=3D=
""></div><div><font face=3D"Courier" class=3D"">vector::operator=3D=3D</fon=
t> is covariant with its <font face=3D"Courier" class=3D"">value_type<=
/font>, as are many of its other properties.</div><div><br class=3D""></div=
><div>The rule for <font face=3D"Courier" class=3D"">variant</font> ty=
pe-list duplicates is arbitrary, unrelated to other rules in the language, =
and unintuitive from the =E2=80=9Csum type=E2=80=9D perspective =E2=80=94 w=
hich is solidly grounded in theory, if not C programming tradition.</div><d=
iv><br class=3D""></div><div>It=E2=80=99s more brittle. Given a <font face=
=3D"Courier" class=3D"">variant<int, T></font> where <font face=3D"Co=
urier" class=3D"">T</font> varies with the enclosing library interface, the=
user can <font face=3D"Courier" class=3D"">get<T></font> for any <fo=
nt face=3D"Courier" class=3D"">T</font> <i class=3D"">besides <font face=3D=
"Courier" class=3D"">int</font></i>, and the library can=E2=80=99t stop the=
m from doing so. This doesn=E2=80=99t depend on properties of <font face=3D=
"Courier" class=3D"">int</font>, unlike your example <font face=3D"Cou=
rier" class=3D"">foo</font>. If the library decides to change and use <font=
face=3D"Courier" class=3D"">unsigned</font> as the value of the <font=
face=3D"Courier" class=3D""><0></font> state, now that=E2=80=99s the=
cursed type.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div=
class=3D""><blockquote type=3D"cite" class=3D"">I can=E2=80=99t imagine wa=
nting to use indexes, or making the effort to define<br class=3D"">the cons=
tants needed to do indexing properly. Given a variant<string,<br class=
=3D"">int>, I=E2=80=99m reaching for get<string>, not get<0>=
.. So, for me, the sooner<br class=3D"">variant<string, string> throws=
an error, the better.<br class=3D""></blockquote><br class=3D"">It seems t=
o me you are still thinking sum types, not unions. </div></blockquote><div>=
<br class=3D""></div><div>Yes. I think I=E2=80=99ll continue to use <font f=
ace=3D"Courier" class=3D"">union</font> for genuine discriminated unions, w=
hich usually have constraints to determine the layout and the values of the=
discriminator.</div><div><br class=3D""></div><div>I=E2=80=99ll be interes=
ted when there=E2=80=99s a <font face=3D"Courier" class=3D"">discriminated_=
union</font> template that can store the discriminator in a bitfield.</div>=
<div><br class=3D""></div><blockquote type=3D"cite" class=3D""><div class=
=3D"">Furthermore note that when retrieving the value of a future, if the f=
irst member of type `std::exception_ptr` is active then a reference to it s=
hould be returned, while if the second member of type `std::exception_ptr` =
is active then it should be rethrown.<br class=3D""></div></blockquote></di=
v><br class=3D""><div class=3D"">Perhaps <font face=3D"Courier" class=3D"">=
variant</font> should not be general enough to implement <font face=3D"Cour=
ier" class=3D"">future</font> (or anyone wishing to do so should just =
use a strong typedef-alike).</div><div class=3D""><br class=3D""></div><div=
class=3D"">=E2=80=94=E2=80=94=E2=80=94</div><div class=3D"">Given that a u=
ser asking for <font face=3D"Courier" class=3D"">get<T></font> just w=
ants a <font face=3D"Courier" class=3D"">T</font> without caring about any =
state-machine, the problem is solvable. Stay on the good side of the strict=
aliasing rule by mapping all discriminator values to the first <font face=
=3D"Courier" class=3D"">T</font> in the list. Check <font face=3D"Cour=
ier" class=3D"">get<T></font> against all matching discriminator valu=
es. This makes no behavioral difference except to bless all type-discrimina=
ted usage, and the performance should be just fine.</div><div class=3D""><b=
r class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_98F33658-1702-4E7D-9B11-F3463E8DF653--
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 22 Sep 2015 21:10:12 +0800
Raw View
--Apple-Mail=_AAAAD152-7A8B-4487-84C2-7CED449E642D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9322, at 8:52 PM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> I really like the N4542 approach of "empty as error condition". I like it=
because you can ensure that a `variant` never becomes empty simply by putt=
ing copy/move constructors in it that don't ever throw. Therefore, if you p=
ut throwing copy/move objects in it, it's up to you to check for errors. An=
d if you don't bother to check for errors, on your head be it.
=E2=80=A6 so if there are any such types going in, you need if(v) before do=
ing any visitation, just as I mentioned.
What percentage of use cases will never see a throwing copy constructor?
--=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/.
--Apple-Mail=_AAAAD152-7A8B-4487-84C2-7CED449E642D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9322, at 8:52 PM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D""><span style=3D"font-family: Helvetica;=
font-size: 12px; font-style: normal; font-variant: normal; font-weight: no=
rmal; letter-spacing: normal; line-height: normal; orphans: auto; text-alig=
n: start; text-indent: 0px; text-transform: none; white-space: normal; wido=
ws: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; d=
isplay: inline !important;" class=3D"">I really like the N4542 approach of =
"empty as error condition". I like it because you can ensure that a `varian=
t` never becomes empty simply by putting copy/move constructors in it that =
don't ever throw. Therefore, if you put throwing copy/move objects in it, i=
t's up to you to check for errors. And if you don't bother to check for err=
ors, on your head be it.</span><br style=3D"font-family: Helvetica; font-si=
ze: 12px; font-style: normal; font-variant: normal; font-weight: normal; le=
tter-spacing: normal; line-height: normal; orphans: auto; text-align: start=
; text-indent: 0px; text-transform: none; white-space: normal; widows: auto=
; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""></div></bl=
ockquote></div><br class=3D""><div class=3D"">=E2=80=A6 so if there are any=
such types going in, you need <font face=3D"Courier" class=3D"">if(v)</fon=
t> before doing any visitation, just as I mentioned.</div><div class=3D""><=
br class=3D""></div><div class=3D"">What percentage of use cases will never=
see a throwing <b class=3D"">copy</b> constructor?</div><div class=3D""><b=
r class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_AAAAD152-7A8B-4487-84C2-7CED449E642D--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Tue, 22 Sep 2015 14:16:58 +0100
Raw View
On 22/09/15 14:07, David Krauss wrote:
> It=E2=80=99s more brittle. Given a variant<int, T> where T varies with th=
e
> enclosing library interface, the user can get<T> for any T /besides
> int/, and the library can=E2=80=99t stop them from doing so. This doesn=
=E2=80=99t depend
> on properties of int, unlike your example foo. If the library decides to
> change and use unsigned as the value of the <0> state, now that=E2=80=99s=
the
> cursed type.
That's an implementation issue. My implementation allows duplicates, and
has get<T> always return the contained T.
This seems the best way to handle it to me.
> Given that a user asking for get<T> just wants a T without caring about
> any state-machine, the problem is solvable. Stay on the good side of the
> strict aliasing rule by mapping all discriminator values to the first T
> in the list. Check get<T> against all matching discriminator values.
> This makes no behavioral difference except to bless all
> type-discriminated usage, and the performance should be just fine.
Yes.
Anthony
--=20
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Tue, 22 Sep 2015 10:31:27 -0300
Raw View
On 9/22/2015 10:07 AM, David Krauss wrote:
>
>> On 2015=E2=80=9309=E2=80=9322, at 8:17 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> This seems like a forced way to phrase it. The interface works 100% of
>> the time, 20% of the interface has stricter requirements than the
>> rest. This is no different than `std::get<T>` on tuple, or
>> `operator=3D=3D` on `std::vector`, and I cannot imagine it being
>> surprising. Consider:
>
> The rule for variant type-list duplicates is arbitrary, unrelated to
> other rules in the language, and unintuitive from the =E2=80=9Csum type=
=E2=80=9D
> perspective =E2=80=94 which is solidly grounded in theory, if not C progr=
amming
> tradition.
The rules are no different than `get<I>` and `get<T>` for `std::tuple`.=20
The "sum type" perspective is unrelated, see below.
>>> I can=E2=80=99t imagine wanting to use indexes, or making the effort to=
define
>>> the constants needed to do indexing properly. Given a variant<string,
>>> int>, I=E2=80=99m reaching for get<string>, not get<0>. So, for me, the=
sooner
>>> variant<string, string> throws an error, the better.
>>
>> It seems to me you are still thinking sum types, not unions.
>
> Yes. I think I=E2=80=99ll continue to use union for genuine discriminated
> unions, which usually have constraints to determine the layout and the
> values of the discriminator.
At Lenexa, the following vote was taken in order to be able to decide on=20
the design of `variant`:
Approval vote:
- Discriminated union: 14
- Non-discriminated union (set of types): 3
- Ordered sequence of types, pick first of equals: 8
When considering the current design of the proposed `variant`, keep in=20
mind that it attempts to model a discriminated union.
If there was a way to sort types at compile time, then a sum type could=20
be preferred, one where `variant<int, float>` equals `variant<float,=20
int>`. Note that unlike it was previously said, it would be possible to=20
do so such that even `std::is_same` would behave as expected:
template <typename Types> class basic_variant { ... };
template <typename ...Ts> using variant =3D
basic_variant<typename sort<Ts...>::type>;
I believe I would still want some form of lower level=20
`discriminated_union<Ts...>` alongside such a `variant<Ts...>`, as=20
that's what I would use to implement the later.
One of the things I regret about Eggs.Variant is not having it called=20
`eggs::discriminated_union`.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 07:01:16 -0700 (PDT)
Raw View
------=_Part_3953_228153570.1442930477063
Content-Type: multipart/alternative;
boundary="----=_Part_3954_1180728800.1442930477064"
------=_Part_3954_1180728800.1442930477064
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 8:19:29 PM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9322, at 1:06 AM, Nicol Bolas <jmck...@gmail.com=
<javascript:>>=20
> wrote:
>
> Conceptually, perhaps. But not in any way that actually takes up storage=
=20
> or anything. So it doesn't impact the quality of the variant's=20
> implementation.
>
>
> More states at runtime implies more code to handle the states.
>
> And if someone can find a use for it, more power to them. Especially if i=
t=20
> allows them to put different typedefs in the same variant.
>
> The only thing it does for the implementation is prevent it from=20
> re-ordering the elements in the variant.
>
>
> No, it affects the semantics of having different typedefs in there. Why=
=20
> shouldn=E2=80=99t it be allowed to retrieve a value given a typedef to it=
s type?=20
> C++ (and C) don=E2=80=99t work by discriminating typedefs from the aliase=
d type;=20
> you=E2=80=99re inventing a need.
>
I am not inventing a need for strong typedefs. We already have such a need.=
=20
As evidenced by people constantly asking for them.
But in lieu of strong typedefs, we will want *some* way of putting two=20
distinct typedefs to the same type in a `variant`. That is a reasonable=20
thing for a user to need to do. Especially within generic code.
=20
> Also, users are pressured to use indexing if it=E2=80=99s more robust, wh=
ich comes=20
> down to either magic numbers or naming the states after types.
>
How is this any different from the way people work with `tuple`?
> We should not create an arbitrary restriction on a C++ type, or choose no=
t=20
> to implement genuinely useful functionality, based on some external conce=
pt=20
> of what a `variant` ought to be.
>
>
> We shouldn=E2=80=99t create a type with functionality defined by the arbi=
trary=20
> internal details of a prototype implementation.
>
And what makes you think this behavior is based on "arbitrary internal=20
details of a prototype implementation"? The desire for accessing `variant`=
=20
by index is *not* due to implementation details of an implementation. It's=
=20
a request for greater functionality.
It has nothing to do with the details of any particular `variant`=20
implementation.
=20
> I can create a value of type `nullptr_t`. I can create a value of type=20
> `nullopt_t`. I can create references to both of those.
>
> I cannot create a value of type `void`. It is not a valid C++ type. It=20
> lacks orthogonality with the behavior of C++ types. That lack of=20
> orthogonality is what makes using it like this an anti-pattern.
>
>
> That=E2=80=99s the opposite of what orthogonality means. Your argument go=
es in the=20
> direction that disengagement is something that ordinary types should=20
> accomplish. Should the user be able to define whether a given type=20
> implements engagement or disengagement? Perhaps exception types are all=
=20
> disengaged states?
>
My argument is that "disengagement", to the degree possible, *should not=20
exist* in `variant`s. That's how N4542 works. It doesn't have=20
"disengagement"; it has "invalid". And a `variant` can *only* become=20
invalid due to a failure of copy/moving of the object it stores.
You can check for validity via the usual expressions. But a key point of=20
N4542 is that a `variant` which contains non-throwing copy/moveable types=
=20
will *never be invalid*. So if your `variant` contains only such objects...=
=20
validity is completely irrelevant to you. You don't have to check it, you=
=20
don't have to think about it. You just use it normally.
The condition of a `variant` being invalid only exists because `variant`s=
=20
are value-types and C++ allows copy/moving to fail. It is used only for=20
that, and it should only be tested by code where copy/movement can fail.
Validity is a fundamentally distinct concept from the user saying that a=20
`variant` can have no meaningful value (ie: be empty). That is covered in=
=20
N4542 via `std::monostate`. It is handled as just another type in the=20
typelist. Just another state.
> Template code has to deal with this kind of "what if T is void" question =
a=20
> lot. The best answer: stop using `void`.
>
>
> =E2=80=9CReplace void with another type to represent no value =E2=80=94 b=
ut which has a=20
> value=E2=80=9D does not follow.
>
> std::function and [boost|experimental]::any both use typeid(void) to=20
> express their disengaged states.
>
The more you talk about `function` and `any` in relation to `variant`, the=
=20
more proof you provide that they are fundamentally different constructs and=
=20
should have distinct behaviors.
`function` and `any`, by definition, could contain *any* type (with some=20
restrictions). They can contain types that your code hasn't #included.
`variant`, by definition, doesn't work that way. All of the types it could=
=20
contain are spelled out explicitly in the typelist, and any code that takes=
=20
a `variant` *must* have static access to those type definitions.
Similarly, `function` and `any` both default construct to being empty.=20
`variant` is *never* empty. It may be *invalid*, but that's different from=
=20
being "empty". As such, `variant` default constructs one of its type=20
arguments (N4542 says its the first argument).
Given these distinctions, why would you expect `variant` to use=20
"typeid(void)" to represent being invalid? Just because two other classes,=
=20
who have completely different behaviors, do so?
> I don't know what you mean by "tag types". If you're talking about things=
=20
> like iterator categories, those are way too intrusive to use, and can onl=
y=20
> be used by certain special functions.
>
> Also, what does it matter if it is "impure"? How do you even define=20
> "purity" here?
>
>
> I find this:
>
> std::variant< std::default_initial< int >, std::string > >
>
> to be more expressive than this:
>
> std::variant< int, std::string >
>
> Defaulting to the first type is just weird and obtuse.
>
It's also the standard for C++ unions. If you find it to be obtuse... so=20
what?
However much more "expressive" your way is, it's *also* extremely noisy. It=
=20
makes the type list needlessly bigger.
It also makes it difficult to use generically.
=20
> It seems like an implementation detail being foisted on the user.
>
But it's not an implementation detail; it's explicit desired behavior. It's=
=20
an outgrowth of these design goals:
1: `variant` is never empty.
2: `variant` has a useful default constructor.
That means you have to pick one of the elements from the typelist to=20
construct. And every `variant` must have at least one element, so the first=
=20
one is a logical choice. It also fits with `union`.
> The current proposal only has one "empty" state, and it can only be cause=
d=20
> by copy/move failure. The *user* can decide if a particular state=20
> conceptually represents "being empty", but that's up to the user. The=20
> current proposal does not provide some specific type that, when put into=
=20
> the type list, is universally considered being empty.
>
> N4542 has a function valid(), but no means to invalidate a variant.
>
Yes. That's because being "invalid" in N4542 is fundamentally distinct from=
=20
not having a meaningful value.
=20
> So, it=E2=80=99s up to each user to define their own =E2=80=9Cdisengaged =
value=E2=80=9D type.=20
> That=E2=80=99s great for interoperability.
>
> Also, std::monostate is described by N4542 as the type of an =E2=80=9Cemp=
ty=20
> state.=E2=80=9D I=E2=80=99m not reviewing in detail its exact semantics, =
just now.
>
You're right; I missed that. And it's a good thing to have a specific type=
=20
that is generally accepted to mean "has no value".
> Iterating on big proposals full of little details doesn=E2=80=99t seem to=
be=20
>> working.
>>
>
> Everyone judges "working" based on whether it leads to the result they=20
> want.
>
>
> I=E2=80=99m only judging by the number of iterations and the process used=
to get=20
> from #3 to #4. Also, N4542 still contains enough errors and inconsistenci=
es=20
> that #5 seems assured.
>
Do you think that your ideas would have led to fewer iterations? No.=20
Because your view of what `variant` should be is not the same as what=20
others want. The Boost people would have been right there, arguing for=20
their ideas of how `variant` should work.
And they would have every right to make that argument. They would have=20
every right to make revisions to your proposals.
The reason for the number of iterations is that different people want=20
different things, and they need to make sure that `variant` satisfies those=
=20
needs.
The number of revisions is not a good way to judge the quality of a process=
..
> We have `any` and `optional` in TS's. Given the construction and receptio=
n=20
> of N4542, we will likely have `variant`, as well as probably all three in=
=20
> C++17. These classes will fill good and useful niches in the C++ language=
..
>
>
> That's the only objective definition of "working". So objectively=20
> speaking, the process seems to be working.
>
>
> The objective definition of =E2=80=9Cwork=E2=80=9D is =E2=80=9Cpeople app=
lying the necessary=20
> effort to achieve an end.=E2=80=9D The process is working because we are.=
I meant=20
> to disparage review sessions resulting in design-by-committee, not anythi=
ng=20
> broader.
>
And yet, N4542 is not "design-by-committee" at all. It's very much=20
"design-by-Boost-with-minor-additions". Just like `any` and `optional`. And=
=20
`shared_ptr`. And `function`.
N4542 is not very different from `boost::variant`. I see no evidence of any=
=20
"design-by-committee" here. Your notion that more iterations =3D bad just=
=20
doesn't hold water.
TS=E2=80=99es exist to promote rapid, intense review, to speed the process =
=E2=80=94=20
> whatever it really is.
>
No, TS's exist for two reasons:
1) To allow out-of-band releases of large-ish functionality, without having=
=20
to wait for a full version of C++.
2) To allow testing of large-ish functionality in actual implementations,=
=20
to make sure it actually works well before fully standardizing it.
*Study groups* are for "rapid, intense review, to speed the process".
=20
> Debate over what remains on the table is common in this sort of situation=
..=20
> It can take a large majority to change the direction of a draft=20
> specification, but Eggs.Variant seems to be getting more support than=20
> Boost.Variant, and no draft has even been accepted yet. Now we have anoth=
er=20
> prototype as well.
>
What "more support" are we talking about?
Also, Eggs.Variant... sucks. Even if you like "always check for empty=20
before using your variant", the fact is it has no visitation.
Visitation is like 90% of why you shouldn't roll your own variant class.=20
Visitation allows you to create visitor types which will *fail to compile*=
=20
if you don't cover all of the types in the variant typelist. That solves=20
one of the most pernicious problems when using `variant`s: how to know if=
=20
someone's added a new type. Multi-visitation is also an extremely useful=20
feature.
Indeed, I would go so far as to say that manually using `get` or whatever=
=20
to access a `variant` should be considered a *code smell*, if not a full-on=
=20
anti-pattern. That's one of the reasons why I consider `variant` and `any`=
=20
to be wholly distinct types.
So Eggs.Variant is at best *incomplete*.
--=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_3954_1180728800.1442930477064
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 21, 2015 at 8:19:29 PM UTC-4, David Krauss wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"=
><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=9322, at =
1:06 AM, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" gdf-obfu=
scated-mailto=3D"73WJ4GzgBQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
'javascript:';return true;" onclick=3D"this.href=3D'javascript:=
';return true;">jmck...@gmail.com</a>> wrote:</div><br><div><div>Con=
ceptually, perhaps. But not in any way that actually takes up storage or an=
ything. So it doesn't impact the quality of the variant's implement=
ation.<br></div></div></blockquote><div><br></div><div>More states at runti=
me implies more code to handle the states.</div><br><blockquote type=3D"cit=
e"><div><div>And if someone can find a use for it, more power to them. Espe=
cially if it allows them to put different typedefs in the same variant.<br>=
<br>The only thing it does for the implementation is prevent it from re-ord=
ering the elements in the variant.<br></div></div></blockquote><div><br></d=
iv><div>No, it affects the semantics of having different typedefs in there.=
Why shouldn=E2=80=99t it be allowed to retrieve a value given a typedef to=
its type? C++ (and C) don=E2=80=99t work by discriminating typedefs from t=
he aliased type; you=E2=80=99re inventing a need.</div></div></div></blockq=
uote><div><br>I am not inventing a need for strong typedefs. We already hav=
e such a need. As evidenced by people constantly asking for them.<br><br>Bu=
t in lieu of strong typedefs, we will want <i>some</i> way of putting two d=
istinct typedefs to the same type in a `variant`. That is a reasonable thin=
g for a user to need to do. Especially within generic code.<br>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-=
word"><div><div></div><div>Also, users are pressured to use indexing if it=
=E2=80=99s more robust, which comes down to either magic numbers or naming =
the states after types.</div></div></div></blockquote><div><br>How is this =
any different from the way people work with `tuple`?<br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><b=
lockquote type=3D"cite"><div><div>We should not create an arbitrary restric=
tion on a C++ type, or choose not to implement genuinely useful functionali=
ty, based on some external concept of what a `variant` ought to be.<br></di=
v></div></blockquote><div><br></div><div>We shouldn=E2=80=99t create a type=
with functionality defined by the arbitrary internal details of a prototyp=
e implementation.</div></div></div></blockquote><div><br>And what makes you=
think this behavior is based on "arbitrary internal details of a prot=
otype implementation"? The desire for accessing `variant` by index is =
<i>not</i> due to implementation details of an implementation. It's a r=
equest for greater functionality.<br><br>It has nothing to do with the deta=
ils of any particular `variant` implementation.<br>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><=
blockquote type=3D"cite"><div><div>I can create a value of type `nullptr_t`=
.. I can create a value of type `nullopt_t`. I can create references to both=
of those.<br><br>I cannot create a value of type `void`. It is not a valid=
C++ type. It lacks orthogonality with the behavior of C++ types. That lack=
of orthogonality is what makes using it like this an anti-pattern.<br></di=
v></div></blockquote><div><br></div><div>That=E2=80=99s the opposite of wha=
t orthogonality means. Your argument goes in the direction that disengageme=
nt is something that ordinary types should accomplish. Should the user be a=
ble to define whether a given type implements engagement or disengagement? =
Perhaps exception types are all disengaged states?</div></div></div></block=
quote><div><br>My argument is that "disengagement", to the degree=
possible, <i>should not exist</i> in `variant`s. That's how N4542 work=
s. It doesn't have "disengagement"; it has "invalid<i></=
i>". And a `variant` can <i>only</i> become invalid due to a failure o=
f copy/moving of the object it stores.<br><br>You can check for validity vi=
a the usual expressions. But a key point of N4542 is that a `variant` which=
contains non-throwing copy/moveable types will <i>never be invalid</i>. So=
if your `variant` contains only such objects... validity is completely irr=
elevant to you. You don't have to check it, you don't have to think=
about it. You just use it normally.<br><br>The condition of a `variant` be=
ing invalid only exists because `variant`s are value-types and C++ allows c=
opy/moving to fail. It is used only for that, and it should only be tested =
by code where copy/movement can fail.<br><br>Validity is a fundamentally di=
stinct concept from the user saying that a `variant` can have no meaningful=
value (ie: be empty). That is covered in N4542 via `std::monostate`. It is=
handled as just another type in the typelist. Just another state.<br></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break=
-word"><div><blockquote type=3D"cite"><div><div>Template code has to deal w=
ith this kind of "what if T is void" question a lot. The best ans=
wer: stop using `void`.</div></div></blockquote><br></div><div>=E2=80=9CRep=
lace <font face=3D"Courier">void</font> with another type to represent no v=
alue =E2=80=94 but which has a value=E2=80=9D does not follow.</div><br><di=
v><font face=3D"Courier">std::function</font> and <font face=3D"Courier">[b=
oost|experimental]::any</font> both use <font face=3D"Courier">typeid(void)=
</font> to express their disengaged states.</div></div></blockquote><div><b=
r>The more you talk about `function` and `any` in relation to `variant`, th=
e more proof you provide that they are fundamentally different constructs a=
nd should have distinct behaviors.<br><br>`function` and `any`, by definiti=
on, could contain <i>any</i> type (with some restrictions). They can contai=
n types that your code hasn't #included.<br><br>`variant`, by definitio=
n, doesn't work that way. All of the types it could contain are spelled=
out explicitly in the typelist, and any code that takes a `variant` <i>mus=
t</i> have static access to those type definitions.<i></i><br><br>Similarly=
, `function` and `any` both default construct to being empty. `variant` is =
<i>never</i> empty. It may be <i>invalid</i>, but that's different from=
being "empty". As such, `variant` default constructs one of its =
type arguments (N4542 says its the first argument).<br><br>Given these dist=
inctions, why would you expect `variant` to use "typeid(void)" to=
represent being invalid? Just because two other classes, who have complete=
ly different behaviors, do so?<br></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 style=3D"word-wrap:break-word"><div></div><div><div></div><b=
lockquote type=3D"cite"><div><div dir=3D"ltr"><div>I don't know what yo=
u mean by "tag types". If you're talking about things like it=
erator categories, those are way too intrusive to use, and can only be used=
by certain special functions.<br><br>Also, what does it matter if it is &q=
uot;impure"? How do you even define "purity" here?<br></div>=
</div></div></blockquote><div><br></div><div>I find this:</div><div><br></d=
iv><div><font face=3D"Courier">std::variant< std::default_initial< in=
t >, std::string > ></font></div><div><br></div><div>to be more ex=
pressive than this:</div><div><br></div><div><span style=3D"font-family:Cou=
rier">std::</span><font face=3D"Courier">variant< int, std::string ><=
/font></div><div><br></div><div>Defaulting to the first type is just weird =
and obtuse.</div></div></div></blockquote><div><br>It's also the standa=
rd for C++ unions. If you find it to be obtuse... so what?<br><br>However m=
uch more "expressive" your way is, it's <i>also</i> extremely=
noisy. It makes the type list needlessly bigger.<br><br>It also makes it d=
ifficult to use generically.<br>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div>It seems like a=
n implementation detail being foisted on the user.</div></div></div></block=
quote><div><br>But it's not an implementation detail; it's explicit=
desired behavior. It's an outgrowth of these design goals:<br><br>1: `=
variant` is never empty.<br><br>2: `variant` has a useful default construct=
or.<br><br>That means you have to pick one of the elements from the typelis=
t to construct. And every `variant` must have at least one element, so the =
first one is a logical choice. It also fits with `union`.<br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><d=
iv><div></div><blockquote type=3D"cite"><div><div dir=3D"ltr"><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"><div style=3D"word-wrap:break-word"><div><div></div></div></div></block=
quote><div>The current proposal only has one "empty" state, and i=
t can only be caused by copy/move failure. The=C2=A0<i>user</i>=C2=A0can de=
cide if a particular state conceptually represents "being empty",=
but that's up to the user. The current proposal does not provide some =
specific type that, when put into the type list, is universally considered =
being empty.<br></div></div></div></blockquote><div></div><div>N4542 has a =
function <font face=3D"Courier">valid()</font>, but no means to invalidate =
a variant.</div></div></div></blockquote><div><br>Yes. That's because b=
eing "invalid" in N4542 is fundamentally distinct from not having=
a meaningful value.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div style=3D"word-wrap:break-word"><div><div></div><div>So, it=E2=80=
=99s up to each user to define their own =E2=80=9Cdisengaged value=E2=80=9D=
type. That=E2=80=99s great for interoperability.</div><div><br></div><div>=
Also, <font face=3D"Courier">std::monostate</font> is described by N4542 as=
the type of an =E2=80=9Cempty state.=E2=80=9D I=E2=80=99m not reviewing in=
detail its exact semantics, just now.</div></div></div></blockquote><div><=
br>You're right; I missed that. And it's a good thing to have a spe=
cific type that is generally accepted to mean "has no value".<br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:=
break-word"><div><blockquote type=3D"cite"><div><div dir=3D"ltr"><blockquot=
e 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-lef=
t:1ex"><div style=3D"word-wrap:break-word"><div><div></div></div></div></bl=
ockquote></div></div></blockquote><blockquote type=3D"cite"><div><div dir=
=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div style=3D"word-wrap:break-word"><div>Iteratin=
g on big proposals full of little details doesn=E2=80=99t seem to be workin=
g.</div></div></blockquote><div><br>Everyone judges "working" bas=
ed on whether it leads to the result they want.<br></div></div></div></bloc=
kquote><div><br></div><div>I=E2=80=99m only judging by the number of iterat=
ions and the process used to get from #3 to #4. Also, N4542 still contains =
enough errors and inconsistencies that #5 seems assured.<br></div></div></d=
iv></blockquote><div><br>Do you think that your ideas would have led to few=
er iterations? No. Because your view of what `variant` should be is not the=
same as what others want. The Boost people would have been right there, ar=
guing for their ideas of how `variant` should work.<br><br>And they would h=
ave every right to make that argument. They would have every right to make =
revisions to your proposals.<br><br>The reason for the number of iterations=
is that different people want different things, and they need to make sure=
that `variant` satisfies those needs.<br><br>The number of revisions is no=
t a good way to judge the quality of a process.<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div><=
/div><blockquote type=3D"cite"><div><div dir=3D"ltr"><div>We have `any` and=
`optional` in TS's. Given the construction and reception of N4542, we =
will likely have `variant`, as well as probably all three in C++17. These c=
lasses will fill good and useful niches in the C++ language.<br></div></div=
></div></blockquote><blockquote type=3D"cite"><br></blockquote><blockquote =
type=3D"cite"><div><div dir=3D"ltr"><div>That's the only objective defi=
nition of "working". So objectively speaking, the process seems t=
o be working.<br></div></div></div></blockquote></div><div><div><div dir=3D=
"ltr"><div><br></div><div>The objective definition of =E2=80=9Cwork=E2=80=
=9D is =E2=80=9Cpeople applying the necessary effort to achieve an end.=E2=
=80=9D The process is working because we are. I meant to disparage review s=
essions resulting in design-by-committee, not anything broader.</div></div>=
</div></div></div></blockquote><div><br>And yet, N4542 is not "design-=
by-committee" at all. It's very much "design-by-Boost-with-mi=
nor-additions". Just like `any` and `optional`. And `shared_ptr`. And =
`function`.<br><br> N4542 is not very different from `boost::variant`. I se=
e no evidence of any "design-by-committee" here. Your notion that=
more iterations =3D bad just doesn't hold water.<br><br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><d=
iv><div><div dir=3D"ltr"><div></div><div>TS=E2=80=99es exist to promote rap=
id, intense review, to speed the process =E2=80=94 whatever it really is.</=
div></div></div></div></div></blockquote><div><br>No, TS's exist for tw=
o reasons:<br><br>1) To allow out-of-band releases of large-ish functionali=
ty, without having to wait for a full version of C++.<br><br>2) To allow te=
sting of large-ish functionality in actual implementations, to make sure it=
actually works well before fully standardizing it.<br><br><i>Study groups<=
/i> are for "rapid, intense review, to speed the process".<br>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wr=
ap:break-word"><div><div><div dir=3D"ltr"><div>Debate over what remains on =
the table is common in this sort of situation. It can take a large majority=
to change the direction of a draft specification, but Eggs.Variant seems t=
o be getting more support than Boost.Variant, and no draft has even been ac=
cepted yet. Now we have another prototype as well.</div></div></div></div><=
/div></blockquote><div><br>What "more support" are we talking abo=
ut?<br><br>Also, Eggs.Variant... sucks. Even if you like "always check=
for empty before using your variant", the fact is it has no visitatio=
n.<br><br>Visitation is like 90% of why you shouldn't roll your own var=
iant class. Visitation allows you to create visitor types which will <i>fai=
l to compile</i> if you don't cover all of the types in the variant typ=
elist. That solves one of the most pernicious problems when using `variant`=
s: how to know if someone's added a new type. Multi-visitation is also =
an extremely useful feature.<br><br>Indeed, I would go so far as to say tha=
t manually using `get` or whatever to access a `variant` should be consider=
ed a <i>code smell</i>, if not a full-on anti-pattern. That's one of th=
e reasons why I consider `variant` and `any` to be wholly distinct types.<b=
r><br>So Eggs.Variant is at best <i>incomplete</i>.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_3954_1180728800.1442930477064--
------=_Part_3953_228153570.1442930477063--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 22 Sep 2015 10:15:08 -0400
Raw View
On 2015-09-21 08:50, David Krauss wrote:
> A variant has a value of one of several types. As Michael noted,=20
> indexing the types fundamentally changes their meaning. Now you
> don=E2=80=99t have a variant of one of several types, but one of several=
=20
> type-index pairs. The amount of information in the variant value has
> been measurably increased.
I'm only cursorily following this... my main interest in a standardized
variant type would be something like QVariant, which IIUC is more like
boost::any.
That said, I have to agree with one point being made that it seems
strange to me that the "key" is an index and not a type. Even unions
don't do that; unions "key" on a *name*.
Strong typedefs might be helpful here; that way the "types" in a variant
could be properly named, i.e. variant<A, B, C> (for meaningful names, of
course), even if all of A, B and C are "really" int.
OTOH I could see it being useful to have a union that has run-time
checking that you use it "correctly", but I'm not sure that can be done
via a purely library implementation; not without some performance
penalty anyway.
--=20
Matthew
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 10:05:50 -0700 (PDT)
Raw View
------=_Part_6307_794157671.1442941550159
Content-Type: multipart/alternative;
boundary="----=_Part_6308_478418199.1442941550159"
------=_Part_6308_478418199.1442941550159
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 22, 2015 at 10:15:26 AM UTC-4, Matthew Woehlke wrote:
>
> On 2015-09-21 08:50, David Krauss wrote:=20
> > A variant has a value of one of several types. As Michael noted,=20
> > indexing the types fundamentally changes their meaning. Now you=20
> > don=E2=80=99t have a variant of one of several types, but one of severa=
l=20
> > type-index pairs. The amount of information in the variant value has=20
> > been measurably increased.=20
>
> I'm only cursorily following this... my main interest in a standardized=
=20
> variant type would be something like QVariant, which IIUC is more like=20
> boost::any.=20
=20
>
That said, I have to agree with one point being made that it seems=20
> strange to me that the "key" is an index and not a type. Even unions=20
> don't do that; unions "key" on a *name*.
>
It's all a matter of how you look at things.
Tuples are conceptually analogized to structs. And the tuple equivalent of=
=20
a member name is an index.
Therefore, if tuples are to structs as variants are to unions, then it=20
makes sense to be able to use numeric indices in `variant`. That's the=20
equivalent of a union member's name.
--=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_6308_478418199.1442941550159
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, September 22, 2015 at 10:15:26 AM UTC-4, Matth=
ew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2015-09-21=
08:50, David Krauss wrote:
<br>> A variant has a value of one of several types. As Michael noted,=
=20
<br>> indexing the types fundamentally changes their meaning. Now you
<br>> don=E2=80=99t have a variant of one of several types, but one of s=
everal=20
<br>> type-index pairs. The amount of information in the variant value h=
as
<br>> been measurably increased.
<br>
<br>I'm only cursorily following this... my main interest in a standard=
ized
<br>variant type would be something like QVariant, which IIUC is more like
<br>boost::any.=C2=A0</blockquote><blockquote style=3D"margin: 0px 0px 0px =
0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class=
=3D"gmail_quote"><div>=C2=A0</div></blockquote><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;">That said, I have to agree with one point being made that =
it seems
<br>strange to me that the "key" is an index and not a type. Even=
unions
<br>don't do that; unions "key" on a *name*.<br></blockquote>=
<div><br>It's all a matter of how you look at things.<br><br>Tuples are=
conceptually analogized to structs. And the tuple equivalent of a member n=
ame is an index.<br><br>Therefore, if tuples are to structs as variants are=
to unions, then it makes sense to be able to use numeric indices in `varia=
nt`. That's the equivalent of a union member's name.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_6308_478418199.1442941550159--
------=_Part_6307_794157671.1442941550159--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 12:06:03 -0500
Raw View
--001a11439d98b70fe50520590568
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On 22 September 2015 at 08:07, David Krauss <potswa@gmail.com> wrote:
>
> The rule for variant type-list duplicates is arbitrary,
>
Arbitrary as in either
- Not requiring O(n^2) template instantiations to eliminate it, or
- Doesn't require brand new compiler magic
unrelated to other rules in the language,
>
If it is unrelated to other rules in the language, I take it you are
against new compiler magic. That leaves O(n^2) template instantiations.
I don't think significantly slowing down compiles for such a tiny use case
is worth it.
> It=E2=80=99s more brittle. Given a variant<int, T> where T varies with th=
e
> enclosing library interface, the user can get<T> for any T *besides int*,
> and the library can=E2=80=99t stop them from doing so.
>
The *only* people this is brittle for are the ones who mix both type based
indexing with numeric based indexing. That is a tiny fraction of the users
of variant.
> I=E2=80=99ll be interested when there=E2=80=99s a discriminated_union tem=
plate that can
> store the discriminator in a bitfield.
>
The current variant proposal *can* do that, but why?? That seems way less
efficient.
--=20
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--=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/.
--001a11439d98b70fe50520590568
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 08:07, David Krauss <span dir=3D"l=
tr"><<a href=3D"mailto:potswa@gmail.com" target=3D"_blank">potswa@gmail.=
com</a>></span> wrote:<br><div class=3D"gmail_extra"><div 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 style=3D"word-wrap:break-word">=
<br><div><div>The rule for=C2=A0<font face=3D"Courier">variant</font> type-=
list duplicates is arbitrary, </div></div></div></blockquote><div><br></div=
><div>Arbitrary as in either</div><div><ul><li>Not requiring O(n^2) templat=
e instantiations to eliminate it, or</li><li>Doesn't require brand new =
compiler magic</li></ul></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"=
word-wrap:break-word"><div><div>unrelated to other rules in the language,</=
div></div></div></blockquote><div><br></div><div>If it is unrelated to othe=
r rules in the language, I take it you are against new compiler magic.=C2=
=A0 That leaves O(n^2) template instantiations.</div><div><br></div><div>I =
don't think significantly slowing down compiles for such a tiny use cas=
e is worth it.</div><div>=C2=A0<br></div><blockquote class=3D"gmail_quote" =
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v style=3D"word-wrap:break-word"><div><div>It=E2=80=99s more brittle. Given=
a <font face=3D"Courier">variant<int, T></font> where <font face=3D"=
Courier">T</font> varies with the enclosing library interface, the user can=
<font face=3D"Courier">get<T></font> for any <font face=3D"Courier">=
T</font> <i>besides <font face=3D"Courier">int</font></i>, and the library =
can=E2=80=99t stop them from doing so. </div></div></div></blockquote><div>=
<br></div><div>The <i>only</i>=C2=A0people this is brittle for are the ones=
who mix both type based indexing with numeric based indexing.=C2=A0 That i=
s a tiny fraction of the users of variant.</div><div>=C2=A0</div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div style=3D"word-wrap:break-word"><div><div>I=E2=80=
=99ll be interested when there=E2=80=99s a <font face=3D"Courier">discrimin=
ated_union</font> template that can store the discriminator in a bitfield.<=
br></div></div></div></blockquote><div><br></div><div>The current variant p=
roposal=C2=A0<i>can</i>=C2=A0do that, but why??=C2=A0 That seems way less e=
fficient.=C2=A0</div></div>-- <br><div>=C2=A0Nevin ":-)" Liber=C2=
=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">=
nevin@eviloverlord.com</a>>=C2=A0 <a href=3D"tel:%28847%29%20691-1404" v=
alue=3D"+18476911404" target=3D"_blank">(847) 691-1404</a></div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11439d98b70fe50520590568--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 22 Sep 2015 13:22:51 -0400
Raw View
On 2015-09-22 13:05, Nicol Bolas wrote:
> On Tuesday, September 22, 2015 at 10:15:26 AM UTC-4, Matthew Woehlke wrote:
>> I have to agree with one point being made that it seems strange to
>> me that the "key" is an index and not a type. Even unions don't do
>> that; unions "key" on a *name*.
>
> It's all a matter of how you look at things.
>
> Tuples are conceptually analogized to structs. And the tuple equivalent of
> a member name is an index.
That's an... interesting analogy. A tuple is a "generic" struct, i.e. it
has no particular name, the members have no names, and two tuples with
the same layout are compatible (actually, the same type; unlike two
structs with the same layout).
It's not clear to me that the goal of variant is to provide "generic"
unions. Or maybe I should say, it seems that there is also a use case
for something more like a sum type, which would have different
properties (e.g. no duplication of types, type order not meaningful).
--
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 13:00:46 -0500
Raw View
--001a11415d1c5d8790052059c952
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 09:01, Nicol Bolas <jmckesson@gmail.com> wrote:
> And what makes you think this behavior is based on "arbitrary internal
> details of a prototype implementation"? The desire for accessing `variant`
> by index is *not* due to implementation details of an implementation.
> It's a request for greater functionality.
>
Yes, it is. The people who wanted that functionality made their case for
it in Lenexa, and those of us who participated in the LEWG sessions on
variant found their request quite reasonable.
> It has nothing to do with the details of any particular `variant`
> implementation.
>
That is correct.
> And yet, N4542 is not "design-by-committee" at all. It's very much
> "design-by-Boost-with-minor-additions". Just like `any` and `optional`. And
> `shared_ptr`. And `function`.
>
> N4542 is not very different from `boost::variant`. I see no evidence of
> any "design-by-committee" here. Your notion that more iterations = bad just
> doesn't hold water.
>
The choices are:
- Double buffering in some circumstances
- Empty/invalid state of some sort
- Limit the kinds of types storable in variant
- Terminate when you cannot engage the variant
Boost.Variant does double buffering. Enough committee members are
adamantly against double buffering, so the invalid state was considered the
best of the alternatives.
All the other decisions about variant (default construction, comparison
operators, etc.) reached consensus fairly easily.
Enough other committee members did not like the LEWG consensus achieved in
Lenexa, so the entire discussion will happen again with a larger audience.
But we still have a hard choice between the above alternatives to make, and
while there have been almost 1000 email messages on the topic (both here
and on internal reflectors) since Lenexa, so far there has been little new
additional information added to the discussion to help us make that
decision.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11415d1c5d8790052059c952
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 09:01, Nicol Bolas <span dir=3D"lt=
r"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@g=
mail.com</a>></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>And what makes you think this behavior i=
s based on "arbitrary internal details of a prototype implementation&q=
uot;? The desire for accessing `variant` by index is <i>not</i> due to impl=
ementation details of an implementation. It's a request for greater fun=
ctionality.<br></div></blockquote><div><br></div><div>Yes, it is.=C2=A0 The=
people who wanted that functionality made their case for it in Lenexa, and=
those of us who participated in the LEWG sessions on variant found their r=
equest quite reasonable.</div><div>=C2=A0</div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>It has=
nothing to do with the details of any particular `variant` implementation.=
<br></div></blockquote><div><br></div><div>That is correct.</div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div>And yet, N4542 is not "design-by-commit=
tee" at all. It's very much "design-by-Boost-with-minor-addit=
ions". Just like `any` and `optional`. And `shared_ptr`. And `function=
`.<br></div></blockquote><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><br> N4542 is not very diffe=
rent from `boost::variant`. I see no evidence of any "design-by-commit=
tee" here. Your notion that more iterations =3D bad just doesn't h=
old water.<br></div></blockquote><div><br></div><div>The choices are:</div>=
<div><ul><li>Double buffering in some circumstances<br></li><li>Empty/inval=
id state of some sort<br></li><li>Limit the kinds of types storable in vari=
ant<br></li><li>Terminate when you cannot engage the variant</li></ul></div=
><div>Boost.Variant does double buffering.=C2=A0 Enough committee members a=
re adamantly against double buffering, so the invalid state was considered =
the best of the alternatives.</div><div><br></div><div>All the other decisi=
ons about variant (default construction, comparison operators, etc.) reache=
d consensus fairly easily.</div><div><br></div><div><div>Enough other commi=
ttee members did not like the LEWG consensus achieved in Lenexa, so the ent=
ire discussion will happen again with a larger audience.</div></div><div><b=
r></div><div>But we still have a hard choice between the above alternatives=
to make, and while there have been almost 1000 email messages on the topic=
(both here and on internal reflectors) since Lenexa, so far there has been=
little new additional information added to the discussion to help us make =
that decision.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin=
":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlor=
d.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-140=
4</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11415d1c5d8790052059c952--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 11:21:28 -0700
Raw View
--001a11c30caa11dbf705205a1194
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 11:00 AM, Nevin Liber <nevin@eviloverlord.com>
wrote:
> On 22 September 2015 at 09:01, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> And what makes you think this behavior is based on "arbitrary internal
>> details of a prototype implementation"? The desire for accessing `variant`
>> by index is *not* due to implementation details of an implementation.
>> It's a request for greater functionality.
>>
>
> Yes, it is. The people who wanted that functionality made their case for
> it in Lenexa, and those of us who participated in the LEWG sessions on
> variant found their request quite reasonable.
>
>
>> It has nothing to do with the details of any particular `variant`
>> implementation.
>>
>
> That is correct.
>
>
>> And yet, N4542 is not "design-by-committee" at all. It's very much
>> "design-by-Boost-with-minor-additions". Just like `any` and `optional`. And
>> `shared_ptr`. And `function`.
>>
>
>> N4542 is not very different from `boost::variant`. I see no evidence of
>> any "design-by-committee" here. Your notion that more iterations = bad just
>> doesn't hold water.
>>
>
> The choices are:
>
> - Double buffering in some circumstances
> - Empty/invalid state of some sort
> - Limit the kinds of types storable in variant
> - Terminate when you cannot engage the variant
>
>
I gave what I think is best of all these options (all of the following
describe a single option):
A) In the case that no types involved have a move constructor that can
throw, there is no problem. Everything works and is simple and there is no
invalid state.
B) In the case that at least one type has a move constructor that can
throw, but one of your types has a default constructor that is noexcept,
you can construct that in the even that your variant's move-assignment
operator does not propagate an exception. Everything works and is simple
and there is no invalid state.
C) In the case that one of your types has a move constructor that can throw
and you do not have a type that has a default constructor that is noexcept,
then your overall variant just simply is not
move-assignable/copy-assignable. Everything works and is simple and there
is no invalid state.
Note that in the above option we never weaken the invariants of our type
and we always satisfy the never-empty guarantee. There is never the need
for a special invalid state. If users need to guarantee in generic code
that their variant is move-assignable, even if one of their types has a
move-constructor that can propagate an exception, then all they need to do
is put in a field of their choosing, analogous to boost::blank, as I.E. the
first field of the variant (which would satisfy "B").
This should satisfy everyone's needs and I don't think it's too
controversial. It's efficient and gives the user control.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c30caa11dbf705205a1194
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=
ue, Sep 22, 2015 at 11:00 AM, Nevin Liber <span dir=3D"ltr"><<a href=3D"=
mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>=
></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bor=
der-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On=
22 September 2015 at 09:01, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><span class=3D""><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>And what makes you think this behav=
ior is based on "arbitrary internal details of a prototype implementat=
ion"? The desire for accessing `variant` by index is <i>not</i> due to=
implementation details of an implementation. It's a request for greate=
r functionality.<br></div></blockquote><div><br></div></span><div>Yes, it i=
s.=C2=A0 The people who wanted that functionality made their case for it in=
Lenexa, and those of us who participated in the LEWG sessions on variant f=
ound their request quite reasonable.</div><span class=3D""><div>=C2=A0</div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;=
padding-left:1ex"><div>It has nothing to do with the details of any particu=
lar `variant` implementation.<br></div></blockquote><div><br></div></span><=
div>That is correct.</div><span class=3D""><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
"><div>And yet, N4542 is not "design-by-committee" at all. It'=
;s very much "design-by-Boost-with-minor-additions". Just like `a=
ny` and `optional`. And `shared_ptr`. And `function`.<br></div></blockquote=
><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><br> N4542 is not very different from `boost::varian=
t`. I see no evidence of any "design-by-committee" here. Your not=
ion that more iterations =3D bad just doesn't hold water.<br></div></bl=
ockquote><div><br></div></span><div>The choices are:</div><div><ul><li>Doub=
le buffering in some circumstances<br></li><li>Empty/invalid state of some =
sort<br></li><li>Limit the kinds of types storable in variant<br></li><li>T=
erminate when you cannot engage the variant</li></ul></div></div></div></di=
v></blockquote><div><br></div><div>I gave what I think is best of all these=
options (all of the following describe a single option):</div><div><br></d=
iv><div>A) In the case that no types involved have a move constructor that =
can throw, there is no problem. Everything works and is simple and there is=
no invalid state.</div><div><br></div><div>B) In the case that at least on=
e type has a move constructor that can throw, but one of your types has a d=
efault constructor that is noexcept, you can construct that in the even tha=
t your variant's move-assignment operator does not propagate an excepti=
on. Everything works and is simple and there is no invalid state.</div><div=
><br></div><div>C) In the case that one of your types has a move constructo=
r that can throw and you do not have a type that has a default constructor =
that is noexcept, then your overall variant just simply is not move-assigna=
ble/copy-assignable. Everything works and is simple and there is no invalid=
state.</div><div><br></div><div>Note that in the above option we never wea=
ken the invariants of our type and we always satisfy the never-empty guaran=
tee. There is never the need for a special invalid state. If users need to =
guarantee in generic code that their variant is move-assignable, even if on=
e of their types has a move-constructor that can propagate an exception, th=
en all they need to do is put in a field of their choosing, analogous to bo=
ost::blank, as I.E. the first field of the variant (which would satisfy &qu=
ot;B").</div><div><br></div><div>This should satisfy everyone's ne=
eds and I don't think it's too controversial. It's efficient an=
d gives the user control.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c30caa11dbf705205a1194--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 11:22:43 -0700
Raw View
--001a1142e6488be85005205a15b6
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 11:21 AM, Matt Calabrese <calabrese@google.com>
wrote:
>
> B) In the case that at least one type has a move constructor that can
> throw, but one of your types has a default constructor that is noexcept,
> you can construct that in the even that your variant's move-assignment
> operator does not propagate an exception. Everything works and is simple
> and there is no invalid state.
>
Sigh, I need to proofread before I click send. That should read "you can
construct that in the event that your variant's move-assignment operator
propagates an exception."
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1142e6488be85005205a15b6
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=
ue, Sep 22, 2015 at 11:21 AM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> 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"><div class=3D"gmail_ext=
ra"><div class=3D"gmail_quote"><div>B) In the case that at least one type h=
as a move constructor that can throw, but one of your types has a default c=
onstructor that is noexcept, you can construct that in the even that your v=
ariant's move-assignment operator does not propagate an exception. Ever=
ything works and is simple and there is no invalid state.</div></div></div>=
</div></blockquote><div><br></div><div>Sigh, I need to proofread before I c=
lick send. That should read "you can construct that in the event that =
your variant's move-assignment operator propagates an exception."<=
/div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1142e6488be85005205a15b6--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Tue, 22 Sep 2015 20:25:23 +0200
Raw View
--047d7b624e9a156eb205205a1fec
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 8:00 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 22 September 2015 at 09:01, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> And what makes you think this behavior is based on "arbitrary internal
>> details of a prototype implementation"? The desire for accessing `variant`
>> by index is *not* due to implementation details of an implementation.
>> It's a request for greater functionality.
>>
>
> Yes, it is. The people who wanted that functionality made their case for
> it in Lenexa, and those of us who participated in the LEWG sessions on
> variant found their request quite reasonable.
>
>
>> It has nothing to do with the details of any particular `variant`
>> implementation.
>>
>
> That is correct.
>
>
>> And yet, N4542 is not "design-by-committee" at all. It's very much
>> "design-by-Boost-with-minor-additions". Just like `any` and `optional`. And
>> `shared_ptr`. And `function`.
>>
>
>> N4542 is not very different from `boost::variant`. I see no evidence of
>> any "design-by-committee" here. Your notion that more iterations = bad just
>> doesn't hold water.
>>
>
> The choices are:
>
> - Double buffering in some circumstances
> - Empty/invalid state of some sort
> - Limit the kinds of types storable in variant
> - Terminate when you cannot engage the variant
>
> Boost.Variant does double buffering. Enough committee members are
> adamantly against double buffering, so the invalid state was considered the
> best of the alternatives.
>
> All the other decisions about variant (default construction, comparison
> operators, etc.) reached consensus fairly easily.
>
> Enough other committee members did not like the LEWG consensus achieved in
> Lenexa, so the entire discussion will happen again with a larger audience.
>
> I'm happy with the decision to have an "Empty/invalid state of some
sort". The only modification I would make would be to call it the empty
value, default construct to it, and have it be the default branch in any
switch on the discriminator. Trying to wallpaper over it is just going to
lead to subtle bugs.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b624e9a156eb205205a1fec
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 8:00 PM, Nevin Liber <span dir=3D"ltr"><<a h=
ref=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.=
com</a>></span> wrote:<br><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"><div dir=3D"ltr"><span class=
=3D"">On 22 September 2015 at 09:01, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a=
>></span> wrote:<br></span><div class=3D"gmail_extra"><div class=3D"gmai=
l_quote"><span class=3D""><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>And what makes you think th=
is behavior is based on "arbitrary internal details of a prototype imp=
lementation"? The desire for accessing `variant` by index is <i>not</i=
> due to implementation details of an implementation. It's a request fo=
r greater functionality.<br></div></blockquote><div><br></div></span><div>Y=
es, it is.=C2=A0 The people who wanted that functionality made their case f=
or it in Lenexa, and those of us who participated in the LEWG sessions on v=
ariant found their request quite reasonable.</div><span class=3D""><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div>It has nothing to do with the details of any=
particular `variant` implementation.<br></div></blockquote><div><br></div>=
</span><div>That is correct.</div><span class=3D""><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex"><div>And yet, N4542 is not "design-by-committee" at all=
.. It's very much "design-by-Boost-with-minor-additions". Just=
like `any` and `optional`. And `shared_ptr`. And `function`.<br></div></bl=
ockquote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div><br> N4542 is not very different from `boost=
::variant`. I see no evidence of any "design-by-committee" here. =
Your notion that more iterations =3D bad just doesn't hold water.<br></=
div></blockquote><div><br></div></span><div>The choices are:</div><div><ul>=
<li>Double buffering in some circumstances<br></li><li>Empty/invalid state =
of some sort<br></li><li>Limit the kinds of types storable in variant<br></=
li><li>Terminate when you cannot engage the variant</li></ul></div><div>Boo=
st.Variant does double buffering.=C2=A0 Enough committee members are adaman=
tly against double buffering, so the invalid state was considered the best =
of the alternatives.</div><div><br></div><div>All the other decisions about=
variant (default construction, comparison operators, etc.) reached consens=
us fairly easily.</div><div><br></div><div><div>Enough other committee memb=
ers did not like the LEWG consensus achieved in Lenexa, so the entire discu=
ssion will happen again with a larger audience.</div></div><div><br></div><=
/div></div></div></blockquote><div>I'm happy with the decision to have =
an "Empty/invalid state of some sort".=C2=A0 The only modificatio=
n I would make would be to call it the empty value, default construct to it=
, and have it be the default branch in any switch on the discriminator.=C2=
=A0 Trying to wallpaper over it is just going to lead to subtle bugs.<br></=
div><div><br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b624e9a156eb205205a1fec--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 13:27:42 -0500
Raw View
--001a1142f7ecb20b8505205a2902
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 13:25, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> I'm happy with the decision to have an "Empty/invalid state of some
> sort". The only modification I would make would be to call it the empty
> value, default construct to it,
>
Which was discussed and rejected.
Like I said, there is no new information.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1142f7ecb20b8505205a2902
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 13:25, Andrew Tomazos <span dir=3D=
"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andr=
ewtomazos@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><di=
v class=3D"gmail_quote"><div>=C2=A0</div><blockquote class=3D"gmail_quote" =
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>I&=
#39;m happy with the decision to have an "Empty/invalid state of some =
sort".=C2=A0 The only modification I would make would be to call it th=
e empty value, default construct to it, </div></div></div></div></blockquot=
e><div><br></div><div>Which was discussed and rejected.</div><div><br></div=
><div>Like I said, there is no new information.</div></div>-- <br><div clas=
s=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a=
href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlor=
d.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1142f7ecb20b8505205a2902--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 13:37:23 -0500
Raw View
--001a11459a4064c7f105205a4c29
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 13:21, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> C) In the case that one of your types has a move constructor that can
> throw and you do not have a type that has a default constructor that is
> noexcept, then your overall variant just simply is not
> move-assignable/copy-assignable. Everything works and is simple and there
> is no invalid state.
>
That leads to non-portable code. Is
variant<set<int>, unordered_set<int>>
assignable?
This particular question has caused some committee members to try and
resurrect the idea that move constructors should never throw.
And it isn't just assignability; it also applies to emplace construction.
In other words, once you set that variant with a specific type you can
*never* change the type it holds.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11459a4064c7f105205a4c29
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 13:21, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div>C) In the case that one of your types has =
a move constructor that can throw and you do not have a type that has a def=
ault constructor that is noexcept, then your overall variant just simply is=
not move-assignable/copy-assignable. Everything works and is simple and th=
ere is no invalid state.<br></div></div></div></div></blockquote><div><br><=
/div><div>That leads to non-portable code.=C2=A0 Is</div><div><br></div><di=
v>variant<set<int>, unordered_set<int>></div><div><br></d=
iv><div>assignable?</div><div><br></div><div>This particular question has c=
aused some committee members to try and resurrect the idea that move constr=
uctors should never throw.</div><div><br></div><div>And it isn't just a=
ssignability; it also applies to emplace construction.=C2=A0 In other words=
, once you set that variant with a specific type you can <i>never</i> chang=
e the type it holds.<br></div></div>-- <br><div class=3D"gmail_signature">=
=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@=
eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (8=
47) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11459a4064c7f105205a4c29--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 22 Sep 2015 14:44:06 -0400
Raw View
--089e011605f406935705205a62d3
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 2:21 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Tue, Sep 22, 2015 at 11:00 AM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
>
>> On 22 September 2015 at 09:01, Nicol Bolas <jmckesson@gmail.com> wrote:
>>
>>> And what makes you think this behavior is based on "arbitrary internal
>>> details of a prototype implementation"? The desire for accessing `variant`
>>> by index is *not* due to implementation details of an implementation.
>>> It's a request for greater functionality.
>>>
>>
>> Yes, it is. The people who wanted that functionality made their case for
>> it in Lenexa, and those of us who participated in the LEWG sessions on
>> variant found their request quite reasonable.
>>
>>
>>> It has nothing to do with the details of any particular `variant`
>>> implementation.
>>>
>>
>> That is correct.
>>
>>
>>> And yet, N4542 is not "design-by-committee" at all. It's very much
>>> "design-by-Boost-with-minor-additions". Just like `any` and `optional`. And
>>> `shared_ptr`. And `function`.
>>>
>>
>>> N4542 is not very different from `boost::variant`. I see no evidence of
>>> any "design-by-committee" here. Your notion that more iterations = bad just
>>> doesn't hold water.
>>>
>>
>> The choices are:
>>
>> - Double buffering in some circumstances
>> - Empty/invalid state of some sort
>> - Limit the kinds of types storable in variant
>> - Terminate when you cannot engage the variant
>>
>>
> I gave what I think is best of all these options (all of the following
> describe a single option):
>
> A) In the case that no types involved have a move constructor that can
> throw, there is no problem. Everything works and is simple and there is no
> invalid state.
>
> B) In the case that at least one type has a move constructor that can
> throw, but one of your types has a default constructor that is noexcept,
> you can construct that in the even that your variant's move-assignment
> operator does not propagate an exception. Everything works and is simple
> and there is no invalid state.
>
That sounded reasonable to me at first, however:
I have a drawing program. It can create squares and circles and triangles,
and lay them out, group them (hierarchy) etc.
The user selects a triangle, and clicks "Change to Circle". The triangle
becomes a square.
Is that OK?
To me, the only correct answer is the strong exception guarantee, and
double-buffering (internal, non-allocated - don't want to bring allocators
into this).
If I don't have the strong exception guarantee, I need to implement it
externally. ie keep a backup (probably via the undo buffer). So if
assignment fails, I restore the previous state.
But wait, assignment _didn't_ fail. Or at least I can't tell it failed. It
tried to tell me (via the exception) but the exception was swallowed. I
don't know that I need to restore to a sane state.
:-(
Tony
> C) In the case that one of your types has a move constructor that can
> throw and you do not have a type that has a default constructor that is
> noexcept, then your overall variant just simply is not
> move-assignable/copy-assignable. Everything works and is simple and there
> is no invalid state.
>
> Note that in the above option we never weaken the invariants of our type
> and we always satisfy the never-empty guarantee. There is never the need
> for a special invalid state. If users need to guarantee in generic code
> that their variant is move-assignable, even if one of their types has a
> move-constructor that can propagate an exception, then all they need to do
> is put in a field of their choosing, analogous to boost::blank, as I.E. the
> first field of the variant (which would satisfy "B").
>
> This should satisfy everyone's needs and I don't think it's too
> controversial. It's efficient and gives the user control.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e011605f406935705205a62d3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 2:21 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Tue, Sep 22, 2015=
at 11:00 AM, Nevin Liber <span dir=3D"ltr"><<a href=3D"mailto:nevin@evi=
loverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>></span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><span>On 22 September 2015 at 09:01=
, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" =
target=3D"_blank">jmckesson@gmail.com</a>></span> wrote:<br></span><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><span><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;borde=
r-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><di=
v>And what makes you think this behavior is based on "arbitrary intern=
al details of a prototype implementation"? The desire for accessing `v=
ariant` by index is <i>not</i> due to implementation details of an implemen=
tation. It's a request for greater functionality.<br></div></blockquote=
><div><br></div></span><div>Yes, it is.=C2=A0 The people who wanted that fu=
nctionality made their case for it in Lenexa, and those of us who participa=
ted in the LEWG sessions on variant found their request quite reasonable.</=
div><span><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex"><div>It has nothing to do with =
the details of any particular `variant` implementation.<br></div></blockquo=
te><div><br></div></span><div>That is correct.</div><span><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div>And yet, N4542 is not "design-by-committee"=
at all. It's very much "design-by-Boost-with-minor-additions"=
;. Just like `any` and `optional`. And `shared_ptr`. And `function`.<br></d=
iv></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-le=
ft-style:solid;padding-left:1ex"><div><br> N4542 is not very different from=
`boost::variant`. I see no evidence of any "design-by-committee"=
here. Your notion that more iterations =3D bad just doesn't hold water=
..<br></div></blockquote><div><br></div></span><div>The choices are:</div><d=
iv><ul><li>Double buffering in some circumstances<br></li><li>Empty/invalid=
state of some sort<br></li><li>Limit the kinds of types storable in varian=
t<br></li><li>Terminate when you cannot engage the variant</li></ul></div><=
/div></div></div></blockquote><div><br></div></span><div>I gave what I thin=
k is best of all these options (all of the following describe a single opti=
on):</div><div><br></div><div>A) In the case that no types involved have a =
move constructor that can throw, there is no problem. Everything works and =
is simple and there is no invalid state.</div><div><br></div><div>B) In the=
case that at least one type has a move constructor that can throw, but one=
of your types has a default constructor that is noexcept, you can construc=
t that in the even that your variant's move-assignment operator does no=
t propagate an exception. Everything works and is simple and there is no in=
valid state.</div></div></div></div></blockquote><div><br></div><div>That s=
ounded reasonable to me at first, however:<br><br></div><div>I have a drawi=
ng program.=C2=A0 It can create squares and circles and triangles, and lay =
them out, group them (hierarchy) etc.<br></div><div>The user selects a tria=
ngle, and clicks "Change to Circle".=C2=A0 The triangle becomes a=
square.<br><br></div><div>Is that OK?<br><br></div><div>To me, the only co=
rrect answer is the strong exception guarantee, and double-buffering (inter=
nal, non-allocated - don't want to bring allocators into this).<br><br>=
</div><div>If I don't have the strong exception guarantee, I need to im=
plement it externally.=C2=A0 ie keep a backup (probably via the undo buffer=
).=C2=A0 So if assignment fails, I restore the previous state.<br><br></div=
><div>But wait, assignment _didn't_ fail.=C2=A0 Or at least I can't=
tell it failed. It tried to tell me (via the exception) but the exception =
was swallowed.=C2=A0 I don't know that I need to restore to a sane stat=
e.<br><br>:-(<br><br></div><div>Tony<br><br></div><div><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div><br></div><div>C) In the case that one of your types =
has a move constructor that can throw and you do not have a type that has a=
default constructor that is noexcept, then your overall variant just simpl=
y is not move-assignable/copy-assignable. Everything works and is simple an=
d there is no invalid state.</div><div><br></div><div>Note that in the abov=
e option we never weaken the invariants of our type and we always satisfy t=
he never-empty guarantee. There is never the need for a special invalid sta=
te. If users need to guarantee in generic code that their variant is move-a=
ssignable, even if one of their types has a move-constructor that can propa=
gate an exception, then all they need to do is put in a field of their choo=
sing, analogous to boost::blank, as I.E. the first field of the variant (wh=
ich would satisfy "B").</div><div><br></div><div>This should sati=
sfy everyone's needs and I don't think it's too controversial. =
It's efficient and gives the user control.</div></div></div></div><div =
class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e011605f406935705205a62d3--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 11:45:56 -0700
Raw View
--001a1134e212940e4005205a68fe
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 11:37 AM, Nevin Liber <nevin@eviloverlord.com>
wrote:
> On 22 September 2015 at 13:21, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> C) In the case that one of your types has a move constructor that can
>> throw and you do not have a type that has a default constructor that is
>> noexcept, then your overall variant just simply is not
>> move-assignable/copy-assignable. Everything works and is simple and there
>> is no invalid state.
>>
>
> That leads to non-portable code. Is
>
> variant<set<int>, unordered_set<int>>
>
> assignable?
>
If any type involved has a move constructor that's not noexcept, then it's
not assignable. If a type's move constructor's noexcept specification
varies between implementations and you need the type to be move-assignable,
then you can just put in an empty type, and your overall variant is
consistent between implementations (apart from exception specification).
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134e212940e4005205a68fe
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=
ue, Sep 22, 2015 at 11:37 AM, Nevin Liber <span dir=3D"ltr"><<a href=3D"=
mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.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"">On 22 September 2015 at 13:21, 'Matt Calabrese' via ISO=
C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:st=
d-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>><=
/span> wrote:<br></span><div class=3D"gmail_extra"><div class=3D"gmail_quot=
e"><span class=3D""><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 cl=
ass=3D"gmail_extra"><div class=3D"gmail_quote"><div>C) In the case that one=
of your types has a move constructor that can throw and you do not have a =
type that has a default constructor that is noexcept, then your overall var=
iant just simply is not move-assignable/copy-assignable. Everything works a=
nd is simple and there is no invalid state.<br></div></div></div></div></bl=
ockquote><div><br></div></span><div>That leads to non-portable code.=C2=A0 =
Is</div><div><br></div><div>variant<set<int>, unordered_set<int=
>>=C2=A0</div></div></div></div></blockquote><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quot=
e"><div><br></div><div>assignable?</div></div></div></div></blockquote><div=
><br></div><div>If any type involved has a move constructor that's not =
noexcept, then it's not assignable. If a type's move constructor=
9;s noexcept specification varies between implementations and you need the =
type to be move-assignable, then you can just put in an empty type, and you=
r overall variant is consistent between implementations (apart from excepti=
on specification).</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134e212940e4005205a68fe--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Tue, 22 Sep 2015 20:46:19 +0200
Raw View
--089e0103009ce7a2ac05205a6956
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 8:27 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 22 September 2015 at 13:25, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>
>> I'm happy with the decision to have an "Empty/invalid state of some
>> sort". The only modification I would make would be to call it the empty
>> value, default construct to it,
>>
>
> Which was discussed and rejected.
>
I just read the minutes. It was 10 people in the room and the first vote
on that issue was split down the middle. I think there were a lot of
people not present that hold the position that if there is to be a
reachable empty state then it should behave like every other type that has
such an empty state. I expect the default-construct-to-empty to be
reopened at Kona.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0103009ce7a2ac05205a6956
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=
ue, Sep 22, 2015 at 8:27 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span>On 22 Septembe=
r 2015 at 13:25, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:and=
rewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a>></sp=
an> wrote:<br></span><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<span><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmai=
l_extra"><div class=3D"gmail_quote"><div>I'm happy with the decision to=
have an "Empty/invalid state of some sort".=C2=A0 The only modif=
ication I would make would be to call it the empty value, default construct=
to it, </div></div></div></div></blockquote><div><br></div></span><div>Whi=
ch was discussed and rejected.</div><div></div></div></div></div></blockquo=
te></div><br></div><div class=3D"gmail_extra">I just read the minutes.=C2=
=A0 It was 10 people in the room and the first vote on that issue was split=
down the middle.=C2=A0 I think there were a lot of people not present that=
hold the position that if there is to be a reachable empty state then it s=
hould behave like every other type that has such an empty state.=C2=A0 I ex=
pect the default-construct-to-empty to be reopened at Kona.</div><div class=
=3D"gmail_extra"><br></div><div class=3D"gmail_extra"><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0103009ce7a2ac05205a6956--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 11:54:45 -0700
Raw View
--001a1134beb20eb90205205a88fa
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
> On Tue, Sep 22, 2015 at 2:21 PM, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>>
>> I gave what I think is best of all these options (all of the following
>> describe a single option):
>>
>> A) In the case that no types involved have a move constructor that can
>> throw, there is no problem. Everything works and is simple and there is no
>> invalid state.
>>
>> B) In the case that at least one type has a move constructor that can
>> throw, but one of your types has a default constructor that is noexcept,
>> you can construct that in the even that your variant's move-assignment
>> operator does not propagate an exception. Everything works and is simple
>> and there is no invalid state.
>>
>
> That sounded reasonable to me at first, however:
>
> I have a drawing program. It can create squares and circles and
> triangles, and lay them out, group them (hierarchy) etc.
> The user selects a triangle, and clicks "Change to Circle". The triangle
> becomes a square.
>
> Is that OK?
>
> To me, the only correct answer is the strong exception guarantee, and
> double-buffering (internal, non-allocated - don't want to bring allocators
> into this).
>
Why? I'm all for having the strong exception guarantee if it makes sense
and is implementable without sacrifice, but that's simply not the case
here. Realistically we can only efficiently meet the basic exception
guarantee in the event that one of the move-constructors can throw. If you
need to go back to the previous state when an exception propagates, a user
would have to take that into consideration (this is always the case for any
type with the basic exception guarantee, and is always tricky when a type
has a move constructor that can throw).
On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
> If I don't have the strong exception guarantee, I need to implement it
> externally. ie keep a backup (probably via the undo buffer).
>
In practice, a user can store the field via a unique_ptr instead of
directly, such that the field in question now has a noexcept move
constructor.
On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
> But wait, assignment _didn't_ fail. Or at least I can't tell it failed.
> It tried to tell me (via the exception) but the exception was swallowed. I
> don't know that I need to restore to a sane state.
>
You can tell that it failed. The exception isn't swallowed, it still
propagates. The implementation only constructs the fallback type to restore
the invariants in the case that an exception does, indeed, propagate. If
there is no suitable fallback type, then the user gets a compile error.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134beb20eb90205205a88fa
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=
ue, Sep 22, 2015 at 11:44 AM, Tony V E <span dir=3D"ltr"><<a href=3D"mai=
lto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=
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"><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote"><span class=3D"">On Tue, Sep 22, 2015 at 2:21 PM, '=
Matt Calabrese' via ISO C++ Standard - Future Proposals <span dir=3D"lt=
r"><<a href=3D"mailto:std-proposals@isocpp.org" target=3D"_blank">std-pr=
oposals@isocpp.org</a>></span> wrote:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rg=
b(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><=
div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>I gave what I thi=
nk is best of all these options (all of the following describe a single opt=
ion):</div><div><br></div><div>A) In the case that no types involved have a=
move constructor that can throw, there is no problem. Everything works and=
is simple and there is no invalid state.</div><div><br></div><div>B) In th=
e case that at least one type has a move constructor that can throw, but on=
e of your types has a default constructor that is noexcept, you can constru=
ct that in the even that your variant's move-assignment operator does n=
ot propagate an exception. Everything works and is simple and there is no i=
nvalid state.</div></div></div></div></blockquote><div><br></div></span><di=
v>That sounded reasonable to me at first, however:<br><br></div><div>I have=
a drawing program.=C2=A0 It can create squares and circles and triangles, =
and lay them out, group them (hierarchy) etc.<br></div><div>The user select=
s a triangle, and clicks "Change to Circle".=C2=A0 The triangle b=
ecomes a square.=C2=A0</div></div></div></div></blockquote><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"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><br></div><div>Is that OK?<br><br></div><div>To me, the only correct answ=
er is the strong exception guarantee, and double-buffering (internal, non-a=
llocated - don't want to bring allocators into this).<br></div></div></=
div></div></blockquote><div><br></div><div>Why? I'm all for having the =
strong exception guarantee if it makes sense and is implementable without s=
acrifice, but that's simply not the case here. Realistically we can onl=
y efficiently meet the basic exception guarantee in the event that one of t=
he move-constructors can throw. If you need to go back to the previous stat=
e when an exception propagates, a user would have to take that into conside=
ration (this is always the case for any type with the basic exception guara=
ntee, and is always tricky when a type has a move constructor that can thro=
w).</div><div><br></div><div>=C2=A0On Tue, Sep 22, 2015 at 11:44 AM, Tony V=
E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=
=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><div>If I don't have the strong exception guarantee, I need to impleme=
nt it externally.=C2=A0 ie keep a backup (probably via the undo buffer).</d=
iv></div></div></div></blockquote><div><br></div><div>In practice, a user c=
an store the field via a unique_ptr instead of directly, such that the fiel=
d in question now has a noexcept move constructor.</div><div><br></div><div=
>=C2=A0On Tue, Sep 22, 2015 at 11:44 AM, Tony V E=C2=A0<span dir=3D"ltr">&l=
t;<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.co=
m</a>></span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><div>But wait, assignment =
_didn't_ fail.=C2=A0 Or at least I can't tell it failed. It tried t=
o tell me (via the exception) but the exception was swallowed.=C2=A0 I don&=
#39;t know that I need to restore to a sane state.<br></div></div></div></d=
iv></blockquote><div><br></div><div>You can tell that it failed. The except=
ion isn't swallowed, it still propagates. The implementation only const=
ructs the fallback type to restore the invariants in the case that an excep=
tion does, indeed, propagate. If there is no suitable fallback type, then t=
he user gets a compile error.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134beb20eb90205205a88fa--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 22 Sep 2015 14:58:51 -0400
Raw View
--001a11c3124ab9cbed05205a9692
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 2:46 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> On Tue, Sep 22, 2015 at 8:27 PM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
>
>> On 22 September 2015 at 13:25, Andrew Tomazos <andrewtomazos@gmail.com>
>> wrote:
>>
>>
>>> I'm happy with the decision to have an "Empty/invalid state of some
>>> sort". The only modification I would make would be to call it the empty
>>> value, default construct to it,
>>>
>>
>> Which was discussed and rejected.
>>
>
> I just read the minutes. It was 10 people in the room and the first vote
> on that issue was split down the middle. I think there were a lot of
> people not present that hold the position that if there is to be a
> reachable empty state then it should behave like every other type that has
> such an empty state. I expect the default-construct-to-empty to be
> reopened at Kona.
>
>
>
Then let's not call it an empty state. Call it an error state (which it
currently is).
If it is the construction state, then I need to check for it.
Whereas if it is only on throwing-move, I can ignore it. Throwing moves
are rare - not just that their types are rare, but the conditions for
throwing are rare - ie typically _totally_ out of memory (ie can't allocate
16 bytes for a sentinel node). I'm happy to ignore those types and those
rare conditions. Which means if it is only on a move that throws, I can
ignore the error state.
P.S. If it is the construction state, you should also add a reset()
function, to be able to make it empty at any time. (Even if I don't like
empty-construct, I like proper APIs, so if we can construct that state, we
need reset().)
Tony
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c3124ab9cbed05205a9692
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 2:46 PM, Andrew Tomazos <span dir=3D"ltr"><<=
a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@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""><div class=3D"gmail_extra"><div class=3D"gmail_qu=
ote">On Tue, Sep 22, 2015 at 8:27 PM, Nevin Liber <span dir=3D"ltr"><<a =
href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord=
..com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,=
204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span>On 22=
September 2015 at 13:25, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"m=
ailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a=
>></span> wrote:<br></span><div class=3D"gmail_extra"><div class=3D"gmai=
l_quote"><span><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div clas=
s=3D"gmail_extra"><div class=3D"gmail_quote"><div>I'm happy with the de=
cision to have an "Empty/invalid state of some sort".=C2=A0 The o=
nly modification I would make would be to call it the empty value, default =
construct to it, </div></div></div></div></blockquote><div><br></div></span=
><div>Which was discussed and rejected.</div><div></div></div></div></div><=
/blockquote></div><br></div></span><div class=3D"gmail_extra">I just read t=
he minutes.=C2=A0 It was 10 people in the room and the first vote on that i=
ssue was split down the middle.=C2=A0 I think there were a lot of people no=
t present that hold the position that if there is to be a reachable empty s=
tate then it should behave like every other type that has such an empty sta=
te.=C2=A0 I expect the default-construct-to-empty to be reopened at Kona.</=
div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra"><br></d=
iv></div></blockquote><div><br></div><div>Then let's not call it an emp=
ty state.=C2=A0 Call it an error state (which it currently is).<br></div><d=
iv><br>If it is the construction state, then I need to check for it.<br></d=
iv><div><br>Whereas if it is only on throwing-move, I can ignore it.=C2=A0 =
Throwing moves are rare - not just that their types are rare, but the condi=
tions for throwing are rare - ie typically _totally_ out of memory (ie can&=
#39;t allocate 16 bytes for a sentinel node).=C2=A0 I'm happy to ignore=
those types and those rare conditions.=C2=A0 Which means if it is only on =
a move that throws, I can ignore the error state.<br><br></div><div>P.S. If=
it is the construction state, you should also add a reset() function, to b=
e able to make it empty at any time.=C2=A0 (Even if I don't like empty-=
construct, I like proper APIs, so if we can construct that state, we need r=
eset().)<br><br></div><div>Tony<br></div><blockquote class=3D"gmail_quote" =
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div class=3D"gmail_extra"></div></div><div class=3D"HOEnZb">=
<div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3124ab9cbed05205a9692--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 13:58:18 -0500
Raw View
--001a113d9f7a218e4705205a9711
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 13:46, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> I just read the minutes. It was 10 people in the room and the first vote
> on that issue was split down the middle.
>
And there were discussions after that.
While we did reach consensus, it was not unanimous (IIRC there was still
one dissenter in the room).
> I think there were a lot of people not present that hold the position that
> if there is to be a reachable empty state then it should behave like every
> other type that has such an empty state. I expect the
> default-construct-to-empty to be reopened at Kona.
>
Oh, I expect *every* design decision on variant (and possibly optional,
since it is a related type, as well as requiring move constructors to never
throw, either in the standard library or in the language) to be reopened in
Kona.
And there is a very real possibility that we won't have variant in the
standard at all, if committee members cannot come to consensus on what they
are willing to live with.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113d9f7a218e4705205a9711
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra">On 22 September 2015 at 13:46, =
Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.=
com" target=3D"_blank">andrewtomazos@gmail.com</a>></span> wrote:<br><di=
v 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 class=3D"gmail_=
extra">I just read the minutes.=C2=A0 It was 10 people in the room and the =
first vote on that issue was split down the middle.=C2=A0</div></blockquote=
><div><br></div><div>And there were discussions after that.</div><div><br><=
/div><div>While we did reach consensus, it was not unanimous (IIRC there wa=
s still one dissenter in the room).</div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div class=3D"gmail_extra"> I think there were a lot of peopl=
e not present that hold the position that if there is to be a reachable emp=
ty state then it should behave like every other type that has such an empty=
state.=C2=A0 I expect the default-construct-to-empty to be reopened at Kon=
a.</div></blockquote><div><br></div><div>Oh, I expect <i>every</i>=C2=A0des=
ign decision on variant (and possibly optional, since it is a related type,=
as well as requiring move constructors to never throw, either in the stand=
ard library or in the language) to be reopened in Kona.</div><div><br></div=
><div>And there is a very real possibility that we won't have variant i=
n the standard at all, if committee members cannot come to consensus on wha=
t they are willing to live with.</div></div>-- <br><div class=3D"gmail_sign=
ature">=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto=
:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=
=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113d9f7a218e4705205a9711--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 22 Sep 2015 15:12:35 -0400
Raw View
--001a11341a34d41fe705205ac745
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 2:54 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
>>
>> On Tue, Sep 22, 2015 at 2:21 PM, 'Matt Calabrese' via ISO C++ Standard -
>> Future Proposals <std-proposals@isocpp.org> wrote:
>>>
>>> I gave what I think is best of all these options (all of the following
>>> describe a single option):
>>>
>>> A) In the case that no types involved have a move constructor that can
>>> throw, there is no problem. Everything works and is simple and there is no
>>> invalid state.
>>>
>>> B) In the case that at least one type has a move constructor that can
>>> throw, but one of your types has a default constructor that is noexcept,
>>> you can construct that in the even that your variant's move-assignment
>>> operator does not propagate an exception. Everything works and is simple
>>> and there is no invalid state.
>>>
>>
>> That sounded reasonable to me at first, however:
>>
>> I have a drawing program. It can create squares and circles and
>> triangles, and lay them out, group them (hierarchy) etc.
>> The user selects a triangle, and clicks "Change to Circle". The triangle
>> becomes a square.
>>
>
>> Is that OK?
>>
>> To me, the only correct answer is the strong exception guarantee, and
>> double-buffering (internal, non-allocated - don't want to bring allocators
>> into this).
>>
>
> Why? I'm all for having the strong exception guarantee if it makes sense
> and is implementable without sacrifice, but that's simply not the case
> here. Realistically we can only efficiently meet the basic exception
> guarantee in the event that one of the move-constructors can throw. If you
> need to go back to the previous state when an exception propagates, a user
> would have to take that into consideration (this is always the case for any
> type with the basic exception guarantee, and is always tricky when a type
> has a move constructor that can throw).
>
If I only have basic, I end up writing strong myself, in a more convoluted
way. Thus I just rather have strong from the start.
>
> On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> If I don't have the strong exception guarantee, I need to implement it
>> externally. ie keep a backup (probably via the undo buffer).
>>
>
> In practice, a user can store the field via a unique_ptr instead of
> directly, such that the field in question now has a noexcept move
> constructor.
>
Allocation. No thanks.
>
> On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> But wait, assignment _didn't_ fail. Or at least I can't tell it failed.
>> It tried to tell me (via the exception) but the exception was swallowed. I
>> don't know that I need to restore to a sane state.
>>
>
> You can tell that it failed. The exception isn't swallowed, it still
> propagates. The implementation only constructs the fallback type to restore
> the invariants in the case that an exception does, indeed, propagate. If
> there is no suitable fallback type, then the user gets a compile error.
>
Ah, OK. Not quite as bad then.
But in the case of a collection of variants (ie a vector, or my layout
document), in order to know _which_ variant failed, I probably need to use
a specific type (blank_t, null_t, error_t, etc) not just Rectangle, as my
default constructible, so I can easily find the offending variant.
Or catch my exceptions closer to their source (I'd prefer not).
At that point, a built-in error state (Lenexa variant) seems just as good.
Or better, since it can only happen on failure, whereas blank_t can happen
throughout the code.
As for the ...else compile erorr, like Nevin mentioned, this might be too
drastic, making variant unusable. Or usable but not portable. (I'd hate
to find out I need to add blank_t years later when we decide to port. And
also update all my visitors. If I should have known that blank_t was
needed, well, just build it into variant.)
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11341a34d41fe705205ac745
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 2:54 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Tue, Sep 22, 2015=
at 11:44 AM, Tony V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gma=
il.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> wrote:</span><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gm=
ail_quote"><span><span class=3D"">On Tue, Sep 22, 2015 at 2:21 PM, 'Mat=
t Calabrese' via ISO C++ Standard - Future Proposals <span dir=3D"ltr">=
<<a href=3D"mailto:std-proposals@isocpp.org" target=3D"_blank">std-propo=
sals@isocpp.org</a>></span> wrote:</span><span class=3D""><blockquote cl=
ass=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:1e=
x"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><=
div>I gave what I think is best of all these options (all of the following =
describe a single option):</div><div><br></div><div>A) In the case that no =
types involved have a move constructor that can throw, there is no problem.=
Everything works and is simple and there is no invalid state.</div><div><b=
r></div><div>B) In the case that at least one type has a move constructor t=
hat can throw, but one of your types has a default constructor that is noex=
cept, you can construct that in the even that your variant's move-assig=
nment operator does not propagate an exception. Everything works and is sim=
ple and there is no invalid state.</div></div></div></div></blockquote><div=
><br></div></span></span><span class=3D""><div>That sounded reasonable to m=
e at first, however:<br><br></div><div>I have a drawing program.=C2=A0 It c=
an create squares and circles and triangles, and lay them out, group them (=
hierarchy) etc.<br></div><div>The user selects a triangle, and clicks "=
;Change to Circle".=C2=A0 The triangle becomes a square.=C2=A0</div></=
span></div></div></div></blockquote><span class=3D""><blockquote class=3D"g=
mail_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 class=3D"gmail_quote"><div><br>=
</div><div>Is that OK?<br><br></div><div>To me, the only correct answer is =
the strong exception guarantee, and double-buffering (internal, non-allocat=
ed - don't want to bring allocators into this).<br></div></div></div></=
div></blockquote><div><br></div></span><div>Why? I'm all for having the=
strong exception guarantee if it makes sense and is implementable without =
sacrifice, but that's simply not the case here. Realistically we can on=
ly efficiently meet the basic exception guarantee in the event that one of =
the move-constructors can throw. If you need to go back to the previous sta=
te when an exception propagates, a user would have to take that into consid=
eration (this is always the case for any type with the basic exception guar=
antee, and is always tricky when a type has a move constructor that can thr=
ow).</div></div></div></div></blockquote><div><br></div><div><br>If I only =
have basic, I end up writing strong myself, in a more convoluted way.=C2=A0=
Thus I just rather have strong from the start.<br>=C2=A0<br></div><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 class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><span class=3D""><div><br></div><div>=C2=A0On Tue, Sep 2=
2, 2015 at 11:44 AM, Tony V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:=
tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=
=A0wrote:</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 class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div>If I don't have the strong exception g=
uarantee, I need to implement it externally.=C2=A0 ie keep a backup (probab=
ly via the undo buffer).</div></div></div></div></blockquote><div><br></div=
></span><div>In practice, a user can store the field via a unique_ptr inste=
ad of directly, such that the field in question now has a noexcept move con=
structor.</div></div></div></div></blockquote><div><br></div><div>Allocatio=
n. No thanks.<br>=C2=A0<br></div><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 class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D"=
"><div><br></div><div>=C2=A0On Tue, Sep 22, 2015 at 11:44 AM, Tony V E=C2=
=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_b=
lank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>But wait, assignment _didn't_ fail.=C2=A0 Or at least I can't tell=
it failed. It tried to tell me (via the exception) but the exception was s=
wallowed.=C2=A0 I don't know that I need to restore to a sane state.<br=
></div></div></div></div></blockquote><div><br></div></span><div>You can te=
ll that it failed. The exception isn't swallowed, it still propagates. =
The implementation only constructs the fallback type to restore the invaria=
nts in the case that an exception does, indeed, propagate. If there is no s=
uitable fallback type, then the user gets a compile error.</div></div></div=
></div></blockquote><div><br></div><div>Ah, OK.=C2=A0 Not quite as bad then=
..<br></div><div>But in the case of a collection of variants (ie a vector, o=
r my layout document), in order to know _which_ variant failed, I probably =
need to use a specific type (blank_t, null_t, error_t, etc) not just Rectan=
gle, as my default constructible, so I can easily find the offending varian=
t.<br></div><div>Or catch my exceptions closer to their source (I'd pre=
fer not).<br></div><div>At that point, a built-in error state (Lenexa varia=
nt) seems just as good. Or better, since it can only happen on failure, whe=
reas blank_t can happen throughout the code.<br><br></div><div>As for the .=
...else compile erorr, like Nevin mentioned, this might be too drastic, maki=
ng variant unusable.=C2=A0 Or usable but not portable.=C2=A0 (I'd hate =
to find out I need to add blank_t years later when we decide to port.=C2=A0=
And also update all my visitors.=C2=A0 If I should have known that blank_t=
was needed, well, just build it into variant.)<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11341a34d41fe705205ac745--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Tue, 22 Sep 2015 21:22:14 +0200
Raw View
--047d7bb04db062bda005205aea0e
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 8:58 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>
> On Tue, Sep 22, 2015 at 2:46 PM, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> On Tue, Sep 22, 2015 at 8:27 PM, Nevin Liber <nevin@eviloverlord.com>
>> wrote:
>>
>>> On 22 September 2015 at 13:25, Andrew Tomazos <andrewtomazos@gmail.com>
>>> wrote:
>>>
>>>
>>>> I'm happy with the decision to have an "Empty/invalid state of some
>>>> sort". The only modification I would make would be to call it the empty
>>>> value, default construct to it,
>>>>
>>>
>>> Which was discussed and rejected.
>>>
>>
>> I just read the minutes. It was 10 people in the room and the first vote
>> on that issue was split down the middle. I think there were a lot of
>> people not present that hold the position that if there is to be a
>> reachable empty state then it should behave like every other type that has
>> such an empty state. I expect the default-construct-to-empty to be
>> reopened at Kona.
>>
>>
>>
> Then let's not call it an empty state. Call it an error state (which it
> currently is).
>
> If it is the construction state, then I need to check for it.
>
Same as std::any, std::function, std::thread, std::all_the_ptrs, etc etc.
And what's more with variant you have to branch on the discriminator
anyway. It's just one more branch in the switch.
For each type T in the variant, the variant can either be holding T or
not. Having an empty value doesn't change that.
Whereas if it is only on throwing-move, I can ignore it.
>
It's precisely because of the fact that people will ignore it if it is rare
that it will cause bugs.
Also, I don't think a fully-embraced empty value will necessarily be
limited to being reachable via throwing moves in the most elegant design.
I think it entails other (good) design decisions.
Throwing moves are rare - not just that their types are rare, but the
> conditions for throwing are rare - ie typically _totally_ out of memory (ie
> can't allocate 16 bytes for a sentinel node). I'm happy to ignore those
> types and those rare conditions. Which means if it is only on a move that
> throws, I can ignore the error state.
>
> P.S. If it is the construction state, you should also add a reset()
> function, to be able to make it empty at any time. (Even if I don't like
> empty-construct, I like proper APIs, so if we can construct that state, we
> need reset().)
>
> Tony
>
>> --
>>
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7bb04db062bda005205aea0e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 8:58 PM, Tony V E <span dir=3D"ltr"><<a href=
=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.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"><br><div =
class=3D"gmail_extra"><br><div class=3D"gmail_quote"><div><div>On Tue, Sep =
22, 2015 at 2:46 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto=
:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.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><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote">On Tue, Sep 22, 2015 at =
8:27 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"mailto:nevin@evilover=
lord.com" target=3D"_blank">nevin@eviloverlord.com</a>></span> wrote:<br=
><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"><span>On 22 September 2015 at 13:25, And=
rew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com=
" target=3D"_blank">andrewtomazos@gmail.com</a>></span> wrote:<br></span=
><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span><div>=C2=A0</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 class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div>I'm happy with the decision to have an "Empt=
y/invalid state of some sort".=C2=A0 The only modification I would mak=
e would be to call it the empty value, default construct to it, </div></div=
></div></div></blockquote><div><br></div></span><div>Which was discussed an=
d rejected.</div><div></div></div></div></div></blockquote></div><br></div>=
</span><div class=3D"gmail_extra">I just read the minutes.=C2=A0 It was 10 =
people in the room and the first vote on that issue was split down the midd=
le.=C2=A0 I think there were a lot of people not present that hold the posi=
tion that if there is to be a reachable empty state then it should behave l=
ike every other type that has such an empty state.=C2=A0 I expect the defau=
lt-construct-to-empty to be reopened at Kona.</div><div class=3D"gmail_extr=
a"><br></div><div class=3D"gmail_extra"><br></div></div></blockquote><div><=
br></div></div></div><div>Then let's not call it an empty state.=C2=A0 =
Call it an error state (which it currently is).<br></div><div><br>If it is =
the construction state, then I need to check for it.</div></div></div></div=
></blockquote><div><br></div><div>Same as std::any, std::function, std::thr=
ead, std::all_the_ptrs, etc etc.</div><div><br></div><div>And what's mo=
re with variant you have to branch on the discriminator anyway.=C2=A0 It=
9;s just one more branch in the switch.</div><div><br></div><div>For each t=
ype T in the variant, the variant can either be holding T or not.=C2=A0 Hav=
ing an empty value doesn't change that.</div><div><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div>Whereas if it is only on throwing-move, I can ignore =
it.</div></div></div></div></blockquote><div><br></div><div>It's precis=
ely because of the fact that people will ignore it if it is rare that it wi=
ll cause bugs.</div><div><br></div><div>Also, I don't think a fully-emb=
raced empty value will necessarily be limited to being reachable via throwi=
ng moves in the most elegant design.=C2=A0 I think it entails other (good) =
design decisions.</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"><div d=
ir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Throw=
ing moves are rare - not just that their types are rare, but the conditions=
for throwing are rare - ie typically _totally_ out of memory (ie can't=
allocate 16 bytes for a sentinel node).=C2=A0 I'm happy to ignore thos=
e types and those rare conditions.=C2=A0 Which means if it is only on a mov=
e that throws, I can ignore the error state.<br><br></div><div>P.S. If it i=
s the construction state, you should also add a reset() function, to be abl=
e to make it empty at any time.=C2=A0 (Even if I don't like empty-const=
ruct, I like proper APIs, so if we can construct that state, we need reset(=
).)<br><br></div><div>Tony<br></div><span><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div class=3D"gmail_extra"></div></div><div><div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></span></div><br></div></div><div><div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bb04db062bda005205aea0e--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 22 Sep 2015 15:29:32 -0400
Raw View
--001a1141eeec80a1e805205b047f
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 3:22 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
>
>
> On Tue, Sep 22, 2015 at 8:58 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>>
>>
>> On Tue, Sep 22, 2015 at 2:46 PM, Andrew Tomazos <andrewtomazos@gmail.com>
>> wrote:
>>
>>> On Tue, Sep 22, 2015 at 8:27 PM, Nevin Liber <nevin@eviloverlord.com>
>>> wrote:
>>>
>>>> On 22 September 2015 at 13:25, Andrew Tomazos <andrewtomazos@gmail.com>
>>>> wrote:
>>>>
>>>>
>>>>> I'm happy with the decision to have an "Empty/invalid state of some
>>>>> sort". The only modification I would make would be to call it the empty
>>>>> value, default construct to it,
>>>>>
>>>>
>>>> Which was discussed and rejected.
>>>>
>>>
>>> I just read the minutes. It was 10 people in the room and the first
>>> vote on that issue was split down the middle. I think there were a lot of
>>> people not present that hold the position that if there is to be a
>>> reachable empty state then it should behave like every other type that has
>>> such an empty state. I expect the default-construct-to-empty to be
>>> reopened at Kona.
>>>
>>>
>>>
>> Then let's not call it an empty state. Call it an error state (which it
>> currently is).
>>
>> If it is the construction state, then I need to check for it.
>>
>
> Same as std::any, std::function, std::thread, std::all_the_ptrs, etc etc.
>
> And what's more with variant you have to branch on the discriminator
> anyway. It's just one more branch in the switch.
>
> For each type T in the variant, the variant can either be holding T or
> not. Having an empty value doesn't change that.
>
> Whereas if it is only on throwing-move, I can ignore it.
>>
>
> It's precisely because of the fact that people will ignore it if it is
> rare that it will cause bugs.
>
> Also, I don't think a fully-embraced empty value will necessarily be
> limited to being reachable via throwing moves in the most elegant design.
> I think it entails other (good) design decisions.
>
I don't like that variant<int, long> (or <Foo,Bar>, because I don't write
throwing moves) suddenly needs to handle that third case, that would
otherwise be guaranteed to never happen.
I can live with the empty state when has T throwing moves (even if rare),
but it bothers me that it is also added for "sane" :-) classes.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1141eeec80a1e805205b047f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 3:22 PM, Andrew Tomazos <span dir=3D"ltr"><<=
a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@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"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quote"><spa=
n class=3D"">On Tue, Sep 22, 2015 at 8:58 PM, Tony V E <span dir=3D"ltr">&l=
t;<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.co=
m</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<br><div class=3D"gmail_extra"><br><div class=3D"gmail_quote"><div><div>On =
Tue, Sep 22, 2015 at 2:46 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><span><div class=3D"gmail_extra"><div class=3D"gmail_quote">On Tue, Sep 22=
, 2015 at 8:27 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"mailto:nevi=
n@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>></span>=
wrote:<br><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-st=
yle:solid;padding-left:1ex"><div dir=3D"ltr"><span>On 22 September 2015 at =
13:25, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos=
@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a>></span> wrote:=
<br></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-=
style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><=
div class=3D"gmail_quote"><div>I'm happy with the decision to have an &=
quot;Empty/invalid state of some sort".=C2=A0 The only modification I =
would make would be to call it the empty value, default construct to it, </=
div></div></div></div></blockquote><div><br></div></span><div>Which was dis=
cussed and rejected.</div><div></div></div></div></div></blockquote></div><=
br></div></span><div class=3D"gmail_extra">I just read the minutes.=C2=A0 I=
t was 10 people in the room and the first vote on that issue was split down=
the middle.=C2=A0 I think there were a lot of people not present that hold=
the position that if there is to be a reachable empty state then it should=
behave like every other type that has such an empty state.=C2=A0 I expect =
the default-construct-to-empty to be reopened at Kona.</div><div class=3D"g=
mail_extra"><br></div><div class=3D"gmail_extra"><br></div></div></blockquo=
te><div><br></div></div></div><div>Then let's not call it an empty stat=
e.=C2=A0 Call it an error state (which it currently is).<br></div><div><br>=
If it is the construction state, then I need to check for it.</div></div></=
div></div></blockquote><div><br></div></span><div>Same as std::any, std::fu=
nction, std::thread, std::all_the_ptrs, etc etc.</div><div><br></div><div>A=
nd what's more with variant you have to branch on the discriminator any=
way.=C2=A0 It's just one more branch in the switch.</div><div><br></div=
><div>For each type T in the variant, the variant can either be holding T o=
r not.=C2=A0 Having an empty value doesn't change that.</div><span clas=
s=3D""><div><br></div><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 =
class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Whereas if it is only=
on throwing-move, I can ignore it.</div></div></div></div></blockquote><di=
v><br></div></span><div>It's precisely because of the fact that people =
will ignore it if it is rare that it will cause bugs.</div><div><br></div><=
div>Also, I don't think a fully-embraced empty value will necessarily b=
e limited to being reachable via throwing moves in the most elegant design.=
=C2=A0 I think it entails other (good) design decisions.</div></div></div><=
/div></blockquote><div><br><br></div></div>I don't like that variant<=
;int, long> (or <Foo,Bar>, because I don't write throwing move=
s) suddenly needs to handle that third case, that would otherwise be guaran=
teed to never happen.<br><br></div><div class=3D"gmail_extra">I can live wi=
th the empty state when has T throwing moves (even if rare), but it bothers=
me that it is also added for "sane" :-) classes.<br><br></div><d=
iv class=3D"gmail_extra">Tony<br><br></div><div class=3D"gmail_extra"><br><=
/div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1141eeec80a1e805205b047f--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Tue, 22 Sep 2015 21:34:32 +0200
Raw View
--047d7b874e5062eba105205b1667
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 22 September 2015 at 13:46, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> I just read the minutes. It was 10 people in the room and the first vote
>> on that issue was split down the middle.
>>
>
> And there were discussions after that.
>
> While we did reach consensus, it was not unanimous (IIRC there was still
> one dissenter in the room).
>
>
>> I think there were a lot of people not present that hold the position
>> that if there is to be a reachable empty state then it should behave like
>> every other type that has such an empty state. I expect the
>> default-construct-to-empty to be reopened at Kona.
>>
>
> Oh, I expect *every* design decision on variant (and possibly optional,
> since it is a related type, as well as requiring move constructors to never
> throw, either in the standard library or in the language) to be reopened in
> Kona.
>
> And there is a very real possibility that we won't have variant in the
> standard at all, if committee members cannot come to consensus on what they
> are willing to live with.
>
If it drags on I think people will soften their stances. It was just a
little early at Lenexa and the group was too small. I think the 1000+
messages are a sign that people really want std::variant, so that will
motivate consensus in the long run. (I hope! :) )
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b874e5062eba105205b1667
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=
ue, Sep 22, 2015 at 8:58 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</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"><div c=
lass=3D"gmail_extra"><span class=3D"">On 22 September 2015 at 13:46, Andrew=
Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" t=
arget=3D"_blank">andrewtomazos@gmail.com</a>></span> wrote:<br></span><d=
iv class=3D"gmail_quote"><span class=3D""><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv class=3D"gmail_extra">I just read the minutes.=C2=A0 It was 10 people in=
the room and the first vote on that issue was split down the middle.=C2=A0=
</div></blockquote><div><br></div></span><div>And there were discussions af=
ter that.</div><div><br></div><div>While we did reach consensus, it was not=
unanimous (IIRC there was still one dissenter in the room).</div><span cla=
ss=3D""><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"gmail=
_extra"> I think there were a lot of people not present that hold the posit=
ion that if there is to be a reachable empty state then it should behave li=
ke every other type that has such an empty state.=C2=A0 I expect the defaul=
t-construct-to-empty to be reopened at Kona.</div></blockquote><div><br></d=
iv></span><div>Oh, I expect <i>every</i>=C2=A0design decision on variant (a=
nd possibly optional, since it is a related type, as well as requiring move=
constructors to never throw, either in the standard library or in the lang=
uage) to be reopened in Kona.</div><div><br></div><div>And there is a very =
real possibility that we won't have variant in the standard at all, if =
committee members cannot come to consensus on what they are willing to live=
with.</div></div></div></div></blockquote><div>=C2=A0</div><div>If it drag=
s on I think people will soften their stances.=C2=A0 It was just a little e=
arly at Lenexa and the group was too small.=C2=A0 I think the 1000+ message=
s are a sign that people really want std::variant, so that will motivate co=
nsensus in the long run. =C2=A0(I hope! :) )</div></div></div><div class=3D=
"gmail_extra"><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b874e5062eba105205b1667--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 13:43:47 -0700
Raw View
--001a1134e2120a2a3d05205c0ed4
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 12:12 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>
> On Tue, Sep 22, 2015 at 2:54 PM, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
>>>
>>> On Tue, Sep 22, 2015 at 2:21 PM, 'Matt Calabrese' via ISO C++ Standard -
>>> Future Proposals <std-proposals@isocpp.org> wrote:
>>>>
>>>> I gave what I think is best of all these options (all of the following
>>>> describe a single option):
>>>>
>>>> A) In the case that no types involved have a move constructor that can
>>>> throw, there is no problem. Everything works and is simple and there is no
>>>> invalid state.
>>>>
>>>> B) In the case that at least one type has a move constructor that can
>>>> throw, but one of your types has a default constructor that is noexcept,
>>>> you can construct that in the even that your variant's move-assignment
>>>> operator does not propagate an exception. Everything works and is simple
>>>> and there is no invalid state.
>>>>
>>>
>>> That sounded reasonable to me at first, however:
>>>
>>> I have a drawing program. It can create squares and circles and
>>> triangles, and lay them out, group them (hierarchy) etc.
>>> The user selects a triangle, and clicks "Change to Circle". The
>>> triangle becomes a square.
>>>
>>
>>> Is that OK?
>>>
>>> To me, the only correct answer is the strong exception guarantee, and
>>> double-buffering (internal, non-allocated - don't want to bring allocators
>>> into this).
>>>
>>
>> Why? I'm all for having the strong exception guarantee if it makes sense
>> and is implementable without sacrifice, but that's simply not the case
>> here. Realistically we can only efficiently meet the basic exception
>> guarantee in the event that one of the move-constructors can throw. If you
>> need to go back to the previous state when an exception propagates, a user
>> would have to take that into consideration (this is always the case for any
>> type with the basic exception guarantee, and is always tricky when a type
>> has a move constructor that can throw).
>>
>
>
> If I only have basic, I end up writing strong myself, in a more convoluted
> way. Thus I just rather have strong from the start.
>
I don't think that's a reasonable rationale. If you start with a basic
guarantee, you are not impacting people who only need the basic guarantee,
and people who need to restore the old state can generally do so if they
need to. On the other hand, if you start with the strong guarantee where it
doesn't naturally fit (I.E. requires double storage and internally a way to
keep track of which location holds the actual instance), then a user can't
avoid that overhead even when they don't need it, and in the case of double
storage, you're paying for that overhead everywhere even though you only
propagate an exception in an "exceptional" case. In general (I.E. even
separate from variant), with a copyable type that has a noexcept move, you
can easily get the same effect of the strong guarantee by way of a type
that only satisfies the basic guarantee. You copy out a backup and then
move-assign to restore the backup if an exception propagates somewhere (or
you can sometimes do something more specific to the type). Note that this
kind of restoration is really only reliable if the type in question has a
noexcept move anyway.
On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> If I don't have the strong exception guarantee, I need to implement it
>>> externally. ie keep a backup (probably via the undo buffer).
>>>
>>
>> In practice, a user can store the field via a unique_ptr instead of
>> directly, such that the field in question now has a noexcept move
>> constructor.
>>
>
> Allocation. No thanks.
>
Two things -- first, if you have a move-constructor that can throw, that
often already means it's because it needs to do dynamic memory allocation,
so I don't really buy the avoidance at this level of abstraction. Second,
using unique_ptr (or similar indirection solutions) does not necessarily
imply dynamic memory allocation at all. It can just be a pointer to some
local storage. You can even couple it at a higher level.
Really, though, I just have to recommend that you embrace the basic
guarantee. The strong guarantee was never intended as the "default"
guarantee to implement. Not that original intent really matters if you
truly disagree, but understand that relying on the basic guarantee is not
outlandish, but rather it's suggested practice by the original
specification of the guarantees. We already have operations in the standard
library that only satisfy the basic guarantee, and in my opinion that is a
very good thing.
That said, the strong guarantee is simply not implementable without some
serious compromises here, and so we shouldn't try to force the type to meet
it. If one of the fields has a move constructor that can throw and you have
a fallback type, just accept that your variant's copy/move operations only
meet the basic guarantee. If all of your types have a move constructor that
is noexcept, then your variant's move operations meets the nothrow
guarantee and the copy assignment meets the minimum guarantee of that of
the corresponding fields. Forcing the strong guarantee punishes those who
do not need it and it also complicates the implementation.
Regarding the more general point of the exception guarantees, perhaps a bit
subjective but I think is difficult to deny. The guarantee of any operation
should be dependent on what is feasible to implement, and not simply on
what people want. If we only cared about what people wanted, separate from
what is feasible to implement, we would never have an operation that
specifies anything less than the strong guarantee (or really the nothrow
guarantee, for that matter, if we're talking about ideals here), but that's
simply not realistic for many types and operations, and it's really not
feasible here. That's okay and also nothing particularly unique to a
variant. Not all types in the standard library have operations that meet
the strong guarantee, and this would just happen to be one of those types.
Also, apart from all of this, something very important to realize is that
if you have an "invalid" state, then you still are only meeting the basic
guarantee, so this particular point does not differ! The solution I suggest
just gets you there without introducing an unnecessary and separate kind of
state.
> On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> But wait, assignment _didn't_ fail. Or at least I can't tell it failed.
>>> It tried to tell me (via the exception) but the exception was swallowed. I
>>> don't know that I need to restore to a sane state.
>>>
>>
>> You can tell that it failed. The exception isn't swallowed, it still
>> propagates. The implementation only constructs the fallback type to restore
>> the invariants in the case that an exception does, indeed, propagate. If
>> there is no suitable fallback type, then the user gets a compile error.
>>
>
> Ah, OK. Not quite as bad then.
> But in the case of a collection of variants (ie a vector, or my layout
> document), in order to know _which_ variant failed
>
How is this different from dealing with exceptions for any type that
encapsulates instances of other types? AFAICT, it's not unique to variant.
> On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
> At that point, a built-in error state (Lenexa variant) seems just as good.
> Or better, since it can only happen on failure, whereas blank_t can happen
> throughout the code.
>
The problem with an "invalid" state is that it weakens the types invariants
and either necessitates adding preconditions to all (or most) other
functions, such as visitation, that previously didn't have to be there, or
it requires special handling for those operations. For instance, what
happens if you visit something in the invalid state? Is this UB? If you
don't want it UB, does the visitation result in receiving a tag
representing this invalid state, such that people can handle it? If the
latter, the user could/should have handled it earlier. If they want to
handle it during visitation, they could have, in my suggested solution,
just put in some dummy type. As well, if you allow visitation of an invalid
state, it means that all visitors need to have an overload that handles the
state (unless it is suggested that by default, if such a case is
encountered and there is no overload, then you have UB). All of this is
just unnecessarily hairy for the specification, for the implementation, and
for the user. Avoiding the empty state is simpler to specify, works
perfectly and efficiently in the case that you have types with
noexcept-move (which in practice, I've personally found, is the common
case), and gives more control to the user in the odd case that they are
dealing with a type that has a move constructor that can throw. They get a
compile error if they try to use the copy-assignment/move-assignment in the
case that it is not implemented due to the conditions specified earlier,
and if they reach those conditions but never use
copy-assignment/move-assignment, things just work anyway. Also understand
that copy-construction and move-construction still work, so this type is
still very usable in many cases, as it can be passed to and returned from
functions, etc.. Finally, this approach prevents the library from making a
trade-off decision for users. Instead, the user gets to decide what is best
for their application. I.E. If they want something equivalent to an invalid
state, they can put it into their variant as a field themselves.
On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
> As for the ...else compile erorr, like Nevin mentioned, this might be too
> drastic, making variant unusable.
>
I don't understand why this would make it unusable. We shouldn't try to
define an operation that is not feasible to implement. There are solutions
described that will satisfy the user's needs and that does not require
making additions/sacrifices to variants state and invariants.
> On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <tvaneerd@gmail.com> wrote:
> (I'd hate to find out I need to add blank_t years later when we decide to
> port. And also update all my visitors. If I should have known that
> blank_t was needed, well, just build it into variant.)
>
That to me sounds like either A) a poor specification of a type that has a
noexcept specification in some implementation but not in others or B) an
initial mistake on the part of the user to not put a blank type in there to
begin with.
There also is one more solution to consider, that is of a similar ilk.
While the variant itself wouldn't be move-assignable or copy-assignable due
to the move-constructor being able to throw, an optional of such a variant
would, in fact, be able to be move-assignable or copy-assignable, though
this may not be immediately obvious. This is, perhaps, even more analogous
to the "invalid" state that was suggested, although is again more explicit
for the user and they only get it if they explicitly ask for it. It has
similar properties to the "invalid" state version in that by default you
get such an empty state and also that visitation of the underlying variant
does not forward the "invalid" state during visitation and there is also no
precondition for visitation regarding some hypothetical invalid state. This
is because the "invalid" state is represented at a higher level of
abstraction, separate from the variant itself. The underlying variant still
has the never empty guarantee. So everything works perfectly fine and
variant remains simple. An intelligent implementation can even share
storage for the discriminator between the optional and the variant,
especially if the optional is implemented on top of variant and there is a
more general optimization of that kind already present.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134e2120a2a3d05205c0ed4
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=
ue, Sep 22, 2015 at 12:12 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mai=
lto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=
wrote:<br><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-st=
yle:solid;padding-left:1ex"><div dir=3D"ltr"><br><div class=3D"gmail_extra"=
><br><div class=3D"gmail_quote"><span class=3D"">On Tue, Sep 22, 2015 at 2:=
54 PM, 'Matt Calabrese' via ISO C++ Standard - Future Proposals <sp=
an dir=3D"ltr"><<a href=3D"mailto:std-proposals@isocpp.org" target=3D"_b=
lank">std-proposals@isocpp.org</a>></span> wrote:<br><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><spa=
n>On Tue, Sep 22, 2015 at 11:44 AM, Tony V E <span dir=3D"ltr"><<a href=
=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>>=
</span> wrote:</span><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_=
extra"><div class=3D"gmail_quote"><span><span>On Tue, Sep 22, 2015 at 2:21 =
PM, 'Matt Calabrese' via ISO C++ Standard - Future Proposals <span =
dir=3D"ltr"><<a href=3D"mailto:std-proposals@isocpp.org" target=3D"_blan=
k">std-proposals@isocpp.org</a>></span> wrote:</span><span><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<div>I gave what I think is best of all these options (all of the following=
describe a single option):</div><div><br></div><div>A) In the case that no=
types involved have a move constructor that can throw, there is no problem=
.. Everything works and is simple and there is no invalid state.</div><div><=
br></div><div>B) In the case that at least one type has a move constructor =
that can throw, but one of your types has a default constructor that is noe=
xcept, you can construct that in the even that your variant's move-assi=
gnment operator does not propagate an exception. Everything works and is si=
mple and there is no invalid state.</div></div></div></div></blockquote><di=
v><br></div></span></span><span><div>That sounded reasonable to me at first=
, however:<br><br></div><div>I have a drawing program.=C2=A0 It can create =
squares and circles and triangles, and lay them out, group them (hierarchy)=
etc.<br></div><div>The user selects a triangle, and clicks "Change to=
Circle".=C2=A0 The triangle becomes a square.=C2=A0</div></span></div=
></div></div></blockquote><span><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div clas=
s=3D"gmail_extra"><div class=3D"gmail_quote"><div><br></div><div>Is that OK=
?<br><br></div><div>To me, the only correct answer is the strong exception =
guarantee, and double-buffering (internal, non-allocated - don't want t=
o bring allocators into this).<br></div></div></div></div></blockquote><div=
><br></div></span><div>Why? I'm all for having the strong exception gua=
rantee if it makes sense and is implementable without sacrifice, but that&#=
39;s simply not the case here. Realistically we can only efficiently meet t=
he basic exception guarantee in the event that one of the move-constructors=
can throw. If you need to go back to the previous state when an exception =
propagates, a user would have to take that into consideration (this is alwa=
ys the case for any type with the basic exception guarantee, and is always =
tricky when a type has a move constructor that can throw).</div></div></div=
></div></blockquote><div><br></div></span><div><br>If I only have basic, I =
end up writing strong myself, in a more convoluted way.=C2=A0 Thus I just r=
ather have strong from the start.<br></div></div></div></div></blockquote><=
div><br></div><div>I don't think that's a reasonable rationale. If =
you start with a basic guarantee, you are not impacting people who only nee=
d the basic guarantee, and people who need to restore the old state can gen=
erally do so if they need to. On the other hand, if you start with the stro=
ng guarantee where it doesn't naturally fit (I.E. requires double stora=
ge and internally a way to keep track of which location holds the actual in=
stance), then a user can't avoid that overhead even when they don't=
need it, and in the case of double storage, you're paying for that ove=
rhead everywhere even though you only propagate an exception in an "ex=
ceptional" case. In general (I.E. even separate from variant), with a =
copyable type that has a noexcept move, you can easily get the same effect =
of the strong guarantee by way of a type that only satisfies the basic guar=
antee. You copy out a backup and then move-assign to restore the backup if =
an exception propagates somewhere (or you can sometimes do something more s=
pecific to the type). Note that this kind of restoration is really only rel=
iable if the type in question has a noexcept move anyway.=C2=A0</div><div><=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div =
class=3D"gmail_quote"><div>=C2=A0 On Tue, Sep 22, 2015 at 11:44 AM, Tony V =
E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=
=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:</div><span class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><span><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"gm=
ail_extra"><div class=3D"gmail_quote"><div>If I don't have the strong e=
xception guarantee, I need to implement it externally.=C2=A0 ie keep a back=
up (probably via the undo buffer).</div></div></div></div></blockquote><div=
><br></div></span><div>In practice, a user can store the field via a unique=
_ptr instead of directly, such that the field in question now has a noexcep=
t move constructor.</div></div></div></div></blockquote><div><br></div></sp=
an><div>Allocation. No thanks.</div></div></div></div></blockquote><div><br=
></div><div>Two things -- first, if you have a move-constructor that can th=
row, that often already means it's because it needs to do dynamic memor=
y allocation, so I don't really buy the avoidance at this level of abst=
raction. Second, using unique_ptr (or similar indirection solutions) does n=
ot necessarily imply dynamic memory allocation at all. It can just be a poi=
nter to some local storage. You can even couple it at a higher level.</div>=
<div><br></div><div>Really, though, I just have to recommend that you embra=
ce the basic guarantee. The strong guarantee was never intended as the &quo=
t;default" guarantee to implement. Not that original intent really mat=
ters if you truly disagree, but understand that relying on the basic guaran=
tee is not outlandish, but rather it's suggested practice by the origin=
al specification of the guarantees. We already have operations in the stand=
ard library that only satisfy the basic guarantee, and in my opinion that i=
s a very good thing.</div><div><br></div><div>That said, the strong guarant=
ee is simply not implementable without some serious compromises here, and s=
o we shouldn't try to force the type to meet it. If one of the fields h=
as a move constructor that can throw and you have a fallback type, just acc=
ept that your variant's copy/move operations only meet the basic guaran=
tee. If all of your types have a move constructor that is noexcept, then yo=
ur variant's move operations meets the nothrow guarantee and the copy a=
ssignment meets the minimum guarantee of that of the corresponding fields. =
Forcing the strong guarantee punishes those who do not need it and it also =
complicates the implementation.</div><div><br></div><div>Regarding the more=
general point of the exception guarantees, perhaps a bit subjective but I =
think is difficult to deny. The guarantee of any operation should be depend=
ent on what is feasible to implement, and not simply on what people want. I=
f we only cared about what people wanted, separate from what is feasible to=
implement, we would never have an operation that specifies anything less t=
han the strong guarantee (or really the nothrow guarantee, for that matter,=
if we're talking about ideals here), but that's simply not realist=
ic for many types and operations, and it's really not feasible here. Th=
at's okay and also nothing particularly unique to a variant. Not all ty=
pes in the standard library have operations that meet the strong guarantee,=
and this would just happen to be one of those types.</div><div><br></div><=
div>Also, apart from all of this, something very important to realize is th=
at if you have an "invalid" state, then you still are only meetin=
g the basic guarantee, so this particular point does not differ! The soluti=
on I suggest just gets you there without introducing an unnecessary and sep=
arate kind of state.</div><div><br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>=C2=A0 On Tue, Sep 22, 2015 at 11:44 AM, Tony V E=C2=A0<span dir=3D"ltr">&=
lt;<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.c=
om</a>></span>=C2=A0wrote:</div><span class=3D""><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div d=
ir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span><blo=
ckquote 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;paddi=
ng-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmai=
l_quote"><div>But wait, assignment _didn't_ fail.=C2=A0 Or at least I c=
an't tell it failed. It tried to tell me (via the exception) but the ex=
ception was swallowed.=C2=A0 I don't know that I need to restore to a s=
ane state.<br></div></div></div></div></blockquote><div><br></div></span><d=
iv>You can tell that it failed. The exception isn't swallowed, it still=
propagates. The implementation only constructs the fallback type to restor=
e the invariants in the case that an exception does, indeed, propagate. If =
there is no suitable fallback type, then the user gets a compile error.</di=
v></div></div></div></blockquote><div><br></div></span><div>Ah, OK.=C2=A0 N=
ot quite as bad then.<br></div><div>But in the case of a collection of vari=
ants (ie a vector, or my layout document), in order to know _which_ variant=
failed</div></div></div></div></blockquote><div><br></div><div>How is this=
different from dealing with exceptions for any type that encapsulates inst=
ances of other types? AFAICT, it's not unique to variant.</div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div =
class=3D"gmail_quote"><div></div>On Tue, Sep 22, 2015 at 11:44 AM, Tony V E=
=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D=
"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:<div>At that point, a=
built-in error state (Lenexa variant) seems just as good. Or better, since=
it can only happen on failure, whereas blank_t can happen throughout the c=
ode.<br></div></div></div></div></blockquote><div><br></div><div>The proble=
m with an "invalid" state is that it weakens the types invariants=
and either necessitates adding preconditions to all (or most) other functi=
ons, such as visitation, that previously didn't have to be there, or it=
requires special handling for those operations. For instance, what happens=
if you visit something in the invalid state? Is this UB? If you don't =
want it UB, does the visitation result in receiving a tag representing this=
invalid state, such that people can handle it? If the latter, the user cou=
ld/should have handled it earlier. If they want to handle it during visitat=
ion, they could have, in my suggested solution, just put in some dummy type=
.. As well, if you allow visitation of an invalid state, it means that all v=
isitors need to have an overload that handles the state (unless it is sugge=
sted that by default, if such a case is encountered and there is no overloa=
d, then you have UB). All of this is just unnecessarily hairy for the speci=
fication, for the implementation, and for the user. Avoiding the empty stat=
e is simpler to specify, works perfectly and efficiently in the case that y=
ou have types with noexcept-move (which in practice, I've personally fo=
und, is the common case), and gives more control to the user in the odd cas=
e that they are dealing with a type that has a move constructor that can th=
row. They get a compile error if they try to use the copy-assignment/move-a=
ssignment in the case that it is not implemented due to the conditions spec=
ified earlier, and if they reach those conditions but never use copy-assign=
ment/move-assignment, things just work anyway. Also understand that copy-co=
nstruction and move-construction still work, so this type is still very usa=
ble in many cases, as it can be passed to and returned from functions, etc.=
.. Finally, this approach prevents the library from making a trade-off decis=
ion for users. Instead, the user gets to decide what is best for their appl=
ication. I.E. If they want something equivalent to an invalid state, they c=
an put it into their variant as a field themselves.=C2=A0</div><div><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 class=3D"gmail_extra"><div class=
=3D"gmail_quote">On Tue, Sep 22, 2015 at 11:44 AM, Tony V E=C2=A0<span dir=
=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvanee=
rd@gmail.com</a>></span>=C2=A0wrote:<div>As for the ...else compile eror=
r, like Nevin mentioned, this might be too drastic, making variant unusable=
..</div></div></div></div></blockquote><div><br></div><div>I don't under=
stand why this would make it unusable. We shouldn't try to define an op=
eration that is not feasible to implement. There are solutions described th=
at will satisfy the user's needs and that does not require making addit=
ions/sacrifices to variants state and invariants.</div><div><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><d=
iv class=3D"gmail_quote">On Tue, Sep 22, 2015 at 11:44 AM, Tony V E=C2=A0<s=
pan dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank"=
>tvaneerd@gmail.com</a>></span>=C2=A0wrote:<div>(I'd hate to find ou=
t I need to add blank_t years later when we decide to port.=C2=A0 And also =
update all my visitors.=C2=A0 If I should have known that blank_t was neede=
d, well, just build it into variant.)</div></div></div></div></blockquote><=
div><br></div><div>That to me sounds like either A) a poor specification of=
a type that has a noexcept specification in some implementation but not in=
others or B) an initial mistake on the part of the user to not put a blank=
type in there to begin with.</div><div><br></div><div>There also is one mo=
re solution to consider, that is of a similar ilk. While the variant itself=
wouldn't be move-assignable or copy-assignable due to the move-constru=
ctor being able to throw, an optional of such a variant would, in fact, be =
able to be move-assignable or copy-assignable, though this may not be immed=
iately obvious. This is, perhaps, even more analogous to the "invalid&=
quot; state that was suggested, although is again more explicit for the use=
r and they only get it if they explicitly ask for it. It has similar proper=
ties to the "invalid" state version in that by default you get su=
ch an empty state and also that visitation of the underlying variant does n=
ot forward the "invalid" state during visitation and there is als=
o no precondition for visitation regarding some hypothetical invalid state.=
This is because the "invalid" state is represented at a higher l=
evel of abstraction, separate from the variant itself. The underlying varia=
nt still has the never empty guarantee. So everything works perfectly fine =
and variant remains simple. An intelligent implementation can even share st=
orage for the discriminator between the optional and the variant, especiall=
y if the optional is implemented on top of variant and there is a more gene=
ral optimization of that kind already present.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134e2120a2a3d05205c0ed4--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 14:48:42 -0700 (PDT)
Raw View
------=_Part_1072_1800511789.1442958522723
Content-Type: multipart/alternative;
boundary="----=_Part_1073_3061159.1442958522723"
------=_Part_1073_3061159.1442958522723
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 22, 2015 at 3:34:34 PM UTC-4, Andrew Tomazos wrote:
>
> On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <ne...@eviloverlord.com
> <javascript:>> wrote:
>
>> On 22 September 2015 at 13:46, Andrew Tomazos <andrew...@gmail.com
>> <javascript:>> wrote:
>>
>>> I just read the minutes. It was 10 people in the room and the first
>>> vote on that issue was split down the middle.
>>>
>>
>> And there were discussions after that.
>>
>> While we did reach consensus, it was not unanimous (IIRC there was still
>> one dissenter in the room).
>>
>>
>>> I think there were a lot of people not present that hold the position
>>> that if there is to be a reachable empty state then it should behave like
>>> every other type that has such an empty state. I expect the
>>> default-construct-to-empty to be reopened at Kona.
>>>
>>
>> Oh, I expect *every* design decision on variant (and possibly optional,
>> since it is a related type, as well as requiring move constructors to never
>> throw, either in the standard library or in the language) to be reopened in
>> Kona.
>>
>> And there is a very real possibility that we won't have variant in the
>> standard at all, if committee members cannot come to consensus on what they
>> are willing to live with.
>>
>
> If it drags on I think people will soften their stances. It was just a
> little early at Lenexa and the group was too small. I think the 1000+
> messages are a sign that people really want std::variant, so that will
> motivate consensus in the long run. (I hope! :) )
>
Why does "consensus" mean "variants can be empty?" It seems to me that they
were able to get a good 90% consensus on N4542. It's only been commentary
since then that has reopened the issue.
Here's the thing I've never understood about the whole emptiness thing.
If I have need of a variant, and my use case is of the sort where that
variant may be empty, N4542 lets me do that by explicitly providing an
"empty" state, via the `monostate` type. If I want default constructing the
variant to create an empty one, I just make it the first argument in the
typelist.
I can even create a specific typedef for it:
template<typename ...Args>
using empty_variant = variant<monostate, Args...>;
However, if my use case for variant is such that it won't be empty... I
still have to cover the empty case. Even though I know that it *cannot* be
empty. If I use visitation, I have to handle the empty state. A state that
no variant will ever be in.
It seems to me that N4542 is the option that offers the most *freedom of
choice* to the user. Users who want empty variants have them, and users who
don't want empty variants don't have to have them.
Why do people want to dictate how I code?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1073_3061159.1442958522723
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Tuesday, September 22, 2015 at 3:34:34 PM UTC-4, Andrew Tomazos =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote">On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <span=
dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-m=
ailto=3D"srDDMnUfBgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'jav=
ascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;">ne...@eviloverlord.com</a>></span> wrote:<br><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div><span>On 22 September 2015 at 13:46, =
Andrew Tomazos <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"srDDMnUfBgAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">andrew...@gmail.com</a>></span> wrote:<b=
r></span><div class=3D"gmail_quote"><span><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv>I just read the minutes.=C2=A0 It was 10 people in the room and the firs=
t vote on that issue was split down the middle.=C2=A0</div></blockquote><di=
v><br></div></span><div>And there were discussions after that.</div><div><b=
r></div><div>While we did reach consensus, it was not unanimous (IIRC there=
was still one dissenter in the room).</div><span><div>=C2=A0</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div> I think there were a lot of people not present=
that hold the position that if there is to be a reachable empty state then=
it should behave like every other type that has such an empty state.=C2=A0=
I expect the default-construct-to-empty to be reopened at Kona.</div></blo=
ckquote><div><br></div></span><div>Oh, I expect <i>every</i>=C2=A0design de=
cision on variant (and possibly optional, since it is a related type, as we=
ll as requiring move constructors to never throw, either in the standard li=
brary or in the language) to be reopened in Kona.</div><div><br></div><div>=
And there is a very real possibility that we won't have variant in the =
standard at all, if committee members cannot come to consensus on what they=
are willing to live with.</div></div></div></div></blockquote><div>=C2=A0<=
/div><div>If it drags on I think people will soften their stances.=C2=A0 It=
was just a little early at Lenexa and the group was too small.=C2=A0 I thi=
nk the 1000+ messages are a sign that people really want std::variant, so t=
hat will motivate consensus in the long run. =C2=A0(I hope! :) )</div></div=
></div></div></blockquote><div><br>Why does "consensus" mean &quo=
t;variants can be empty?" It seems to me that they were able to get a =
good 90% consensus on N4542. It's only been commentary since then that =
has reopened the issue.<br><br>Here's the thing I've never understo=
od about the whole emptiness thing.<br><br>If I have need of a variant, and=
my use case is of the sort where that variant may be empty, N4542 lets me =
do that by explicitly providing an "empty" state, via the `monost=
ate` type. If I want default constructing the variant to create an empty on=
e, I just make it the first argument in the typelist.<br><br>I can even cre=
ate a specific typedef for it:<br><br><div class=3D"prettyprint" style=3D"b=
ackground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bord=
er-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">template</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">typename</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">...</span><span style=3D"color: #606;" class=3D"styled-by-prettify">=
Args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">using</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> empty_variant </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> variant</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">monostate</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Args</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">...>;</span></div></code></div><br>However, if my use =
case for variant is such that it won't be empty... I still have to cove=
r the empty case. Even though I know that it <i>cannot</i> be empty. If I u=
se visitation, I have to handle the empty state. A state that no variant wi=
ll ever be in.<br><br>It seems to me that N4542 is the option that offers t=
he most <i>freedom of choice</i> to the user. Users who want empty variants=
have them, and users who don't want empty variants don't have to h=
ave them.<br><br>Why do people want to dictate how I code?<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_1073_3061159.1442958522723--
------=_Part_1072_1800511789.1442958522723--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 14:58:33 -0700
Raw View
--001a11c30caa67630305205d19bb
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 2:48 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> Why do people want to dictate how I code?
>
+1
I'd restate this in the following manner -- why do people want to have a
library that specifically forces a trade-off when it remaining agnostic is
both simpler and gives more control to the user to make the best decision
for their particular case? If there were a solution that was always best,
then there wouldn't be an issue, but it really is a trade-off. Because of
that, it is the responsibility of a good library author to allow users to
be the one to handle that trade-off.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c30caa67630305205d19bb
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=
ue, Sep 22, 2015 at 2:48 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div>Why do people want to dictat=
e how I code?</div></blockquote><div><br></div><div>+1</div><div><br></div>=
<div>I'd restate this in the following manner -- why do people want to =
have a library that specifically forces a trade-off when it remaining agnos=
tic is both simpler and gives more control to the user to make the best dec=
ision for their particular case? If there were a solution that was always b=
est, then there wouldn't be an issue, but it really is a trade-off. Bec=
ause of that, it is the responsibility of a good library author to allow us=
ers to be the one to handle that trade-off.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c30caa67630305205d19bb--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 15:23:46 -0700
Raw View
--047d7b33d31896e3cc05205d7347
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 1:43 PM, Matt Calabrese <calabrese@google.com>
wrote:\
>
> I don't think that's a reasonable rationale. If you start with a basic
> guarantee, you are not impacting people who only need the basic guarantee,
> and people who need to restore the old state can generally do so if they
> need to. On the other hand, if you start with the strong guarantee where it
> doesn't naturally fit (I.E. requires double storage and internally a way to
> keep track of which location holds the actual instance), then a user can't
> avoid that overhead even when they don't need it, and in the case of double
> storage, you're paying for that overhead everywhere even though you only
> propagate an exception in an "exceptional" case.
>
I want to reiterate this because I think it might be the most important
point of the discussion and may get lost in the mix. Even for types with
move constructors that can throw (I.E. something like a list), the case of
it throwing is often more theoretical than practical, as in most people
will never ever see it happen. However, even though they'd likely never see
it happen, they'd always pay for something like double storage if that were
what was used to meet the strong guarantee, as has been advocated. This can
potentially have huge ramifications for an entire program in the
non-exceptional case, just so that if/when move-construction really does
propagate an exception, it *might* be easier to handle in some situations,
depending on what users need to do for that particular case. This seems
like a really questionable rationale, to me at least. What makes variant so
much more unique in that the basic guarantee isn't acceptable here? It
sounds like the argument is that the strong guarantee is easier to deal
with, which I agree is always the case, but that alone is not a complete
rationale and effectively rules out ever having operations that meet the
basic guarantee. I don't buy it.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b33d31896e3cc05205d7347
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=
ue, Sep 22, 2015 at 1:43 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> wrote:\<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 cla=
ss=3D"gmail_extra"><div class=3D"gmail_quote"><div>I don't think that&#=
39;s a reasonable rationale. If you start with a basic guarantee, you are n=
ot impacting people who only need the basic guarantee, and people who need =
to restore the old state can generally do so if they need to. On the other =
hand, if you start with the strong guarantee where it doesn't naturally=
fit (I.E. requires double storage and internally a way to keep track of wh=
ich location holds the actual instance), then a user can't avoid that o=
verhead even when they don't need it, and in the case of double storage=
, you're paying for that overhead everywhere even though you only propa=
gate an exception in an "exceptional" case.</div></div></div></di=
v></blockquote><div><br></div><div>I want to reiterate this because I think=
it might be the most important point of the discussion and may get lost in=
the mix. Even for types with move constructors that can throw (I.E. someth=
ing like a list), the case of it throwing is often more theoretical than pr=
actical, as in most people will never ever see it happen. However, even tho=
ugh they'd likely never see it happen, they'd always pay for someth=
ing like double storage if that were what was used to meet the strong guara=
ntee, as has been advocated. This can potentially have huge ramifications f=
or an entire program in the non-exceptional case, just so that if/when move=
-construction really does propagate an exception, it *might* be easier to h=
andle in some situations, depending on what users need to do for that parti=
cular case. This seems like a really questionable rationale, to me at least=
.. What makes variant so much more unique in that the basic guarantee isn=
9;t acceptable here? It sounds like the argument is that the strong guarant=
ee is easier to deal with, which I agree is always the case, but that alone=
is not a complete rationale and effectively rules out ever having operatio=
ns that meet the basic guarantee. I don't buy it.</div></div></div></di=
v>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--047d7b33d31896e3cc05205d7347--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Wed, 23 Sep 2015 00:37:32 +0200
Raw View
--001a11c26816d2b51505205da4ce
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 11:48 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>
> On Tuesday, September 22, 2015 at 3:34:34 PM UTC-4, Andrew Tomazos wrote:
>>
>> On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <ne...@eviloverlord.com>
>> wrote:
>>
>>> On 22 September 2015 at 13:46, Andrew Tomazos <andrew...@gmail.com>
>>> wrote:
>>>
>>>> I just read the minutes. It was 10 people in the room and the first
>>>> vote on that issue was split down the middle.
>>>>
>>>
>>> And there were discussions after that.
>>>
>>> While we did reach consensus, it was not unanimous (IIRC there was still
>>> one dissenter in the room).
>>>
>>>
>>>> I think there were a lot of people not present that hold the position
>>>> that if there is to be a reachable empty state then it should behave like
>>>> every other type that has such an empty state. I expect the
>>>> default-construct-to-empty to be reopened at Kona.
>>>>
>>>
>>> Oh, I expect *every* design decision on variant (and possibly optional,
>>> since it is a related type, as well as requiring move constructors to never
>>> throw, either in the standard library or in the language) to be reopened in
>>> Kona.
>>>
>>> And there is a very real possibility that we won't have variant in the
>>> standard at all, if committee members cannot come to consensus on what they
>>> are willing to live with.
>>>
>>
>> If it drags on I think people will soften their stances. It was just a
>> little early at Lenexa and the group was too small. I think the 1000+
>> messages are a sign that people really want std::variant, so that will
>> motivate consensus in the long run. (I hope! :) )
>>
>
> Why does "consensus" mean "variants can be empty?" It seems to me that
> they were able to get a good 90% consensus on N4542. It's only been
> commentary since then that has reopened the issue.
>
> Here's the thing I've never understood about the whole emptiness thing.
>
> If I have need of a variant, and my use case is of the sort where that
> variant may be empty, N4542 lets me do that by explicitly providing an
> "empty" state, via the `monostate` type. If I want default constructing the
> variant to create an empty one, I just make it the first argument in the
> typelist.
>
> I can even create a specific typedef for it:
>
> template<typename ...Args>
> using empty_variant = variant<monostate, Args...>;
>
> However, if my use case for variant is such that it won't be empty... I
> still have to cover the empty case. Even though I know that it *cannot*
> be empty. If I use visitation, I have to handle the empty state. A state
> that no variant will ever be in.
>
> It seems to me that N4542 is the option that offers the most *freedom of
> choice* to the user. Users who want empty variants have them, and users
> who don't want empty variants don't have to have them.
>
> Why do people want to dictate how I code?
>
> My statement is (and it is a position shared by a lot of people) that *if*
variant has a reachable empty value (whether you call it an invalid state,
an error state, whatever) *then* it should behave as all the other C++
types do that have such an empty value. It should default construct to it,
it should be queryable via the usual interface and should be mutatable into
it.
I would have prefered a never-empty variant, provided it could have been as
performant as a union+tag and supported all types. Unfortunately it turns
out such a thing is impossible, so having an empty-value is the least-worst
alternative (in my opinion).
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c26816d2b51505205da4ce
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 11:48 PM, Nicol Bolas <span dir=3D"ltr"><<a =
href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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"><br><br>On Tuesday, =
September 22, 2015 at 3:34:34 PM UTC-4, Andrew Tomazos wrote:<blockquote cl=
ass=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><div class=3D"gmail_quote">=
On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <span dir=3D"ltr"><<a rel=
=3D"nofollow">ne...@eviloverlord.com</a>></span> wrote:<span class=3D"">=
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><span>On 22 Septem=
ber 2015 at 13:46, Andrew Tomazos <span dir=3D"ltr"><<a rel=3D"nofollow"=
>andrew...@gmail.com</a>></span> wrote:<br></span><div class=3D"gmail_qu=
ote"><span><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div>I just read the minutes.=C2=
=A0 It was 10 people in the room and the first vote on that issue was split=
down the middle.=C2=A0</div></blockquote><div><br></div></span><div>And th=
ere were discussions after that.</div><div><br></div><div>While we did reac=
h consensus, it was not unanimous (IIRC there was still one dissenter in th=
e room).</div><span><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div> I=
think there were a lot of people not present that hold the position that i=
f there is to be a reachable empty state then it should behave like every o=
ther type that has such an empty state.=C2=A0 I expect the default-construc=
t-to-empty to be reopened at Kona.</div></blockquote><div><br></div></span>=
<div>Oh, I expect <i>every</i>=C2=A0design decision on variant (and possibl=
y optional, since it is a related type, as well as requiring move construct=
ors to never throw, either in the standard library or in the language) to b=
e reopened in Kona.</div><div><br></div><div>And there is a very real possi=
bility that we won't have variant in the standard at all, if committee =
members cannot come to consensus on what they are willing to live with.</di=
v></div></div></div></blockquote><div>=C2=A0</div><div>If it drags on I thi=
nk people will soften their stances.=C2=A0 It was just a little early at Le=
nexa and the group was too small.=C2=A0 I think the 1000+ messages are a si=
gn that people really want std::variant, so that will motivate consensus in=
the long run. =C2=A0(I hope! :) )</div></span></div></div></div></blockquo=
te><div><br>Why does "consensus" mean "variants can be empty=
?" It seems to me that they were able to get a good 90% consensus on N=
4542. It's only been commentary since then that has reopened the issue.=
<br><br>Here's the thing I've never understood about the whole empt=
iness thing.<br><br>If I have need of a variant, and my use case is of the =
sort where that variant may be empty, N4542 lets me do that by explicitly p=
roviding an "empty" state, via the `monostate` type. If I want de=
fault constructing the variant to create an empty one, I just make it the f=
irst argument in the typelist.<br><br>I can even create a specific typedef =
for it:<br><br><div style=3D"background-color:rgb(250,250,250);border-color=
:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"=
><code><div><span style=3D"color:#008">template</span><span style=3D"color:=
#660"><</span><span style=3D"color:#008">typename</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">...</span><span style=3D"colo=
r:#606">Args</span><span style=3D"color:#660">></span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#008">using</span><span style=3D"c=
olor:#000"> empty_variant </span><span style=3D"color:#660">=3D</span><span=
style=3D"color:#000"> variant</span><span style=3D"color:#660"><</span>=
<span style=3D"color:#000">monostate</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#606">Args</span=
><span style=3D"color:#660">...>;</span></div></code></div><br>However, =
if my use case for variant is such that it won't be empty... I still ha=
ve to cover the empty case. Even though I know that it <i>cannot</i> be emp=
ty. If I use visitation, I have to handle the empty state. A state that no =
variant will ever be in.<br><br>It seems to me that N4542 is the option tha=
t offers the most <i>freedom of choice</i> to the user. Users who want empt=
y variants have them, and users who don't want empty variants don't=
have to have them.<br><br>Why do people want to dictate how I code?<br></d=
iv><div class=3D"HOEnZb"><div class=3D"h5">
<p></p></div></div></blockquote></div>My statement is (and it is a position=
shared by a lot of people) that *if* variant has a reachable empty value (=
whether you call it an invalid state, an error state, whatever) *then* it s=
hould behave as all the other C++ types do that have such an empty value.=
=C2=A0 It should default construct to it, it should be queryable via the us=
ual interface and should be mutatable into it.</div><div class=3D"gmail_ext=
ra"><br></div><div class=3D"gmail_extra">I would have prefered a never-empt=
y variant, provided it could have been as performant as a union+tag and sup=
ported all types.=C2=A0 Unfortunately it turns out such a thing is impossib=
le, so having an empty-value is the least-worst alternative (in my opinion)=
..</div><div class=3D"gmail_extra"><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c26816d2b51505205da4ce--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 16:03:59 -0700
Raw View
--089e0122822e6a231605205e03dd
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 3:37 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
>
> I would have prefered a never-empty variant, provided it could have been
> as performant as a union+tag and supported all types. Unfortunately it
> turns out such a thing is impossible, so having an empty-value is the
> least-worst alternative (in my opinion).
>
But it *is* possible and is as performant. It only doesn't work for all
types if you are talking about my suggestion that certain functions are
present iff some operations of the field types are noexcept. Predicating
the existence of operations in instantiations of a template on properties
of one or more of the arguments that the template is instantiated with is
nothing unique to variant, and I don't see it as unreasonable. It's simply
what makes sense. Other examples in the standard and in user code just
often aren't predicated on a noexcept specification, but rather only on the
operation existing. In this case, implementability really does depend on
such a specification, so we shouldn't be afraid to respect that
requirement. We do not need to introduce an invalid state. When the
predicate isn't satisfied, we can simply state that the type isn't
move-assignable/copy-assignable. If the user wishes to support that
operation, they can get it by putting in their own type (analogous to
boost::blank), or by making an optional of that variant, if my other
recommendation is considered.
I don't think we should be so quick to jump to an invalid state. I see no
reason for it and it just complicates things for everyone. Just accept that
the predicate which tells you whether or not copy-assignment or
move-assignment exists is slightly less trivial than it is for containers.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0122822e6a231605205e03dd
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=
ue, Sep 22, 2015 at 3:37 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v class=3D"gmail_extra">I would have prefered a never-empty variant, provid=
ed it could have been as performant as a union+tag and supported all types.=
=C2=A0 Unfortunately it turns out such a thing is impossible, so having an =
empty-value is the least-worst alternative (in my opinion).</div></div></bl=
ockquote><div><br></div><div>But it *is* possible and is as performant. It =
only doesn't work for all types if you are talking about my suggestion =
that certain functions are present iff some operations of the field types a=
re noexcept. Predicating the existence of operations in instantiations of a=
template on properties of one or more of the arguments that the template i=
s instantiated with is nothing unique to variant, and I don't see it as=
unreasonable. It's simply what makes sense. Other examples in the stan=
dard and in user code just often aren't predicated on a noexcept specif=
ication, but rather only on the operation existing. In this case, implement=
ability really does depend on such a specification, so we shouldn't be =
afraid to respect that requirement. We do not need to introduce an invalid =
state. When the predicate isn't satisfied, we can simply state that the=
type isn't move-assignable/copy-assignable. If the user wishes to supp=
ort that operation, they can get it by putting in their own type (analogous=
to boost::blank), or by making an optional of that variant, if my other re=
commendation is considered.</div><div><br></div><div>I don't think we s=
hould be so quick to jump to an invalid state. I see no reason for it and i=
t just complicates things for everyone. Just accept that the predicate whic=
h tells you whether or not copy-assignment or move-assignment exists is sli=
ghtly less trivial than it is for containers.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0122822e6a231605205e03dd--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 16:20:38 -0700 (PDT)
Raw View
------=_Part_6626_2138095474.1442964038436
Content-Type: multipart/alternative;
boundary="----=_Part_6627_1816563715.1442964038436"
------=_Part_6627_1816563715.1442964038436
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 22, 2015 at 7:04:01 PM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 22, 2015 at 3:37 PM, Andrew Tomazos <andrew...@gmail.com
> <javascript:>> wrote:
>>
>> I would have prefered a never-empty variant, provided it could have been
>> as performant as a union+tag and supported all types. Unfortunately it
>> turns out such a thing is impossible, so having an empty-value is the
>> least-worst alternative (in my opinion).
>>
>
> But it *is* possible and is as performant. It only doesn't work for all
> types if you are talking about my suggestion that certain functions are
> present iff some operations of the field types are noexcept. Predicating
> the existence of operations in instantiations of a template on properties
> of one or more of the arguments that the template is instantiated with is
> nothing unique to variant, and I don't see it as unreasonable. It's simply
> what makes sense. Other examples in the standard and in user code just
> often aren't predicated on a noexcept specification, but rather only on the
> operation existing. In this case, implementability really does depend on
> such a specification, so we shouldn't be afraid to respect that
> requirement. We do not need to introduce an invalid state. When the
> predicate isn't satisfied, we can simply state that the type isn't
> move-assignable/copy-assignable. If the user wishes to support that
> operation, they can get it by putting in their own type (analogous to
> boost::blank), or by making an optional of that variant, if my other
> recommendation is considered.
>
> I don't think we should be so quick to jump to an invalid state. I see no
> reason for it and it just complicates things for everyone. Just accept that
> the predicate which tells you whether or not copy-assignment or
> move-assignment exists is slightly less trivial than it is for containers.
>
But that's not what we'd be "accepting" if we accepted your idea. We'd be
accepting that some people *cannot use variant*.
Copy assignment and move assignment is not optional for some people. For
entirely *reasonable* people. And there is nothing specifically about
variant that makes copy/move assignment somehow wrong or unacceptable. Even
when the copy/move may fail.
Again, why are you dictating who can and cannot use the type? Why are you
disfavoring people with throwing copy/move assignments?
Unless and *until* you can get people to agree that (like destructors),
move assignment shouldn't be able to throw, your idea favors some
programmers over others. They would have to roll their own variant type,
rather than using the standard library's one.
All because of an unfortunate and unnecessary design decision.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6627_1816563715.1442964038436
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 22, 2015 at 7:04:01 PM UTC-4, Matt Calabrese wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote">On Tue, Sep 22, 2015 at 3:37 PM, Andrew Tomazos <span dir=
=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailt=
o=3D"8yMoH-MqBgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">andrew...@gmail.com</a>></span> wrote:<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>I would have prefered a never-empty variant, pro=
vided it could have been as performant as a union+tag and supported all typ=
es.=C2=A0 Unfortunately it turns out such a thing is impossible, so having =
an empty-value is the least-worst alternative (in my opinion).</div></div><=
/blockquote><div><br></div><div>But it *is* possible and is as performant. =
It only doesn't work for all types if you are talking about my suggesti=
on that certain functions are present iff some operations of the field type=
s are noexcept. Predicating the existence of operations in instantiations o=
f a template on properties of one or more of the arguments that the templat=
e is instantiated with is nothing unique to variant, and I don't see it=
as unreasonable. It's simply what makes sense. Other examples in the s=
tandard and in user code just often aren't predicated on a noexcept spe=
cification, but rather only on the operation existing. In this case, implem=
entability really does depend on such a specification, so we shouldn't =
be afraid to respect that requirement. We do not need to introduce an inval=
id state. When the predicate isn't satisfied, we can simply state that =
the type isn't move-assignable/copy-<wbr>assignable. If the user wishes=
to support that operation, they can get it by putting in their own type (a=
nalogous to boost::blank), or by making an optional of that variant, if my =
other recommendation is considered.</div><div><br></div><div>I don't th=
ink we should be so quick to jump to an invalid state. I see no reason for =
it and it just complicates things for everyone. Just accept that the predic=
ate which tells you whether or not copy-assignment or move-assignment exist=
s is slightly less trivial than it is for containers.</div></div></div></di=
v></blockquote><div><br>But that's not what we'd be "accepting=
" if we accepted your idea. We'd be accepting that some people <i>=
cannot use variant</i>.<br><br>Copy assignment and move assignment is not o=
ptional for some people. For entirely <i>reasonable</i> people. And there i=
s nothing specifically about variant that makes copy/move assignment someho=
w wrong or unacceptable. Even when the copy/move may fail.<br><br>Again, wh=
y are you dictating who can and cannot use the type? Why are you disfavorin=
g people with throwing copy/move assignments?<br><br>Unless and <i>until</i=
> you can get people to agree that (like destructors), move assignment shou=
ldn't be able to throw, your idea favors some programmers over others. =
They would have to roll their own variant type, rather than using the stand=
ard library's one.<br><br>All because of an unfortunate and unnecessary=
design decision.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_6627_1816563715.1442964038436--
------=_Part_6626_2138095474.1442964038436--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 18:35:02 -0500
Raw View
--001a1143f1c0cdf8b105205e747b
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 17:37, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> My statement is (and it is a position shared by a lot of people) that *if*
> variant has a reachable empty value (whether you call it an invalid state,
> an error state, whatever) *then* it should behave as all the other C++
> types do that have such an empty value.
>
The current design of N4542 for default construction is also shared by a
lot of people.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143f1c0cdf8b105205e747b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On 22 September 2015 at 17:37, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"gm=
ail_extra">My statement is (and it is a position shared by a lot of people)=
that *if* variant has a reachable empty value (whether you call it an inva=
lid state, an error state, whatever) *then* it should behave as all the oth=
er C++ types do that have such an empty value.</div></blockquote><div><br><=
/div><div>The current design of N4542 for default construction is also shar=
ed by a lot of people.</div></div>-- <br><div class=3D"gmail_signature">=C2=
=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@evi=
loverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847)=
691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143f1c0cdf8b105205e747b--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 18:36:34 -0500
Raw View
--001a113d9f7a470f3a05205e7a00
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 18:03, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
>
> I don't think we should be so quick to jump to an invalid state.
>
What on earth makes you think we have done so quickly??
The engineering problems don't go away just because some people on mailing
lists wish them to.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113d9f7a470f3a05205e7a00
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 18:03, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div><br></div><div>I don't think we should=
be so quick to jump to an invalid state.</div></div></div></div></blockquo=
te><div><br></div><div>What on earth makes you think we have done so quickl=
y??</div><div><br></div><div>The engineering problems don't go away jus=
t because some people on mailing lists wish them to.</div></div>-- <br><div=
class=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=C2=A0 <mail=
to:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@evilov=
erlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113d9f7a470f3a05205e7a00--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 18:38:20 -0500
Raw View
--001a11439d989d357905205e80d5
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 18:20, Nicol Bolas <jmckesson@gmail.com> wrote:
> But that's not what we'd be "accepting" if we accepted your idea. We'd be
> accepting that some people *cannot use variant*.
>
A variant that cannot change the type it holds would be very bad, IMNSHO.
If my answer to people is "well, just use Boost.Variant", then I see no
reason to put this one in the standard.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11439d989d357905205e80d5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 18:20, Nicol Bolas <span dir=3D"lt=
r"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@g=
mail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"=
gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div>But that's not what we=
'd be "accepting" if we accepted your idea. We'd be accep=
ting that some people <i>cannot use variant</i>.<br></div></blockquote><div=
><br></div><div>A variant that cannot change the type it holds would be ver=
y bad, IMNSHO.=C2=A0 If my answer to people is "well, just use Boost.V=
ariant", then I see no reason to put this one in the standard.</div></=
div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=
=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blan=
k">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11439d989d357905205e80d5--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 16:39:44 -0700 (PDT)
Raw View
------=_Part_3317_1765243039.1442965184128
Content-Type: multipart/alternative;
boundary="----=_Part_3318_370920757.1442965184134"
------=_Part_3318_370920757.1442965184134
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 22, 2015 at 6:37:34 PM UTC-4, Andrew Tomazos wrote:
>
>
>
> On Tue, Sep 22, 2015 at 11:48 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>>
>>
>> On Tuesday, September 22, 2015 at 3:34:34 PM UTC-4, Andrew Tomazos wrote:
>>>
>>> On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <ne...@eviloverlord.com>
>>> wrote:
>>>
>>>> On 22 September 2015 at 13:46, Andrew Tomazos <andrew...@gmail.com>
>>>> wrote:
>>>>
>>>>> I just read the minutes. It was 10 people in the room and the first
>>>>> vote on that issue was split down the middle.
>>>>>
>>>>
>>>> And there were discussions after that.
>>>>
>>>> While we did reach consensus, it was not unanimous (IIRC there was
>>>> still one dissenter in the room).
>>>>
>>>>
>>>>> I think there were a lot of people not present that hold the position
>>>>> that if there is to be a reachable empty state then it should behave like
>>>>> every other type that has such an empty state. I expect the
>>>>> default-construct-to-empty to be reopened at Kona.
>>>>>
>>>>
>>>> Oh, I expect *every* design decision on variant (and possibly
>>>> optional, since it is a related type, as well as requiring move
>>>> constructors to never throw, either in the standard library or in the
>>>> language) to be reopened in Kona.
>>>>
>>>> And there is a very real possibility that we won't have variant in the
>>>> standard at all, if committee members cannot come to consensus on what they
>>>> are willing to live with.
>>>>
>>>
>>> If it drags on I think people will soften their stances. It was just a
>>> little early at Lenexa and the group was too small. I think the 1000+
>>> messages are a sign that people really want std::variant, so that will
>>> motivate consensus in the long run. (I hope! :) )
>>>
>>
>> Why does "consensus" mean "variants can be empty?" It seems to me that
>> they were able to get a good 90% consensus on N4542. It's only been
>> commentary since then that has reopened the issue.
>>
>> Here's the thing I've never understood about the whole emptiness thing.
>>
>> If I have need of a variant, and my use case is of the sort where that
>> variant may be empty, N4542 lets me do that by explicitly providing an
>> "empty" state, via the `monostate` type. If I want default constructing the
>> variant to create an empty one, I just make it the first argument in the
>> typelist.
>>
>> I can even create a specific typedef for it:
>>
>> template<typename ...Args>
>> using empty_variant = variant<monostate, Args...>;
>>
>> However, if my use case for variant is such that it won't be empty... I
>> still have to cover the empty case. Even though I know that it *cannot*
>> be empty. If I use visitation, I have to handle the empty state. A state
>> that no variant will ever be in.
>>
>> It seems to me that N4542 is the option that offers the most *freedom of
>> choice* to the user. Users who want empty variants have them, and users
>> who don't want empty variants don't have to have them.
>>
>> Why do people want to dictate how I code?
>>
>> My statement is (and it is a position shared by a lot of people) that
> *if* variant has a reachable empty value (whether you call it an invalid
> state, an error state, whatever) *then* it should behave as all the other
> C++ types do that have such an empty value. It should default construct to
> it, it should be queryable via the usual interface and should be mutatable
> into it.
>
There are two problems with this.
The first problem is really simple. Let's say I have a variant, and I need
to put types into it that can throw on move. And I catch an exception,
resolve something, and move on. I inspect the variant, and I find that it
is empty.
Now answer me this: is that variant empty because it was set to the empty
state or because an exception was thrown?
The answer, of course, is that you don't know.
With N4542, you *do* know. Because there is a fundamental distinction
between the variant being invalid (due to copy/move failure), and the
variant containing the `monostate` type (the way you set it to being
"empty").
So I would say that your notion that "invalid" and "empty" are the same
thing is just wrong.
The second problem is this:
I would have prefered a never-empty variant, provided it could have been as
> performant as a union+tag and supported all types. Unfortunately it turns
> out such a thing is impossible, so having an empty-value is the least-worst
> alternative (in my opinion).
>
But it isn't impossible; it's impractical. The only two alternatives are to
either forbid copy/move if one of the types is not noexcept, or to make
copy/move expensive for types that are noexcept.
Also, you don't seem to realize that N4542 gives you never-empty variants.
It *guarantees* never-empty variants... so long as you follow the rules. If
all the types you provide are no-except-moveable, then it is exactly
equivalent to a "never empty" variant.
It's really the best of all possible worlds. Users of throwing move objects
still get to use variant, and do so with no loss of performance on
copy/move. They have a way to test to see if the variant is valid, so that
they can tell the difference between "empty due to failure" and "empty
because I wanted it empty".
And if you don't use throwing move objects... it's a never-empty variant,
just like Boost.Variant.
What more could you possibly ask for?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3318_370920757.1442965184134
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 22, 2015 at 6:37:34 PM UTC-4, Andrew Tomazos wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><div><br><d=
iv class=3D"gmail_quote">On Tue, Sep 22, 2015 at 11:48 PM, Nicol Bolas <spa=
n dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-=
mailto=3D"IgZ6p3EpBgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'ja=
vascript:';return true;" onclick=3D"this.href=3D'javascript:';r=
eturn true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><br><br>On Tuesday, September 22, 2015 at 3:34:34 PM UTC-4, A=
ndrew Tomazos wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div><div class=3D"gmail_quote">On Tue, Sep 22, 2015 at 8:58 PM, Nevin Li=
ber <span dir=3D"ltr"><<a rel=3D"nofollow">ne...@eviloverlord.com</a>>=
;</span> wrote:<span><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"><d=
iv><span>On 22 September 2015 at 13:46, Andrew Tomazos <span dir=3D"ltr">&l=
t;<a rel=3D"nofollow">andrew...@gmail.com</a>></span> wrote:<br></span><=
div class=3D"gmail_quote"><span><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>I just =
read the minutes.=C2=A0 It was 10 people in the room and the first vote on =
that issue was split down the middle.=C2=A0</div></blockquote><div><br></di=
v></span><div>And there were discussions after that.</div><div><br></div><d=
iv>While we did reach consensus, it was not unanimous (IIRC there was still=
one dissenter in the room).</div><span><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div> I think there were a lot of people not present that hol=
d the position that if there is to be a reachable empty state then it shoul=
d behave like every other type that has such an empty state.=C2=A0 I expect=
the default-construct-to-empty to be reopened at Kona.</div></blockquote><=
div><br></div></span><div>Oh, I expect <i>every</i>=C2=A0design decision on=
variant (and possibly optional, since it is a related type, as well as req=
uiring move constructors to never throw, either in the standard library or =
in the language) to be reopened in Kona.</div><div><br></div><div>And there=
is a very real possibility that we won't have variant in the standard =
at all, if committee members cannot come to consensus on what they are will=
ing to live with.</div></div></div></div></blockquote><div>=C2=A0</div><div=
>If it drags on I think people will soften their stances.=C2=A0 It was just=
a little early at Lenexa and the group was too small.=C2=A0 I think the 10=
00+ messages are a sign that people really want std::variant, so that will =
motivate consensus in the long run. =C2=A0(I hope! :) )</div></span></div><=
/div></div></blockquote><div><br>Why does "consensus" mean "=
variants can be empty?" It seems to me that they were able to get a go=
od 90% consensus on N4542. It's only been commentary since then that ha=
s reopened the issue.<br><br>Here's the thing I've never understood=
about the whole emptiness thing.<br><br>If I have need of a variant, and m=
y use case is of the sort where that variant may be empty, N4542 lets me do=
that by explicitly providing an "empty" state, via the `monostat=
e` type. If I want default constructing the variant to create an empty one,=
I just make it the first argument in the typelist.<br><br>I can even creat=
e a specific typedef for it:<br><br><div style=3D"background-color:rgb(250,=
250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;=
word-wrap:break-word"><code><div><span style=3D"color:#008">template</span>=
<span style=3D"color:#660"><</span><span style=3D"color:#008">typename</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">...</spa=
n><span style=3D"color:#606">Args</span><span style=3D"color:#660">></sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#008">using</=
span><span style=3D"color:#000"> empty_variant </span><span style=3D"color:=
#660">=3D</span><span style=3D"color:#000"> variant</span><span style=3D"co=
lor:#660"><</span><span style=3D"color:#000">monostate</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#606">Args</span><span style=3D"color:#660">...>;</span></div></cod=
e></div><br>However, if my use case for variant is such that it won't b=
e empty... I still have to cover the empty case. Even though I know that it=
<i>cannot</i> be empty. If I use visitation, I have to handle the empty st=
ate. A state that no variant will ever be in.<br><br>It seems to me that N4=
542 is the option that offers the most <i>freedom of choice</i> to the user=
.. Users who want empty variants have them, and users who don't want emp=
ty variants don't have to have them.<br><br>Why do people want to dicta=
te how I code?<br></div><div><div>
<p></p></div></div></blockquote></div>My statement is (and it is a position=
shared by a lot of people) that *if* variant has a reachable empty value (=
whether you call it an invalid state, an error state, whatever) *then* it s=
hould behave as all the other C++ types do that have such an empty value.=
=C2=A0 It should default construct to it, it should be queryable via the us=
ual interface and should be mutatable into it.</div></div></blockquote><div=
><br>There are two problems with this. <br><br>The first problem is really =
simple. Let's say I have a variant, and I need to put types into it tha=
t can throw on move. And I catch an exception, resolve something, and move =
on. I inspect the variant, and I find that it is empty.<br><br>Now answer m=
e this: is that variant empty because it was set to the empty state or beca=
use an exception was thrown?<br><br>The answer, of course, is that you don&=
#39;t know.<br><br>With N4542, you <i>do</i> know. Because there is a funda=
mental distinction between the variant being invalid (due to copy/move fail=
ure), and the variant containing the `monostate` type (the way you set it t=
o being "empty").<br><br>So I would say that your notion that &qu=
ot;invalid" and "empty" are the same thing is just wrong.<br=
><br>The second problem is this:<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>I would have prefered a never-empty v=
ariant, provided it could have been as performant as a union+tag and suppor=
ted all types.=C2=A0 Unfortunately it turns out such a thing is impossible,=
so having an empty-value is the least-worst alternative (in my opinion).</=
div></div></blockquote><div><br>But it isn't impossible; it's impra=
ctical. The only two alternatives are to either forbid copy/move if one of =
the types is not noexcept, or to make copy/move expensive for types that ar=
e noexcept.<br><br>Also, you don't seem to realize that N4542 gives you=
never-empty variants. It <i>guarantees</i> never-empty variants... so long=
as you follow the rules. If all the types you provide are=20
no-except-moveable, then it is exactly equivalent to a "never empty&qu=
ot;=20
variant.<br><br>It's really the best of all possible worlds. Users of t=
hrowing move objects still get to use variant, and do so with no loss of pe=
rformance on copy/move. They have a way to test to see if the variant is va=
lid, so that they can tell the difference between "empty due to failur=
e" and "empty because I wanted it empty".<br><br>And if you =
don't use throwing move objects... it's a never-empty variant, just=
like Boost.Variant.<br><br>What more could you possibly ask for?<br> </di=
v>
<p></p>
-- <br />
<br />
--- <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 />
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_3318_370920757.1442965184134--
------=_Part_3317_1765243039.1442965184128--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 18:43:55 -0500
Raw View
--001a1143f1c08f46de05205e9455
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 14:34, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
>
>> On 22 September 2015 at 13:46, Andrew Tomazos <andrewtomazos@gmail.com>
>> wrote:
>>
>>> I just read the minutes. It was 10 people in the room and the first
>>> vote on that issue was split down the middle.
>>>
>>
>> And there were discussions after that.
>>
>> While we did reach consensus, it was not unanimous (IIRC there was still
>> one dissenter in the room).
>>
>>
>>> I think there were a lot of people not present that hold the position
>>> that if there is to be a reachable empty state then it should behave like
>>> every other type that has such an empty state. I expect the
>>> default-construct-to-empty to be reopened at Kona.
>>>
>>
>> Oh, I expect *every* design decision on variant (and possibly optional,
>> since it is a related type, as well as requiring move constructors to never
>> throw, either in the standard library or in the language) to be reopened in
>> Kona.
>>
>> And there is a very real possibility that we won't have variant in the
>> standard at all, if committee members cannot come to consensus on what they
>> are willing to live with.
>>
>
> If it drags on I think people will soften their stances.
>
Do you plan on softening your stance? :-)
> It was just a little early at Lenexa and the group was too small.
>
We had plenty of email on variant before Lenexa (I'd go back and count, but
it's too depressing), but that certainly wasn't enough to get more people
into the room to discuss it.
> I think the 1000+ messages are a sign that people really want
> std::variant, so that will motivate consensus in the long run.
>
Some people now believe it isn't worth the amount of time we've spent on it
and we should no longer try.
Other people want it to go directly into C++17 (as opposed to a TS), which
is more likely to harden, not soften the stance of the people who don't
like whatever gets decided in Kona, since we'll never get a chance to
correct it once C++17 ships.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143f1c08f46de05205e9455
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 14:34, Andrew Tomazos <span dir=3D=
"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andr=
ewtomazos@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><di=
v 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"><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D"">On Tue,=
Sep 22, 2015 at 8:58 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"mail=
to:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.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"><div clas=
s=3D"gmail_extra"><span>On 22 September 2015 at 13:46, Andrew Tomazos <span=
dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blan=
k">andrewtomazos@gmail.com</a>></span> wrote:<br></span><div class=3D"gm=
ail_quote"><span><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"gmail_extra">=
I just read the minutes.=C2=A0 It was 10 people in the room and the first v=
ote on that issue was split down the middle.=C2=A0</div></blockquote><div><=
br></div></span><div>And there were discussions after that.</div><div><br><=
/div><div>While we did reach consensus, it was not unanimous (IIRC there wa=
s still one dissenter in the room).</div><span><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div class=3D"gmail_extra"> I think there were a lot of=
people not present that hold the position that if there is to be a reachab=
le empty state then it should behave like every other type that has such an=
empty state.=C2=A0 I expect the default-construct-to-empty to be reopened =
at Kona.</div></blockquote><div><br></div></span><div>Oh, I expect <i>every=
</i>=C2=A0design decision on variant (and possibly optional, since it is a =
related type, as well as requiring move constructors to never throw, either=
in the standard library or in the language) to be reopened in Kona.</div><=
div><br></div><div>And there is a very real possibility that we won't h=
ave variant in the standard at all, if committee members cannot come to con=
sensus on what they are willing to live with.</div></div></div></div></bloc=
kquote><div>=C2=A0</div></span><div>If it drags on I think people will soft=
en their stances.=C2=A0</div></div></div></div></blockquote><div><br></div>=
<div>Do you plan on softening your stance? :-)</div><div>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div c=
lass=3D"gmail_quote"><div> It was just a little early at Lenexa and the gro=
up was too small.=C2=A0</div></div></div></div></blockquote><div><br></div>=
<div>We had plenty of email on variant before Lenexa (I'd go back and c=
ount, but it's too depressing), but that certainly wasn't enough to=
get more people into the room to discuss it.</div><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote"><div> I think the 1000+ messages are a sign that people=
really want std::variant, so that will motivate consensus in the long run.=
</div></div></div></div></blockquote><div><br></div><div>Some people now b=
elieve it isn't worth the amount of time we've spent on it and we s=
hould no longer try.</div><div><br></div><div>Other people want it to go di=
rectly into C++17 (as opposed to a TS), which is more likely to harden, not=
soften the stance of the people who don't like whatever gets decided i=
n Kona, since we'll never get a chance to correct it once C++17 ships.<=
/div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin ":-)"=
; Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=
=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143f1c08f46de05205e9455--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 16:51:26 -0700
Raw View
--089e01536608226f9305205ead69
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, September 22, 2015 at 7:04:01 PM UTC-4, Matt Calabrese wrote:
>>
>> On Tue, Sep 22, 2015 at 3:37 PM, Andrew Tomazos <andrew...@gmail.com>
>> wrote:
>>>
>>> I would have prefered a never-empty variant, provided it could have been
>>> as performant as a union+tag and supported all types. Unfortunately it
>>> turns out such a thing is impossible, so having an empty-value is the
>>> least-worst alternative (in my opinion).
>>>
>>
>> But it *is* possible and is as performant. It only doesn't work for all
>> types if you are talking about my suggestion that certain functions are
>> present iff some operations of the field types are noexcept. Predicating
>> the existence of operations in instantiations of a template on properties
>> of one or more of the arguments that the template is instantiated with is
>> nothing unique to variant, and I don't see it as unreasonable. It's simply
>> what makes sense. Other examples in the standard and in user code just
>> often aren't predicated on a noexcept specification, but rather only on the
>> operation existing. In this case, implementability really does depend on
>> such a specification, so we shouldn't be afraid to respect that
>> requirement. We do not need to introduce an invalid state. When the
>> predicate isn't satisfied, we can simply state that the type isn't
>> move-assignable/copy-assignable. If the user wishes to support that
>> operation, they can get it by putting in their own type (analogous to
>> boost::blank), or by making an optional of that variant, if my other
>> recommendation is considered.
>>
>> I don't think we should be so quick to jump to an invalid state. I see no
>> reason for it and it just complicates things for everyone. Just accept that
>> the predicate which tells you whether or not copy-assignment or
>> move-assignment exists is slightly less trivial than it is for containers.
>>
>
> But that's not what we'd be "accepting" if we accepted your idea. We'd be
> accepting that some people *cannot use variant*.
>
Sure they can use it. Even if they want it copy-assignable/move-assignable
they can simply put in an extra type or make it optional. Saying they
"can't use it" is like saying users *cannot use std::pair* with a type that
is not copyable because that would imply that the std::pair wouldn't be
copyable. That's not true, you just don't get that particular operation if
you don't meet the requirements of that operation. The only difference in
the variant case is that the predicate which dictates whether or not the
copy-assignment or move-assignment operation exists is dependent on an
operation's noexcept specification rather than that operation merely being
defined. This requirement exists out of necessity, whether people
immediately understand that or not. It's simply a fact and is the
underlying issue of all of these discussions -- a move-constructor that can
throw prevents us from being able to implement the move-assign or
copy-assign operation. Either you simply represent that requirement and
leave variant otherwise untainted, or you weaken the invariants of the
type. The former is much more acceptable, imo, and sacrifices no overall
behavior due to the alternative solutions that I've already suggested.
On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Copy assignment and move assignment is not optional for some people. For
> entirely *reasonable* people.
>
Again, they can still get those operations. All they do in that case is
simply put in an empty type, or make it optional.
> On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> And there is nothing specifically about variant that makes copy/move
>> assignment somehow wrong or unacceptable. Even when the copy/move may fail.
>
>
There most certainly is. People denying that are just choosing to not
accept the issue. Again, operations existing on a type being predicated by
properties of template arguments is nothing special here. The only thing
different is that the predicate in this case depends on an exception
specification instead of an operation just existing.
> On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Again, why are you dictating who can and cannot use the type? Why are you
> disfavoring people with throwing copy/move assignments?
>
We're not! This all works in such cases. All we are doing is not
implementing what is not implementable and properly identifying the
predicate that makes it so. If you want the type copy-assignable or
move-assignable for your variant that has fields with throwing move
constructors, you can get that by just putting in a dummy type along side
the other fields. There is no sacrificed functionality here, all it does is
avoid introducing an unnecessary notion of an invalid state and
complicating specification/uses.
On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Unless and *until* you can get people to agree that (like destructors),
> move assignment shouldn't be able to throw, your idea favors some
> programmers over others.
>
It doesn't favor one or the other, it just predicates the operations
appropriately. You can still use variant in those cases even if you need
those operations and you don't already meet the predicate because
satisfying the predicate only requires putting in some empty type or by
making the type optional (both of these are equivalent to variant having an
invalid state, with which one being "more" equivalent depending on if you
want to handle visitation of an invalid state as UB or as receiving a dummy
type). All that's changed is that in my suggested approach, the invariants
of the type are not violate, and people need to be explicit if they are to
get such a state.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e01536608226f9305205ead69
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=
ue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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">On Tuesday, September 22, 2015 at 7:04:01 P=
M UTC-4, Matt Calabrese wrote:<span class=3D""><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D=
"ltr"><div><div class=3D"gmail_quote">On Tue, Sep 22, 2015 at 3:37 PM, Andr=
ew Tomazos <span dir=3D"ltr"><<a rel=3D"nofollow">andrew...@gmail.com</a=
>></span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 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>I would have pref=
ered a never-empty variant, provided it could have been as performant as a =
union+tag and supported all types.=C2=A0 Unfortunately it turns out such a =
thing is impossible, so having an empty-value is the least-worst alternativ=
e (in my opinion).</div></div></blockquote><div><br></div><div>But it *is* =
possible and is as performant. It only doesn't work for all types if yo=
u are talking about my suggestion that certain functions are present iff so=
me operations of the field types are noexcept. Predicating the existence of=
operations in instantiations of a template on properties of one or more of=
the arguments that the template is instantiated with is nothing unique to =
variant, and I don't see it as unreasonable. It's simply what makes=
sense. Other examples in the standard and in user code just often aren'=
;t predicated on a noexcept specification, but rather only on the operation=
existing. In this case, implementability really does depend on such a spec=
ification, so we shouldn't be afraid to respect that requirement. We do=
not need to introduce an invalid state. When the predicate isn't satis=
fied, we can simply state that the type isn't move-assignable/copy-assi=
gnable. If the user wishes to support that operation, they can get it by pu=
tting in their own type (analogous to boost::blank), or by making an option=
al of that variant, if my other recommendation is considered.</div><div><br=
></div><div>I don't think we should be so quick to jump to an invalid s=
tate. I see no reason for it and it just complicates things for everyone. J=
ust accept that the predicate which tells you whether or not copy-assignmen=
t or move-assignment exists is slightly less trivial than it is for contain=
ers.</div></div></div></div></blockquote></span><div><br>But that's not=
what we'd be "accepting" if we accepted your idea. We'd =
be accepting that some people <i>cannot use variant</i>.<br></div></blockqu=
ote><div><br></div><div>Sure they can use it. Even if they want it copy-ass=
ignable/move-assignable they can simply put in an extra type or make it opt=
ional. Saying they "can't use it" is like saying users <i>can=
not use std::pair</i>=C2=A0with a type that is not copyable because that wo=
uld imply that the std::pair wouldn't be copyable. That's not true,=
you just don't get that particular operation if you don't meet the=
requirements of that operation. The only difference in the variant case is=
that the predicate which dictates whether or not the copy-assignment or mo=
ve-assignment operation exists is dependent on an operation's noexcept =
specification rather than that operation merely being defined. This require=
ment exists out of necessity, whether people immediately understand that or=
not. It's simply a fact and is the underlying issue of all of these di=
scussions -- a move-constructor that can throw prevents us from being able =
to implement the move-assign or copy-assign operation. Either you simply re=
present that requirement and leave variant otherwise untainted, or you weak=
en the invariants of the type. The former is much more acceptable, imo, and=
sacrifices no overall behavior due to the alternative solutions that I'=
;ve already suggested.</div><div><br></div><div>On Tue, Sep 22, 2015 at 4:2=
0 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gm=
ail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:<b=
r></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"><div>Copy assignment and move assignment is not op=
tional for some people. For entirely <i>reasonable</i> people.<br></div></b=
lockquote><div><br></div><div>Again, they can still get those operations. A=
ll they do in that case is simply put in an empty type, or make it optional=
..</div><div>=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>On Tue, Sep 22, 2015 at 4:20 =
PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmai=
l.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:<br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex">And there is nothing specifically about variant that=
makes copy/move assignment somehow wrong or unacceptable. Even when the co=
py/move may fail.</blockquote></blockquote><div><br></div><div>There most c=
ertainly is. People denying that are just choosing to not accept the issue.=
Again, operations existing on a type being predicated by properties of tem=
plate arguments is nothing special here. The only thing different is that t=
he predicate in this case depends on an exception specification instead of =
an operation just existing.</div><div>=C2=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On Tue, =
Sep 22, 2015 at 4:20 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"=
mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></=
span>=C2=A0wrote:<div>Again, why are you dictating who can and cannot use t=
he type? Why are you disfavoring people with throwing copy/move assignments=
?<br></div></blockquote><div><br></div><div>We're not! This all works i=
n such cases. All we are doing is not implementing what is not implementabl=
e and properly identifying the predicate that makes it so. If you want the =
type copy-assignable or move-assignable for your variant that has fields wi=
th throwing move constructors, you can get that by just putting in a dummy =
type along side the other fields. There is no sacrificed functionality here=
, all it does is avoid introducing an unnecessary notion of an invalid stat=
e and complicating specification/uses.</div><div><br></div><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>On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas=C2=A0<span dir=3D"ltr">&=
lt;<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail=
..com</a>></span>=C2=A0wrote:<br>Unless and <i>until</i> you can get peop=
le to agree that (like destructors), move assignment shouldn't be able =
to throw, your idea favors some programmers over others.</div></blockquote>=
<div><br></div><div>It doesn't favor one or the other, it just predicat=
es the operations appropriately. You can still use variant in those cases e=
ven if you need those operations and you don't already meet the predica=
te because satisfying the predicate only requires putting in some empty typ=
e or by making the type optional (both of these are equivalent to variant h=
aving an invalid state, with which one being "more" equivalent de=
pending on if you want to handle visitation of an invalid state as UB or as=
receiving a dummy type). All that's changed is that in my suggested ap=
proach, the invariants of the type are not violate, and people need to be e=
xplicit if they are to get such a state.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01536608226f9305205ead69--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 18:53:03 -0500
Raw View
--001a114363ac4481dc05205eb57b
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 15:43, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> I don't think that's a reasonable rationale. If you start with a basic
> guarantee, you are not impacting people who only need the basic guarantee,
> and people who need to restore the old state can generally do so if they
> need to.
>
The only cost to variant for the strong guarantee is space.
One cannot build an efficient strong guarantee on top of a variant with an
empty state, because every mutating operation may throw an exception,
*including
swap*. This is very problematic.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a114363ac4481dc05205eb57b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 15:43, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div>I don't think that's a reasonable =
rationale. If you start with a basic guarantee, you are not impacting peopl=
e who only need the basic guarantee, and people who need to restore the old=
state can generally do so if they need to.</div></div></div></div></blockq=
uote><div><br></div><div>The only cost to variant for the strong guarantee =
is space.</div><div><br></div><div>One cannot build an efficient strong gua=
rantee on top of a variant with an empty state, because every mutating oper=
ation may throw an exception, <i>including swap</i>.=C2=A0 This is very pro=
blematic.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin &quo=
t;:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com=
" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</di=
v>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a114363ac4481dc05205eb57b--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 18:58:24 -0500
Raw View
--001a114363ac5a4d2905205ec883
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 18:51, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> Sure they can use it. Even if they want it copy-assignable/move-assignable
> they can simply put in an extra type or make it optional. Saying they
> "can't use it" is like saying users *cannot use std::pair* with a type
> that is not copyable because that would imply that the std::pair wouldn't
> be copyable. That's not true, you just don't get that particular operation
> if you don't meet the requirements of that operation. The only difference
> in the variant case is that the predicate which dictates whether or not the
> copy-assignment or move-assignment operation exists is dependent on an
> operation's noexcept specification rather than that operation merely being
> defined. This requirement exists out of necessity, whether people
> immediately understand that or not.
>
It isn't out of necessity. It results from over-constraining the problem,
by not allowing double buffering, an invalid state or termination.
> It's simply a fact and is the underlying issue of all of these discussions
> -- a move-constructor that can throw prevents us from being able to
> implement the move-assign or copy-assign operation. Either you simply
> represent that requirement and leave variant otherwise untainted, or you
> weaken the invariants of the type.
>
Or use double buffering.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a114363ac5a4d2905205ec883
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 18:51, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div>Sure they can use it. Even if they want it=
copy-assignable/move-assignable they can simply put in an extra type or ma=
ke it optional. Saying they "can't use it" is like saying use=
rs <i>cannot use std::pair</i>=C2=A0with a type that is not copyable becaus=
e that would imply that the std::pair wouldn't be copyable. That's =
not true, you just don't get that particular operation if you don't=
meet the requirements of that operation. The only difference in the varian=
t case is that the predicate which dictates whether or not the copy-assignm=
ent or move-assignment operation exists is dependent on an operation's =
noexcept specification rather than that operation merely being defined. Thi=
s requirement exists out of necessity, whether people immediately understan=
d that or not. </div></div></div></div></blockquote><div><br></div><div><br=
></div><div>It isn't out of necessity.=C2=A0 It results from over-const=
raining the problem, by not allowing double buffering, an invalid state or =
termination.</div><div>=C2=A0</div><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 class=3D"gmail_extra"><div class=3D"gmail_quote"><div>It'=
s simply a fact and is the underlying issue of all of these discussions -- =
a move-constructor that can throw prevents us from being able to implement =
the move-assign or copy-assign operation. Either you simply represent that =
requirement and leave variant otherwise untainted, or you weaken the invari=
ants of the type.</div></div></div></div></blockquote><div><br></div><div>O=
r use double buffering.</div></div>-- <br><div class=3D"gmail_signature">=
=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@=
eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (8=
47) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a114363ac5a4d2905205ec883--
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 23 Sep 2015 08:21:50 +0800
Raw View
--Apple-Mail=_CC42D32B-4303-4CE0-822C-3B17A64D91D6
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9323, at 1:06 AM, Nevin Liber <nevin@eviloverlor=
d.com> wrote:
>=20
> On 22 September 2015 at 08:07, David Krauss <potswa@gmail.com <mailto:pot=
swa@gmail.com>> wrote:
>=20
> The rule for variant type-list duplicates is arbitrary,
>=20
> Arbitrary as in either
Arbitrary as in unteachable and illogical compared to other rules which wou=
ldn=E2=80=99t break the program.
I guess you got O(n^2) time from the idea of sorting the list. Some other a=
lternatives are:
1. Use the first T found, with early exit. This can only be faster.
2. As Michael and I mentioned, do not use duplicate T=E2=80=99s for storage=
, but preserve duplicates as indexes only. This still takes O(n) instantiat=
ions.
3. Disallow all duplicates.
4. No index-based get. This is what corresponds to enabling sorting once th=
e compiler magic is available, but it doesn=E2=80=99t seem to be on the tab=
le for now.
> It=E2=80=99s more brittle. Given a variant<int, T> where T varies with th=
e enclosing library interface, the user can get<T> for any T besides int, a=
nd the library can=E2=80=99t stop them from doing so.
>=20
> The only people this is brittle for are the ones who mix both type based =
indexing with numeric based indexing. That is a tiny fraction of the users=
of variant.
Those are the people for which alternative #1 would fail, but that=E2=80=99=
s not what you=E2=80=99re advocating. You=E2=80=99re advocating compile-tim=
e failure for users who use type-based indexing.
> I=E2=80=99ll be interested when there=E2=80=99s a discriminated_union tem=
plate that can store the discriminator in a bitfield.
>=20
> The current variant proposal can do that, but why?? That seems way less =
efficient.=20
No, it can=E2=80=99t. To (meaningfully) put a discriminator in a bitfield, =
it needs to be in the common initial subsequence of each of the variant mem=
bers. Doing so, it can be stored without taking a byte, obviously.
std::variant uses so many defaults and shortcuts, just due to being a templ=
ate, that it can=E2=80=99t compete with the actual C unions it models. What=
=E2=80=99s its real-world use case? What advantage besides saying =E2=80=9C=
Look ma, I=E2=80=99m using templates!=E2=80=9D
The union keyword is not deprecated. We have unions already. We don=E2=80=
=99t have sum types, so that=E2=80=99s the solution I anticipated more.
--=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/.
--Apple-Mail=_CC42D32B-4303-4CE0-822C-3B17A64D91D6
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9323, at 1:06 AM, Nevin Liber <<a href=3D"mailto:nevin@eviloverlo=
rd.com" class=3D"">nevin@eviloverlord.com</a>> wrote:</div><br class=3D"=
Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">On 2=
2 September 2015 at 08:07, David Krauss <span dir=3D"ltr" class=3D""><<a=
href=3D"mailto:potswa@gmail.com" target=3D"_blank" class=3D"">potswa@gmail=
..com</a>></span> wrote:<br class=3D""><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0=
.8ex;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap:=
break-word" class=3D""><br class=3D""><div class=3D""><div class=3D"">The r=
ule for <font face=3D"Courier" class=3D"">variant</font> type-list dup=
licates is arbitrary, </div></div></div></blockquote><div class=3D""><br cl=
ass=3D""></div><div class=3D"">Arbitrary as in either</div></div></div></di=
v></div></blockquote><div><br class=3D""></div><div>Arbitrary as in unteach=
able and illogical compared to other rules which wouldn=E2=80=99t break the=
program.</div><div><br class=3D""></div><div>I guess you got O(n^2) time f=
rom the idea of sorting the list. Some other alternatives are:</div><div><b=
r class=3D""></div><div>1. Use the first T found, with early exit. This can=
only be faster.</div><div>2. As Michael and I mentioned, do not use duplic=
ate T=E2=80=99s for storage, but preserve duplicates as indexes only. This =
still takes O(n) instantiations.</div><div>3. Disallow all duplicates.</div=
><div>4. No index-based <font face=3D"Courier" class=3D"">get</font>. This =
is what corresponds to enabling sorting once the compiler magic is availabl=
e, but it doesn=E2=80=99t seem to be on the table for now.</div><br class=
=3D""><blockquote type=3D"cite" class=3D""><div dir=3D"ltr" class=3D""><div=
class=3D"gmail_extra"><div class=3D"gmail_quote"><div class=3D""></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-word" class=3D"">=
<div class=3D""><div class=3D"">It=E2=80=99s more brittle. Given a <font fa=
ce=3D"Courier" class=3D"">variant<int, T></font> where <font face=3D"=
Courier" class=3D"">T</font> varies with the enclosing library interface, t=
he user can <font face=3D"Courier" class=3D"">get<T></font> for any <=
font face=3D"Courier" class=3D"">T</font> <i class=3D"">besides <font face=
=3D"Courier" class=3D"">int</font></i>, and the library can=E2=80=99t stop =
them from doing so. </div></div></div></blockquote><div class=3D""><br clas=
s=3D""></div><div class=3D"">The <i class=3D"">only</i> people this is=
brittle for are the ones who mix both type based indexing with numeric bas=
ed indexing. That is a tiny fraction of the users of variant.</div></=
div></div></div></blockquote><div><br class=3D""></div><div>Those are the p=
eople for which alternative #1 would fail, but that=E2=80=99s not what you=
=E2=80=99re advocating. You=E2=80=99re advocating compile-time failure for =
users who use type-based indexing.</div><br class=3D""><blockquote type=3D"=
cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class=3D"=
gmail_extra"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
style=3D"word-wrap:break-word" class=3D""><div class=3D""><div class=3D"">=
I=E2=80=99ll be interested when there=E2=80=99s a <font face=3D"Courier" cl=
ass=3D"">discriminated_union</font> template that can store the discriminat=
or in a bitfield.<br class=3D""></div></div></div></blockquote><div class=
=3D""><br class=3D""></div><div class=3D"">The current variant proposal&nbs=
p;<i class=3D"">can</i> do that, but why?? That seems way less e=
fficient. </div></div></div></div></div></blockquote><div><br class=3D=
""></div><div>No, it can=E2=80=99t. To (meaningfully) put a discriminator i=
n a bitfield, it needs to be in the common initial subsequence of each of t=
he variant members. Doing so, it can be stored without taking a byte, obvio=
usly.</div><div><br class=3D""></div><div><font face=3D"Courier" class=3D""=
>std::variant</font> uses so many defaults and shortcuts, just due to being=
a template, that it can=E2=80=99t compete with the actual C <font face=3D"=
Courier" class=3D"">union</font>s it models. What=E2=80=99s its real-world =
use case? What advantage besides saying =E2=80=9CLook ma, I=E2=80=99m using=
templates!=E2=80=9D</div><div><br class=3D""></div><div>The <font face=3D"=
Courier" class=3D"">union</font> keyword is not deprecated. We have unions =
already. We don=E2=80=99t have sum types, so that=E2=80=99s the solution I =
anticipated more.</div><div><br class=3D""></div></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_CC42D32B-4303-4CE0-822C-3B17A64D91D6--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 17:29:54 -0700
Raw View
--001a1134beb2a8942f05205f3635
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 4:53 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 22 September 2015 at 15:43, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> I don't think that's a reasonable rationale. If you start with a basic
>> guarantee, you are not impacting people who only need the basic guarantee,
>> and people who need to restore the old state can generally do so if they
>> need to.
>>
>
> The only cost to variant for the strong guarantee is space.
>
I would hesitate to refer to doubling the storage space of a type by way of
the word "only." Depending on your situation that could be pretty huge,
especially if you have a lot of variants, and even more so if variants
happen to contain other variants. If you just don't specify the strong
guarantee, which plenty of types already do for many operations, including
some in the standard library, then this need goes away. It has never been
recommended practice to force types to meet the strong guarantee when they
don't naturally fit. variant does not need to handle this and there are
usually alternative solutions that the user can use at their level of
abstraction that do not have such drastic ramifications, such as dealing
with the offending objects via indirection, which again, does not even
imply dynamic memory allocation, not that it likely matters given that move
operations that can throw generally are that way because they are doing
dynamic memory allocation to begin with.
On Tue, Sep 22, 2015 at 4:53 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> One cannot build an efficient strong guarantee on top of a variant with an
> empty state, because every mutating operation may throw an exception, *including
> swap*. This is very problematic.
>
I don't consider it problematic, it just tells us that specifying the
strong guarantee would be a mistake here. The basic guarantee has been the
recommended default since the guarantees were first introduced. What makes
people think that it's particularly important here? Especially given that
exceptions *actually* being thrown from types that have move-constructors
that can throw is [likely] rare (this is a generalization that is not
always valid, but I suspect most people will agree with), it seems really
questionable to put a requirement on the implementation to effectively
double the storage for every instance. You are doubling the storage
required for your variants just to make an exceptional case (that many
applications will likely never even see) a little bit easier to deal with.
That's a really questionable trade-off to me. At the very least, you have
to admit it's understandably controversial.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134beb2a8942f05205f3635
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=
ue, Sep 22, 2015 at 4:53 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On =
22 September 2015 at 15:43, 'Matt Calabrese' via ISO C++ Standard -=
Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@iso=
cpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<b=
r></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>I don't think that's a reasonable rationale=
.. If you start with a basic guarantee, you are not impacting people who onl=
y need the basic guarantee, and people who need to restore the old state ca=
n generally do so if they need to.</div></div></div></div></blockquote><div=
><br></div></span><div>The only cost to variant for the strong guarantee is=
space.</div></div></div></div></blockquote><div><br></div><div>I would hes=
itate to refer to doubling the storage space of a type by way of the word &=
quot;only." Depending on your situation that could be pretty huge, esp=
ecially if you have a lot of variants, and even more so if variants happen =
to contain other variants. If you just don't specify the strong guarant=
ee, which plenty of types already do for many operations, including some in=
the standard library, then this need goes away. It has never been recommen=
ded practice to force types to meet the strong guarantee when they don'=
t naturally fit. variant does not need to handle this and there are usually=
alternative solutions that the user can use at their level of abstraction =
that do not have such drastic ramifications, such as dealing with the offen=
ding objects via indirection, which again, does not even imply dynamic memo=
ry allocation, not that it likely matters given that move operations that c=
an throw generally are that way because they are doing dynamic memory alloc=
ation to begin with.</div><div><br></div><div>On Tue, Sep 22, 2015 at 4:53 =
PM, Nevin Liber=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:nevin@evilover=
lord.com" target=3D"_blank">nevin@eviloverlord.com</a>></span>=C2=A0wrot=
e:<br></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-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><d=
iv class=3D"gmail_quote"><div>One cannot build an efficient strong guarante=
e on top of a variant with an empty state, because every mutating operation=
may throw an exception, <i>including swap</i>.=C2=A0 This is very problema=
tic.</div></div></div></div></blockquote><div><br></div><div>I don't co=
nsider it problematic, it just tells us that specifying the strong guarante=
e would be a mistake here. The basic guarantee has been the recommended def=
ault since the guarantees were first introduced. What makes people think th=
at it's particularly important here? Especially given that exceptions *=
actually* being thrown from types that have move-constructors that can thro=
w is [likely] rare (this is a generalization that is not always valid, but =
I suspect most people will agree with), it seems really questionable to put=
a requirement on the implementation to effectively double the storage for =
every instance. You are doubling the storage required for your variants jus=
t to make an exceptional case (that many applications will likely never eve=
n see) a little bit easier to deal with. That's a really questionable t=
rade-off to me. At the very least, you have to admit it's understandabl=
y controversial.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134beb2a8942f05205f3635--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 18:02:08 -0700
Raw View
--001a11c2e462ed969e05205fa93d
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 4:58 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 22 September 2015 at 18:51, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> Sure they can use it. Even if they want it
>> copy-assignable/move-assignable they can simply put in an extra type or
>> make it optional. Saying they "can't use it" is like saying users *cannot
>> use std::pair* with a type that is not copyable because that would imply
>> that the std::pair wouldn't be copyable. That's not true, you just don't
>> get that particular operation if you don't meet the requirements of that
>> operation. The only difference in the variant case is that the predicate
>> which dictates whether or not the copy-assignment or move-assignment
>> operation exists is dependent on an operation's noexcept specification
>> rather than that operation merely being defined. This requirement exists
>> out of necessity, whether people immediately understand that or not.
>>
>
>
> It isn't out of necessity. It results from over-constraining the problem,
> by not allowing double buffering, an invalid state or termination.
>
It's not over-constraining the problem, it's just the solution that avoids
forcing implementation trade-offs on people. If you want the equivalent of
the empty state, you can get that trivially by how you instantiate the
variant rather than some invalid state being some kind of special thing
separate from the fields. Alternatively you can make an optional of the
type. Both of these solutions accomplish what the invalid state would get
you without complicating the specification of the variant itself or the
contracts of operations involving variants. It also gives control to the
user so that the variant only has some kind of "empty" state if they
explicitly put it there, and that type is not handled in any particularly
special way.
Further, this doesn't disallowing double buffering as you claim it does, it
only makes it not required (and I personally wouldn't recommend it). A
variant occupying double storage because one of the types has a move
constructor that can throw is subtle and unnecessary given that there is
absolutely no reason that we need to force this type to satisfy the strong
guarantee. In the case that the variant is assignable by way of the
predicate I suggested earlier, there is no need to have double storage
unless you make the assignment operations have the strong exception
guarantee. Why are you asserting that this is so important for a variant.
Do not start with the assumption that all types need to obey the strong
guarantee. This, again, has not been recommended since the guarantees were
first introduced. If you really want it for a variant, you should be making
that case explicitly, and separate from the rest of the discussion. The
basic guarantee is perfectly acceptable and is the generally recommended
default unless the strong guarantee happens to naturally fit.
On Tue, Sep 22, 2015 at 4:58 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> It's simply a fact and is the underlying issue of all of these discussions
>> -- a move-constructor that can throw prevents us from being able to
>> implement the move-assign or copy-assign operation. Either you simply
>> represent that requirement and leave variant otherwise untainted, or you
>> weaken the invariants of the type.
>>
>
> Or use double buffering.
>
How is double storage at all better than either A) instantiating the
variant with an empty type or B) making an optional of the variant? All
three of the solutions effectively allow copyability, but the latter two do
so without doubling storage and are analogous to the invalid state but
without complicating the type and the contracts of functions that deal with
that type. Again, the only reason you'd need double buffering is if you
want the strong guarantee. This is true whether via my suggestion or via an
invalid state. The issue of double storage is entirely orthogonal to
whether or not we have copyability. Until and unless you have a solid
rationale for the strong guarantee for this operation, do not assume that
the operation should have it. The burden is on you to explain why this
operation should have the strong guarantee.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2e462ed969e05205fa93d
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=
ue, Sep 22, 2015 at 4:58 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On =
22 September 2015 at 18:51, 'Matt Calabrese' via ISO C++ Standard -=
Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@iso=
cpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<b=
r></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>Sure they can use it. Even if they want it copy-ass=
ignable/move-assignable they can simply put in an extra type or make it opt=
ional. Saying they "can't use it" is like saying users <i>can=
not use std::pair</i>=C2=A0with a type that is not copyable because that wo=
uld imply that the std::pair wouldn't be copyable. That's not true,=
you just don't get that particular operation if you don't meet the=
requirements of that operation. The only difference in the variant case is=
that the predicate which dictates whether or not the copy-assignment or mo=
ve-assignment operation exists is dependent on an operation's noexcept =
specification rather than that operation merely being defined. This require=
ment exists out of necessity, whether people immediately understand that or=
not. </div></div></div></div></blockquote><div><br></div><div><br></div></=
span><div>It isn't out of necessity.=C2=A0 It results from over-constra=
ining the problem, by not allowing double buffering, an invalid state or te=
rmination.</div></div></div></div></blockquote><div><br></div><div>It's=
not over-constraining the problem, it's just the solution that avoids =
forcing implementation trade-offs on people. If you want the equivalent of =
the empty state, you can get that trivially by how you instantiate the vari=
ant rather than some invalid state being some kind of special thing separat=
e from the fields. Alternatively you can make an optional of the type. Both=
of these solutions accomplish what the invalid state would get you without=
complicating the specification of the variant itself or the contracts of o=
perations involving variants. It also gives control to the user so that the=
variant only has some kind of "empty" state if they explicitly p=
ut it there, and that type is not handled in any particularly special way.<=
/div><div><br></div><div>Further, this doesn't disallowing double buffe=
ring as you claim it does, it only makes it not required (and I personally =
wouldn't recommend it). A variant occupying double storage because one =
of the types has a move constructor that can throw is subtle and unnecessar=
y given that there is absolutely no reason that we need to force this type =
to satisfy the strong guarantee. In the case that the variant is assignable=
by way of the predicate I suggested earlier, there is no need to have doub=
le storage unless you make the assignment operations have the strong except=
ion guarantee. Why are you asserting that this is so important for a varian=
t. Do not start with the assumption that all types need to obey the strong =
guarantee. This, again, has not been recommended since the guarantees were =
first introduced. If you really want it for a variant, you should be making=
that case explicitly, and separate from the rest of the discussion. The ba=
sic guarantee is perfectly acceptable and is the generally recommended defa=
ult unless the strong guarantee happens to naturally fit.</div><div><br></d=
iv><div>On Tue, Sep 22, 2015 at 4:58 PM, Nevin Liber=C2=A0<span dir=3D"ltr"=
><<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@evil=
overlord.com</a>></span>=C2=A0wrote:<br></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"><div dir=
=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>It's simply a fact and is the underlying issue =
of all of these discussions -- a move-constructor that can throw prevents u=
s from being able to implement the move-assign or copy-assign operation. Ei=
ther you simply represent that requirement and leave variant otherwise unta=
inted, or you weaken the invariants of the type.</div></div></div></div></b=
lockquote><div><br></div></span><div>Or use double buffering.</div></div></=
div></div></blockquote><div><br></div><div>How is double storage at all bet=
ter than either A) instantiating the variant with an empty type or B) makin=
g an optional of the variant? All three of the solutions effectively allow =
copyability, but the latter two do so without doubling storage and are anal=
ogous to the invalid state but without complicating the type and the contra=
cts of functions that deal with that type. Again, the only reason you'd=
need double buffering is if you want the strong guarantee. This is true wh=
ether via my suggestion or via an invalid state. The issue of double storag=
e is entirely orthogonal to whether or not we have copyability. Until and u=
nless you have a solid rationale for the strong guarantee for this operatio=
n, do not assume that the operation should have it. The burden is on you to=
explain why this operation should have the strong guarantee.</div></div></=
div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2e462ed969e05205fa93d--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 20:16:21 -0700 (PDT)
Raw View
------=_Part_7025_49740081.1442978182059
Content-Type: multipart/alternative;
boundary="----=_Part_7026_1444031745.1442978182060"
------=_Part_7026_1444031745.1442978182060
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 22, 2015 at 7:51:28 PM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Tuesday, September 22, 2015 at 7:04:01 PM UTC-4, Matt Calabrese wrote:
>>>
>>> On Tue, Sep 22, 2015 at 3:37 PM, Andrew Tomazos <andrew...@gmail.com>
>>> wrote:
>>>>
>>>> I would have prefered a never-empty variant, provided it could have
>>>> been as performant as a union+tag and supported all types. Unfortunately
>>>> it turns out such a thing is impossible, so having an empty-value is the
>>>> least-worst alternative (in my opinion).
>>>>
>>>
>>> But it *is* possible and is as performant. It only doesn't work for all
>>> types if you are talking about my suggestion that certain functions are
>>> present iff some operations of the field types are noexcept. Predicating
>>> the existence of operations in instantiations of a template on properties
>>> of one or more of the arguments that the template is instantiated with is
>>> nothing unique to variant, and I don't see it as unreasonable. It's simply
>>> what makes sense. Other examples in the standard and in user code just
>>> often aren't predicated on a noexcept specification, but rather only on the
>>> operation existing. In this case, implementability really does depend on
>>> such a specification, so we shouldn't be afraid to respect that
>>> requirement. We do not need to introduce an invalid state. When the
>>> predicate isn't satisfied, we can simply state that the type isn't
>>> move-assignable/copy-assignable. If the user wishes to support that
>>> operation, they can get it by putting in their own type (analogous to
>>> boost::blank), or by making an optional of that variant, if my other
>>> recommendation is considered.
>>>
>>> I don't think we should be so quick to jump to an invalid state. I see
>>> no reason for it and it just complicates things for everyone. Just accept
>>> that the predicate which tells you whether or not copy-assignment or
>>> move-assignment exists is slightly less trivial than it is for containers.
>>>
>>
>> But that's not what we'd be "accepting" if we accepted your idea. We'd be
>> accepting that some people *cannot use variant*.
>>
>
> Sure they can use it. Even if they want it copy-assignable/move-assignable
> they can simply put in an extra type or make it optional.
>
.... huh? How does that work exactly?
You said that the copy/move operation *does not exist* if *any* of the
types are non-noexcept moveable. That was the feature as you suggested it,
and that's the only way to turn it into a proper compiler error (rather
than throwing an exception at runtime if you try to copy a variant that
happens to hold a non-noexcept type). The `variant` becomes an immobile
type if one of its members isn't noexcept moveable.
How would adding an extra type help? And I don't even know what "make it
optional" means; it can't mean to wrap it in an `optional`, since that
class probably forwards the throwing behavior of the copy/move operations
of T. Do you mean by making it a pointer-to-T of some kind?
That's patently absurd. I shouldn't have to heap-allocate memory to work
with a value type like `variant`.
Saying they "can't use it" is like saying users *cannot use std::pair* with
> a type that is not copyable because that would imply that the std::pair
> wouldn't be copyable. That's not true, you just don't get that particular
> operation if you don't meet the requirements of that operation. The only
> difference in the variant case is that the predicate which dictates whether
> or not the copy-assignment or move-assignment operation exists is dependent
> on an operation's noexcept specification rather than that operation merely
> being defined.
>
That's like saying that the only difference between 3 and 4 is that they're
two different numbers. Yes, these two circumstances are different. *You're*
the one who's saying that they're the same.
If I put an immobile type in a std::pair, I expect the std::pair to be
immobile, just as if I had put it into a struct. If I put a non-noexcept
copy/move type in a std::pair, I expect the std::pair to be non-noexcept
copy/move, just as if I had put it into a struct.
But for `variant`, you want throwing copy/move to mean "immobile". That's
not even *remotely* the same thing. That's not merely forwarding the
class's restriction; that's making the class *more* restricted.
So yes, I'm going to stick with my "they can't use it" position.
This requirement exists out of necessity, whether people immediately
> understand that or not.
>
It's only "necessity" because you choose not to accept the (perfectly
reasonable) alternative. You're saying that your solution is necessary, if
you preemptively define all other solutions as bad.
That doesn't make it "out of necessity;" it makes it "assuming your own
conclusion."
Either you simply represent that requirement and leave variant otherwise
> untainted, or you weaken the invariants of the type. The former is much
> more acceptable, imo, and sacrifices no overall behavior due to the
> alternative solutions that I've already suggested.
>
.... how can you say that it "sacrifices no overall behavior" when the *entire
point of the idea* is to restrict behavior? Oh, you can say, "just use a
pointer" or whatever. But that doesn't change the fact that there are
things you could do with `variant` which your suggestion prevents.
Those things are "behavior". Which you are "sacrificing". You can
arbitrarily decide that this behavior is worth sacrificing. But please
don't pretend that you aren't significantly inconveniencing actual
potential users of the class.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7026_1444031745.1442978182060
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 22, 2015 at 7:51:28 PM UTC-4, Matt Calabrese wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote">On Tue, Sep 22, 2015 at 4:20 PM, Nicol Bolas <span dir=3D"=
ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D=
"BGMTFHotBgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:=
';return true;" onclick=3D"this.href=3D'javascript:';return tru=
e;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On Tuesday,=
September 22, 2015 at 7:04:01 PM UTC-4, Matt Calabrese wrote:<span><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Tue, Sep 22, =
2015 at 3:37 PM, Andrew Tomazos <span dir=3D"ltr"><<a rel=3D"nofollow">a=
ndrew...@gmail.com</a>></span> wrote:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rg=
b(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><=
div>I would have prefered a never-empty variant, provided it could have bee=
n as performant as a union+tag and supported all types.=C2=A0 Unfortunately=
it turns out such a thing is impossible, so having an empty-value is the l=
east-worst alternative (in my opinion).</div></div></blockquote><div><br></=
div><div>But it *is* possible and is as performant. It only doesn't wor=
k for all types if you are talking about my suggestion that certain functio=
ns are present iff some operations of the field types are noexcept. Predica=
ting the existence of operations in instantiations of a template on propert=
ies of one or more of the arguments that the template is instantiated with =
is nothing unique to variant, and I don't see it as unreasonable. It=
9;s simply what makes sense. Other examples in the standard and in user cod=
e just often aren't predicated on a noexcept specification, but rather =
only on the operation existing. In this case, implementability really does =
depend on such a specification, so we shouldn't be afraid to respect th=
at requirement. We do not need to introduce an invalid state. When the pred=
icate isn't satisfied, we can simply state that the type isn't move=
-assignable/copy-<wbr>assignable. If the user wishes to support that operat=
ion, they can get it by putting in their own type (analogous to boost::blan=
k), or by making an optional of that variant, if my other recommendation is=
considered.</div><div><br></div><div>I don't think we should be so qui=
ck to jump to an invalid state. I see no reason for it and it just complica=
tes things for everyone. Just accept that the predicate which tells you whe=
ther or not copy-assignment or move-assignment exists is slightly less triv=
ial than it is for containers.</div></div></div></div></blockquote></span><=
div><br>But that's not what we'd be "accepting" if we acc=
epted your idea. We'd be accepting that some people <i>cannot use varia=
nt</i>.<br></div></blockquote><div><br></div><div>Sure they can use it. Eve=
n if they want it copy-assignable/move-<wbr>assignable they can simply put =
in an extra type or make it optional.</div></div></div></div></blockquote><=
div><br>... huh? How does that work exactly?<br><br>You said that the copy/=
move operation <i>does not exist</i> if <i>any</i> of the types are non-noe=
xcept moveable. That was the feature as you suggested it, and that's th=
e only way to turn it into a proper compiler error (rather than throwing an=
exception at runtime if you try to copy a variant that happens to hold a n=
on-noexcept type). The `variant` becomes an immobile type if one of its mem=
bers isn't noexcept moveable.<br><br>How would adding an extra type hel=
p? And I don't even know what "make it optional" means; it ca=
n't mean to wrap it in an `optional`, since that class probably forward=
s the throwing behavior of the copy/move operations of T. Do you mean by ma=
king it a pointer-to-T of some kind?<br><br>That's patently absurd. I s=
houldn't have to heap-allocate memory to work with a value type like `v=
ariant`.<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><div class=3D"gmail_quote"><div>Saying they "can't u=
se it" is like saying users <i>cannot use std::pair</i>=C2=A0with a ty=
pe that is not copyable because that would imply that the std::pair wouldn&=
#39;t be copyable. That's not true, you just don't get that particu=
lar operation if you don't meet the requirements of that operation. The=
only difference in the variant case is that the predicate which dictates w=
hether or not the copy-assignment or move-assignment operation exists is de=
pendent on an operation's noexcept specification rather than that opera=
tion merely being defined.</div></div></div></div></blockquote><div>=C2=A0<=
/div><div>That's like saying that the only difference between 3 and 4 i=
s that they're two different numbers. Yes, these two circumstances are =
different. <i>You're</i> the one who's saying that they're the =
same.<br><br>If I put an immobile type in a std::pair, I expect the std::pa=
ir to be immobile, just as if I had put it into a struct. If I put a non-no=
except copy/move type in a std::pair, I expect the std::pair to be non-noex=
cept copy/move, just as if I had put it into a struct.<br><br>But for `vari=
ant`, you want throwing copy/move to mean "immobile". That's =
not even <i>remotely</i> the same thing. That's not merely forwarding t=
he class's restriction; that's making the class <i>more</i> restric=
ted.<br><br>So yes, I'm going to stick with my "they can't use=
it" position.<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><div class=3D"gmail_quote"><div>This requirement e=
xists out of necessity, whether people immediately understand that or not.<=
/div></div></div></div></blockquote><div><br>It's only "necessity&=
quot; because you choose not to accept the (perfectly reasonable) alternati=
ve. You're saying that your solution is necessary, if you preemptively =
define all other solutions as bad.<br><br>That doesn't make it "ou=
t of necessity;" it makes it "assuming your own conclusion."=
<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div><div class=3D"gmail_quote"><div>Either you simply represent that requ=
irement and leave variant otherwise untainted, or you weaken the invariants=
of the type. The former is much more acceptable, imo, and sacrifices no ov=
erall behavior due to the alternative solutions that I've already sugge=
sted.<br></div></div></div></div></blockquote><div><br>... how can you say =
that it "sacrifices no overall behavior" when the <i>entire point=
of the idea</i> is to restrict behavior? Oh, you can say, "just use a=
pointer" or whatever. But that doesn't change the fact that there=
are things you could do with `variant` which your suggestion prevents.<br>=
<br>Those things are "behavior". Which you are "sacrificing&=
quot;. You can arbitrarily decide that this behavior is worth sacrificing. =
But please don't pretend that you aren't significantly inconvenienc=
ing actual potential users of the class.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_7026_1444031745.1442978182060--
------=_Part_7025_49740081.1442978182059--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 23 Sep 2015 00:32:48 -0300
Raw View
On 9/22/2015 9:21 PM, David Krauss wrote:
> std::variant uses so many defaults and shortcuts, just due to being a
> template, that it can=E2=80=99t compete with the actual C unions it model=
s.
`std::variant` does not model a C union, it does not model a C++ union=20
either, it models a discriminated union.
Which defaults and shortcuts are you referring to, and how do those=20
prevent any kind of competition?
> What=E2=80=99s its real-world use case? What advantage besides saying =E2=
=80=9CLook ma,
> I=E2=80=99m using templates!=E2=80=9D
From the top of my head, unlike a plain union, it has the following=20
additional semantics:
- A discriminated union knows which member is active (if any).
- A discriminated union is type-safe.
- A discriminated union can have non-trivial non-deleted special member=20
functions (copy/move constructor, copy/move assignment, destructor).
- A discriminated union can have relational operators.
Furthermore, a library solution brings the following additional benefits:
- A generic discriminated union can have a variadic number of members,=20
whereas one can't expand a pack as members of a raw union.
- A generic discriminated union can be constexpr-enabled once, which is=20
an incredibly cumbersome process due to constexpr limitations, and=20
trivially exploited as many times as necessary (right away by=20
`std::experimental::optional`, for starters).
There's more, those are just from the top of my head.
> The union keyword is not deprecated. We have unions already.
True, but unrelated. We do not have discriminated unions yet.
> We don=E2=80=99t
> have sum types, so that=E2=80=99s the solution I anticipated more.
Please note that just like a discriminated union is not a sum type, a=20
discriminated union and a plain union are different concepts too. For a=20
plain union, the knowledge of which member is active (if any) exists=20
only in the mind of the developers, so the concept, the model, and the=20
compiler can't build on it.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 20:44:44 -0700 (PDT)
Raw View
------=_Part_5829_613359692.1442979884769
Content-Type: multipart/alternative;
boundary="----=_Part_5830_626476519.1442979884769"
------=_Part_5830_626476519.1442979884769
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 22, 2015 at 8:21:57 PM UTC-4, David Krauss wrote:
>
> I=E2=80=99ll be interested when there=E2=80=99s a discriminated_union tem=
plate that can=20
>> store the discriminator in a bitfield.
>>
>
> The current variant proposal *can* do that, but why?? That seems way=20
> less efficient.=20
>
>
> No, it can=E2=80=99t. To (meaningfully) put a discriminator in a bitfield=
, it=20
> needs to be in the common initial subsequence of each of the variant=20
> members. Doing so, it can be stored without taking a byte, obviously.
>
Um, maybe you need to count your memory again. But "without taking a byte"=
=20
is not the same as "someone else provides the storage for me." Storage for=
=20
the discriminator *still exists*; it's just not directly a member of=20
`variant`.
Also, this *dramatically* limits what types you can use. Like, not being=20
able to use virtual classes or anything that isn't standard layout.
Given that you've suggested doing something that literally has no upsides=
=20
and has only downsides, I'm going to have to reiterate Nevin's "Why?"
std::variant uses so many defaults and shortcuts, just due to being a=20
> template, that it can=E2=80=99t compete with the actual C unions it model=
s.=20
> What=E2=80=99s its real-world use case? What advantage besides saying =E2=
=80=9CLook ma, I=E2=80=99m=20
> using templates!=E2=80=9D
>
=20
.... are you kidding? Just on visitation *alone*, I'd never use a `union`=20
again. And type-safety? Being able to actually ask what was stored, and=20
know what the answer is? Being able to use types with non-trivial copy=20
constructors (without having to go through annoyances)?
Seriously, since picking up Boost.Variant, I have never once considered=20
using a naked `union` for anything. I can't think of a compelling reason to=
=20
use a `union` when `variant` is available. Not unless I were interfacing=20
with some API that exposed a union directly.
And even then, there would be an interface layer via visitation;=20
internally, I'd still be using `variant`.
The union keyword is not deprecated. We have unions already.
>
Yes, they're not deprecated. They also suck. For the reasons outlined above=
..
=20
> We don=E2=80=99t have sum types, so that=E2=80=99s the solution I anticip=
ated more.
>
C++ is not a functional language. We don't need "sum t=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_5830_626476519.1442979884769
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 22, 2015 at 8:21:57 PM UTC-4, David Krauss wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word=
"><div><div></div><blockquote type=3D"cite"><div><div dir=3D"ltr"><div><div=
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 style=3D"word-wr=
ap:break-word"><div><div>I=E2=80=99ll be interested when there=E2=80=99s a =
<font face=3D"Courier">discriminated_union</font> template that can store t=
he discriminator in a bitfield.<br></div></div></div></blockquote><div><br>=
</div><div>The current variant proposal=C2=A0<i>can</i>=C2=A0do that, but w=
hy??=C2=A0 That seems way less efficient.=C2=A0</div></div></div></div></di=
v></blockquote><div><br></div><div>No, it can=E2=80=99t. To (meaningfully) =
put a discriminator in a bitfield, it needs to be in the common initial sub=
sequence of each of the variant members. Doing so, it can be stored without=
taking a byte, obviously.</div></div></div></blockquote><div><br>Um, maybe=
you need to count your memory again. But "without taking a byte"=
is not the same as "someone else provides the storage for me." S=
torage for the discriminator <i>still exists</i>; it's just not directl=
y a member of `variant`.<br><br>Also, this <i>dramatically</i> limits what =
types you can use. Like, not being able to use virtual classes or anything =
that isn't standard layout.<br><br>Given that you've suggested doin=
g something that literally has no upsides and has only downsides, I'm g=
oing to have to reiterate Nevin's "Why?"<br><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><=
div><div></div><div><font face=3D"Courier">std::variant</font> uses so many=
defaults and shortcuts, just due to being a template, that it can=E2=80=99=
t compete with the actual C <font face=3D"Courier">union</font>s it models.=
What=E2=80=99s its real-world use case? What advantage besides saying =E2=
=80=9CLook ma, I=E2=80=99m using templates!=E2=80=9D</div></div></div></blo=
ckquote><div>=C2=A0</div><div>... are you kidding? Just on visitation <i>al=
one</i>, I'd never use a `union` again. And type-safety? Being able to =
actually ask what was stored, and know what the answer is? Being able to us=
e types with non-trivial copy constructors (without having to go through an=
noyances)?<br><br>Seriously, since picking up Boost.Variant, I have never o=
nce considered using a naked `union` for anything. I can't think of a c=
ompelling reason to use a `union` when `variant` is available. Not unless I=
were interfacing with some API that exposed a union directly.<br><br>And e=
ven then, there would be an interface layer via visitation; internally, I&#=
39;d still be using `variant`.<br><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div></div><div>The =
<font face=3D"Courier">union</font> keyword is not deprecated. We have unio=
ns already.</div></div></div></blockquote><div><br>Yes, they're not dep=
recated. They also suck. For the reasons outlined above.<br>=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-wor=
d"><div><div>We don=E2=80=99t have sum types, so that=E2=80=99s the solutio=
n I anticipated more.</div></div></div></blockquote><div><br>C++ is not a f=
unctional language. We don't need "sum t <br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_5830_626476519.1442979884769--
------=_Part_5829_613359692.1442979884769--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 22 Sep 2015 20:49:09 -0700 (PDT)
Raw View
------=_Part_7178_716150582.1442980149908
Content-Type: multipart/alternative;
boundary="----=_Part_7179_707071769.1442980149908"
------=_Part_7179_707071769.1442980149908
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 22, 2015 at 11:32:53 PM UTC-4, Agust=C3=ADn K-ballo B=
erg=C3=A9=20
wrote:
>
> - A discriminated union can have non-trivial non-deleted special member=
=20
> functions (copy/move constructor, copy/move assignment, destructor).
>
Technically, so can C++11 unions. You just have to write those operations=
=20
for the union manually.
Now, that's terrible, fragile, and highly annoying for obvious reasons. But=
=20
it is technically possible.
--=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_7179_707071769.1442980149908
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, September 22, 2015 at 11:32:53 PM UTC-4, Agust=
=C3=ADn K-ballo Berg=C3=A9 wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;">- A discriminated union can have non-trivial non-deleted special member=
=20
<br>functions (copy/move constructor, copy/move assignment, destructor).<br=
></blockquote><div><br>Technically, so can C++11 unions. You just have to w=
rite those operations for the union manually.<br><br>Now, that's terrib=
le, fragile, and highly annoying for obvious reasons. But it is technically=
possible.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7179_707071769.1442980149908--
------=_Part_7178_716150582.1442980149908--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 23:03:14 -0500
Raw View
--001a1143f1c0ff0e3605206233f5
Content-Type: text/plain; charset=UTF-8
On 22 September 2015 at 20:02, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> It's not over-constraining the problem, it's just the solution that avoids
> forcing implementation trade-offs on people.
>
How exactly is this NOT a tradeoff?? Yes, we all get this is the solution
you personally want, but that doesn't make it any less of a tradeoff.
>
> On Tue, Sep 22, 2015 at 4:58 PM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
>
>> It's simply a fact and is the underlying issue of all of these
>>> discussions -- a move-constructor that can throw prevents us from being
>>> able to implement the move-assign or copy-assign operation. Either you
>>> simply represent that requirement and leave variant otherwise untainted, or
>>> you weaken the invariants of the type.
>>>
>>
>> Or use double buffering.
>>
>
> How is double storage at all better than either A) instantiating the
> variant with an empty type or B) making an optional of the variant? All
> three of the solutions effectively allow copyability, but the latter two do
> so without doubling storage and are analogous to the invalid state but
> without complicating the type and the contracts of functions that deal with
> that type. Again, the only reason you'd need double buffering is if you
> want the strong guarantee. This is true whether via my suggestion or via an
> invalid state. The issue of double storage is entirely orthogonal to
> whether or not we have copyability. Until and unless you have a solid
> rationale for the strong guarantee for this operation, do not assume that
> the operation should have it. The burden is on you to explain why this
> operation should have the strong guarantee.
>
So your requirement is basically the same as the one described at <
http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty.optimizations>in
the Enabling Optimizations section, assuming that document had been updated
for move semantics. You differ with Boost in that if the types cannot meet
those requirements, it should be a compile time error instead of double
buffering.
The Boost people seem to have thought it was better to double buffer than
to restrict types.
Oh, and don't forget it is a pessimization to do
construct-then-noexcept-move instead of just construct when the variant is
changing types, so you are penalizing all users. Of course, double
buffering is also a pessimization in terms of cache as well as memory usage.
Tradeoffs are hard.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143f1c0ff0e3605206233f5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 20:02, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></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 class=3D=
"gmail_quote"><div>It's not over-constraining the problem, it's jus=
t the solution that avoids forcing implementation trade-offs on people. </d=
iv></div></div></div></blockquote><div><br></div><div>How exactly is this N=
OT a tradeoff??=C2=A0 Yes, we all get this is the solution you personally w=
ant, but that doesn't make it any less of a tradeoff.</div><div>=C2=A0<=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div clas=
s=3D"gmail_quote"><div><br></div></div></div></div></blockquote><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 class=3D"gmail_quote=
"><span class=3D""><div>On Tue, Sep 22, 2015 at 4:58 PM, Nevin Liber=C2=A0<=
span dir=3D"ltr"><<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_b=
lank">nevin@eviloverlord.com</a>></span>=C2=A0wrote:<br></div><blockquot=
e 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-lef=
t:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quot=
e"><span><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div =
class=3D"gmail_quote"><div>It's simply a fact and is the underlying iss=
ue of all of these discussions -- a move-constructor that can throw prevent=
s us from being able to implement the move-assign or copy-assign operation.=
Either you simply represent that requirement and leave variant otherwise u=
ntainted, or you weaken the invariants of the type.</div></div></div></div>=
</blockquote><div><br></div></span><div>Or use double buffering.</div></div=
></div></div></blockquote><div><br></div></span><div>How is double storage =
at all better than either A) instantiating the variant with an empty type o=
r B) making an optional of the variant? All three of the solutions effectiv=
ely allow copyability, but the latter two do so without doubling storage an=
d are analogous to the invalid state but without complicating the type and =
the contracts of functions that deal with that type. Again, the only reason=
you'd need double buffering is if you want the strong guarantee. This =
is true whether via my suggestion or via an invalid state. The issue of dou=
ble storage is entirely orthogonal to whether or not we have copyability. U=
ntil and unless you have a solid rationale for the strong guarantee for thi=
s operation, do not assume that the operation should have it. The burden is=
on you to explain why this operation should have the strong guarantee.</di=
v></div></div></div></blockquote><div><br></div><div>So your requirement is=
basically the same as the one described at <<a href=3D"http://www.boost=
..org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empt=
y.optimizations">http://www.boost.org/doc/libs/1_59_0/doc/html/variant/desi=
gn.html#variant.design.never-empty.optimizations</a>>in the Enabling Opt=
imizations section, assuming that document had been updated for move semant=
ics.=C2=A0 You differ with Boost in that if the types cannot meet those req=
uirements, it should be a compile time error instead of double buffering.</=
div><div><br></div><div>The Boost people seem to have thought it was better=
to double buffer than to restrict types.</div><div><br></div><div>Oh, and =
don't forget it is a pessimization to do construct-then-noexcept-move i=
nstead of just construct when the variant is changing types, so you are pen=
alizing all users.=C2=A0 Of course, double buffering is also a pessimizatio=
n in terms of cache as well as memory usage.</div><div><br></div><div>Trade=
offs are hard.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin=
":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlor=
d.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-140=
4</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143f1c0ff0e3605206233f5--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 22 Sep 2015 23:31:28 -0500
Raw View
--001a11459a40f39c34052062989a
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On 22 September 2015 at 19:21, David Krauss <potswa@gmail.com> wrote:
>
> Arbitrary as in unteachable and illogical compared to other rules which
> wouldn=E2=80=99t break the program.
>
Your experience teaching variant to others differs from mine. The
questions I've been asked about Boost.Variant:
- How do I avoid memory allocation?
- What state is the variant in after an exception is thrown?
And the first question is asked far more often than the second.
>
> I guess you got O(n^2) time from the idea of sorting the list. Some other
> alternatives are:
>
> 1. Use the first T found, with early exit. This can only be faster.
>
Since I really have no idea what you are talking about anymore, let's take
two simple examples:
variant<int, int>
Should it:
1. Not compile?
2. Be the exact same type as variant<int>?
3. Be a different type but have exactly the same behavior (default
construction, comparison ops, etc.) as variant<int>?
4. Work as described in the current proposal?
(1) and (2) require pruning the type list, which is an O(n^2) template
instantiation w/o compiler support (if you disagree with this, please show
the code). (3) makes position indexing useless and has absolutely no
effect on people who only access the variant via type indexing, so I just
don't see why the folks who exclusively use type indexing (which I
postulate is the vast majority of users) care.
variant<int, float>
Should it:
1. Be the exact same type as variant<float, int>?
2. Be a different type but have exactly the same behavior (default
construction, comparison ops, etc.) as variant<float, int>?
3. Work as described in the current proposal?
(1) and (2) require a compile time portable canonical total ordering for
all types, which is currently impossible without compiler support (if you
disagree with this, please show the code).
Of course, maybe you believe adding such support is trivially easy. Good
luck with that.
--=20
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--=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/.
--001a11459a40f39c34052062989a
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 22 September 2015 at 19:21, David Krauss <span dir=3D"l=
tr"><<a href=3D"mailto:potswa@gmail.com" target=3D"_blank">potswa@gmail.=
com</a>></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 style=3D"word-wrap:break-word"><br><div><div>=
Arbitrary as in unteachable and illogical compared to other rules which wou=
ldn=E2=80=99t break the program.</div></div></div></blockquote><div><br></d=
iv><div>Your experience teaching variant to others differs from mine.=C2=A0=
The questions I've been asked about Boost.Variant:</div><div><ul><li>H=
ow do I avoid memory allocation?</li><li>What state is the variant in after=
an exception is thrown?</li></ul><div>And the first question is asked far =
more often than the second.</div></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div style=3D"word-wrap:break-word"><div><div><br></div><div>I guess you go=
t O(n^2) time from the idea of sorting the list. Some other alternatives ar=
e:</div><div><br></div><div>1. Use the first T found, with early exit. This=
can only be faster.</div></div></div></blockquote><div><br></div><div>Sinc=
e I really have no idea what you are talking about anymore, let's take =
two simple examples:</div><div><br></div><div>variant<int, int></div>=
<div><br></div><div>Should it:</div><div><br></div><div><ol><li>Not compile=
?</li><li>Be the exact same type as variant<int>?</li><li>Be a differ=
ent type but have exactly the same behavior (default construction, comparis=
on ops, etc.) as variant<int>?</li><li>Work as described in the curre=
nt proposal?=C2=A0</li></ol></div><div>(1) and (2) require pruning the type=
list, which is an O(n^2) template instantiation w/o compiler support (if y=
ou disagree with this, please show the code). =C2=A0(3) makes position inde=
xing useless and has absolutely no effect on people who only access the var=
iant via type indexing, so I just don't see why the folks who exclusive=
ly use type indexing (which I postulate is the vast majority of users) care=
..</div><div><br></div><div><div>variant<int, float></div></div><div><=
br></div><div>Should it:</div><div><ol><li>Be the exact same type as varian=
t<float, int>?</li><li>Be a different type but have exactly the same =
behavior (default construction, comparison ops, etc.) as variant<float, =
int>?</li><li>Work as described in the current proposal?</li></ol><div>(=
1) and (2) require a compile time portable canonical total ordering for all=
types, which is currently impossible without compiler support (if you disa=
gree with this, please show the code).</div></div><div><br></div><div>Of co=
urse, maybe you believe adding such support is trivially easy.=C2=A0 Good l=
uck with that.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin=
":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlor=
d.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-140=
4</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11459a40f39c34052062989a--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 21:37:41 -0700
Raw View
--001a11c2d098c8c362052062ac1e
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, September 22, 2015 at 7:51:28 PM UTC-4, Matt Calabrese wrote:
>>
>> Sure they can use it. Even if they want it
>> copy-assignable/move-assignable they can simply put in an extra type or
>> make it optional.
>>
>
> ... huh? How does that work exactly?
>
> You said that the copy/move operation *does not exist* if *any* of the
> types are non-noexcept moveable.
>
I detailed the requirements in the reply where I originally suggested all
of this. If there is something specific about that list that you don't
understand, let me know.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> That was the feature as you suggested it, and that's the only way to turn
> it into a proper compiler error (rather than throwing an exception at
> runtime if you try to copy a variant that happens to hold a non-noexcept
> type). The `variant` becomes an immobile type if one of its members isn't
> noexcept moveable.
>
No, only if one of its types has a move-constructor that is noexcept and
there is also no field that has a noexcept default constructor.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> How would adding an extra type help?
Because it allows you to restore the invariant in the event that an
exception is thrown and you are in an intermediate state between destroying
an object but where a move-construction of a new type has failed (or
emplacement failed, etc.). It's better than some kind of separate notion of
an invalid state because it keeps the invariants strict and avoids
complicating other contracts, such as those for visitation. This is nothing
new and is what boost already does with its variant. Any type that is
noexcept default-constructible is used to restore the invariant. They even
have a special type for this case called boost::blank if you care to use it
over one of your own empty types.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> And I don't even know what "make it optional" means; it can't mean to wrap
> it in an `optional`, since that class probably forwards the throwing
> behavior of the copy/move operations of T. Do you mean by making it a
> pointer-to-T of some kind?
>
No, I really do simply mean optional<variant<T...>>, where one or more of T
has a move-constructor that can throw. In this manner, even though the
variant itself may have a move-constructor that can throw and where at
least one of T is not noexcept-default-constructible, the optional itself
can properly implement a move-assignment operator and copy-assignment
operator because it has the nullopt state to fall back to. To be fully
optimal here, the implementation can use hooks, but in the general case
this isn't even required as you can always implement such an assignment
operation for an optional<T> in the more general case where T has a
move-constructor that can throw and yet no move-assignment operator since
you can implement the move-assignment operator in that particular case by
way of destroy/construct (which is also what you'd already do for an
emplace operation). This is true even outside of the context of a variant
and with any type that has those same properties. In this way, if the
construction fails by way of exception, all you have to do to restore the
invariant is put the optional into the nullopt state as the exception
propagates back to the caller. This is perfectly sensible and leaves you
with a type that has an assignment operator that satisfies the basic
exception guarantee. Complications only arise when you decide that the
operation should satisfy the strong exception guarantee. There has been no
rationale for such a requirement other than "the strong exception guarantee
is easier to work with." That is always true, and the noexcept guarantee is
even easier to work with than that. This alone has never been sufficient
reason to put such requirements on an operation. It's been recommended
since the introduction of the exception guarantees to use the strong
guarantee when it naturally fits the problem. Here, it simply doesn't
naturally fit since it requires things like double storage. Again, though,
the issue of strong/basic guarantee is somewhat orthogonal to the invalid
state.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> That's patently absurd. I shouldn't have to heap-allocate memory to work
> with a value type like `variant`.
>
It's not required and I have never suggested that it was. I've even been
very explicit about that.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> That was the feature as you suggested it, and that's the only way to turn
> it into a proper compiler error (rather than throwing an exception at
> runtime if you try to copy a variant that happens to hold a non-noexcept
> type). The `variant` becomes an immobile type if one of its members isn't
> noexcept moveable.
>
No it's not. I'm sorry to be blunt, but you're not fully understanding the
problem or its solutions.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> If I put an immobile type in a std::pair, I expect the std::pair to be
> immobile, just as if I had put it into a struct. If I put a non-noexcept
> copy/move type in a std::pair, I expect the std::pair to be non-noexcept
> copy/move, just as if I had put it into a struct.
>
Yes, that's what is expected of a pair because that is what's implementable
for a type with a bunch of separate and orthogonal fields.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> But for `variant`, you want throwing copy/move to mean "immobile". That's
> not even *remotely* the same thing. That's not merely forwarding the
> class's restriction; that's making the class *more* restricted.
>
These requirements don't come out of the blue. They are inherent in the
operation that you are implementing. Copy-assignment of a sum type that has
fields with move-constructors that can through is a very different
operation from the copy-assignment of a struct. They are completely
different problems that have different requirements and different
solutions. Your intuitions do not carry over, and that's unfortunate, but
it is also reality. I understand that you personally don't find that
particular requirement very obvious, but again, one's intuitions have no
impact on what is actually true. Either yo represent those requirements, or
you weaken the invariants of the type by introducing an invalid state,
thereby complicating things further. There is no reason to do this short of
a lack of experience with how a variant is implemented. Just represent the
proper requirements of the type and people can get a
copy-assignment/move-assignment by meeting those requirements I.E. by
having a field that is noexcept-default-constructible.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> So yes, I'm going to stick with my "they can't use it" position.
>
I will reiterate one more time -- they already can use it. Just put a
noexcept-default-constructible type as a field. This is non-intrusive to
your other field types and is perfectly acceptable. That's all you need to
have the type be move-assignable in the case that a field has a
move-constructor that can throw. It's explicit and avoids weakening the
invariants of the type and complicating other contracts. If you understand
this and the optional solution, then you should understand that the
"benefits" of the invalid state are gained by this without sacrificing the
never-empty guarantee. There is nothing magical going on here. It is all
perfectly fine and implementable. Boost even already does this part of its
implementation, so it's not even anything new. This aspect of variant has
been understood for years by those who work with variant.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> This requirement exists out of necessity, whether people immediately
>> understand that or not.
>>
>
> It's only "necessity" because you choose not to accept the (perfectly
> reasonable) alternative. You're saying that your solution is necessary, if
> you preemptively define all other solutions as bad.
>
No, it's necessity if you want to avoid unnecessarily complicating all or
most contracts that deal with your type. You can do everything with this
solution that you can do with an invalid state, only you get there without
weakening the types invariants and maintaining the never-empty-guarantee.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> But please don't pretend that you aren't significantly inconveniencing
> actual potential users of the class.
>
I don't have to pretend, it's just a fact.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2d098c8c362052062ac1e
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=
ue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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">On Tuesday, September 22, 2015 at 7:51:28 P=
M UTC-4, Matt Calabrese wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,=
204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"><span class=3D""><div>Sure they can use it. Even if th=
ey want it copy-assignable/move-assignable they can simply put in an extra =
type or make it optional.</div></span></div></div></div></blockquote><div><=
br>... huh? How does that work exactly?<br><br>You said that the copy/move =
operation <i>does not exist</i> if <i>any</i> of the types are non-noexcept=
moveable.=C2=A0</div></blockquote><div><br></div><div>I detailed the requi=
rements in the reply where I originally suggested all of this. If there is =
something specific about that list that you don't understand, let me kn=
ow.<br></div><div>=C2=A0</div><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol B=
olas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" targ=
et=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:<br></div><bloc=
kquote 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;paddin=
g-left:1ex">That was the feature as you suggested it, and that's the on=
ly way to turn it into a proper compiler error (rather than throwing an exc=
eption at runtime if you try to copy a variant that happens to hold a non-n=
oexcept type). The `variant` becomes an immobile type if one of its members=
isn't noexcept moveable.<br></blockquote><div><br></div><div>No, only =
if one of its types has a move-constructor that is noexcept and there is al=
so no field that has a noexcept default constructor.</div><div><br></div><d=
iv>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><=
<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.co=
m</a>></span>=C2=A0wrote:<br></div><blockquote class=3D"gmail_quote" sty=
le=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">How would adding an =
extra type help?</blockquote><div><br></div><div>Because it allows you to r=
estore the invariant in the event that an exception is thrown and you are i=
n an intermediate state between destroying an object but where a move-const=
ruction of a new type has failed (or emplacement failed, etc.). It's be=
tter than some kind of separate notion of an invalid state because it keeps=
the invariants strict and avoids complicating other contracts, such as tho=
se for visitation. This is nothing new and is what boost already does with =
its variant. Any type that is noexcept default-constructible is used to res=
tore the invariant. They even have a special type for this case called boos=
t::blank if you care to use it over one of your own empty types.=C2=A0</div=
><div><br></div><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<spa=
n dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">=
jmckesson@gmail.com</a>></span>=C2=A0wrote:<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
And I don't even know what "make it optional" means; it can&=
#39;t mean to wrap it in an `optional`, since that class probably forwards =
the throwing behavior of the copy/move operations of T. Do you mean by maki=
ng it a pointer-to-T of some kind?<br></blockquote><div><br></div><div>No, =
I really do simply mean optional<variant<T...>>, where one or m=
ore of T has a move-constructor that can throw. In this manner, even though=
the variant itself may have a move-constructor that can throw and where at=
least one of T is not noexcept-default-constructible, the optional itself =
can properly implement a move-assignment operator and copy-assignment opera=
tor because it has the nullopt state to fall back to. To be fully optimal h=
ere, the implementation can use hooks, but in the general case this isn'=
;t even required as you can always implement such an assignment operation f=
or an optional<T> in the more general case where T has a move-constru=
ctor that can throw and yet no move-assignment operator since you can imple=
ment the move-assignment operator in that particular case by way of destroy=
/construct (which is also what you'd already do for an emplace operatio=
n). This is true even outside of the context of a variant and with any type=
that has those same properties. In this way, if the construction fails by =
way of exception, all you have to do to restore the invariant is put the op=
tional into the nullopt state as the exception propagates back to the calle=
r. This is perfectly sensible and leaves you with a type that has an assign=
ment operator that satisfies the basic exception guarantee. Complications o=
nly arise when you decide that the operation should satisfy the strong exce=
ption guarantee. There has been no rationale for such a requirement other t=
han "the strong exception guarantee is easier to work with." That=
is always true, and the noexcept guarantee is even easier to work with tha=
n that. This alone has never been sufficient reason to put such requirement=
s on an operation. It's been recommended since the introduction of the =
exception guarantees to use the strong guarantee when it naturally fits the=
problem. Here, it simply doesn't naturally fit since it requires thing=
s like double storage. Again, though, the issue of strong/basic guarantee i=
s somewhat orthogonal to the invalid state.</div><div><br></div><div>On Tue=
, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=
=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&g=
t;</span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex">That's patently absurd. I s=
houldn't have to heap-allocate memory to work with a value type like `v=
ariant`.<br></blockquote><div><br></div><div>It's not required and I ha=
ve never suggested that it was. I've even been very explicit about that=
..</div><div><br></div><div>=C2=A0On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bol=
as=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=
=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:</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"><div> That was the feature as you suggested it, and that's the on=
ly way to turn it into a proper compiler error (rather than throwing an exc=
eption at runtime if you try to copy a variant that happens to hold a non-n=
oexcept type). The `variant` becomes an immobile type if one of its members=
isn't noexcept moveable.<br></div></blockquote><div><br></div><div>No =
it's not. I'm sorry to be blunt, but you're not fully understan=
ding the problem or its solutions.</div><div><br></div><div>On Tue, Sep 22,=
2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:=
jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=
=C2=A0wrote:</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"><div>If I put an immobile type in a std:=
:pair, I expect the std::pair to be immobile, just as if I had put it into =
a struct. If I put a non-noexcept copy/move type in a std::pair, I expect t=
he std::pair to be non-noexcept copy/move, just as if I had put it into a s=
truct.<br></div></blockquote><div><br></div><div>Yes, that's what is ex=
pected of a pair because that is what's implementable for a type with a=
bunch of separate and orthogonal fields.</div><div>=C2=A0</div><div>On Tue=
, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=
=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&g=
t;</span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex"><div>But for `variant`, you wan=
t throwing copy/move to mean "immobile". That's not even <i>r=
emotely</i> the same thing. That's not merely forwarding the class'=
s restriction; that's making the class <i>more</i> restricted.<br></div=
></blockquote><div><br></div><div>These requirements don't come out of =
the blue. They are inherent in the operation that you are implementing. Cop=
y-assignment of a sum type that has fields with move-constructors that can =
through is a very different operation from the copy-assignment of a struct.=
They are completely different problems that have different requirements an=
d different solutions. Your intuitions do not carry over, and that's un=
fortunate, but it is also reality. I understand that you personally don'=
;t find that particular requirement very obvious, but again, one's intu=
itions have no impact on what is actually true. Either yo represent those r=
equirements, or you weaken the invariants of the type by introducing an inv=
alid state, thereby complicating things further. There is no reason to do t=
his short of a lack of experience with how a variant is implemented. Just r=
epresent the proper requirements of the type and people can get a copy-assi=
gnment/move-assignment by meeting those requirements I.E. by having a field=
that is noexcept-default-constructible.</div><div><br></div><div>On Tue, S=
ep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan>=C2=A0wrote:</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);bor=
der-left-style:solid;padding-left:1ex"><div>So yes, I'm going to stick =
with my "they can't use it" position.<br></div></blockquote><=
div><br></div><div>I will reiterate one more time -- they already can use i=
t. Just put a noexcept-default-constructible type as a field. This is non-i=
ntrusive to your other field types and is perfectly acceptable. That's =
all you need to have the type be move-assignable in the case that a field h=
as a move-constructor that can throw. It's explicit and avoids weakenin=
g the invariants of the type and complicating other contracts. If you under=
stand this and the optional solution, then you should understand that the &=
quot;benefits" of the invalid state are gained by this without sacrifi=
cing the never-empty guarantee. There is nothing magical going on here. It =
is all perfectly fine and implementable. Boost even already does this part =
of its implementation, so it's not even anything new. This aspect of va=
riant has been understood for years by those who work with variant.</div><d=
iv><br></div><div><br></div><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bol=
as=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=
=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:=C2=A0</div><bloc=
kquote 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;paddin=
g-left:1ex"><span class=3D""><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"><div dir=3D"ltr"><div><div cl=
ass=3D"gmail_quote"><div>This requirement exists out of necessity, whether =
people immediately understand that or not.</div></div></div></div></blockqu=
ote></span><div><br>It's only "necessity" because you choose =
not to accept the (perfectly reasonable) alternative. You're saying tha=
t your solution is necessary, if you preemptively define all other solution=
s as bad.<br></div></blockquote><div><br></div><div>No, it's necessity =
if you want to avoid unnecessarily complicating all or most contracts that =
deal with your type. You can do everything with this solution that you can =
do with an invalid state, only you get there without weakening the types in=
variants and maintaining the never-empty-guarantee.</div><div><br></div><di=
v>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<=
a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com=
</a>></span>=C2=A0wrote:=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=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>But please don=
't pretend that you aren't significantly inconveniencing actual pot=
ential users of the class.<br></div></blockquote><div><br></div><div>I don&=
#39;t have to pretend, it's just a fact.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2d098c8c362052062ac1e--
.
Author: Michael Park <mcypark@gmail.com>
Date: Tue, 22 Sep 2015 21:47:57 -0700 (PDT)
Raw View
------=_Part_1269_380024764.1442983677577
Content-Type: multipart/alternative;
boundary="----=_Part_1270_1507373809.1442983677577"
------=_Part_1270_1507373809.1442983677577
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Since the Wikipedia article for *tagged union* refers to tagged union,=20
variant, discriminated union, disjoint union, and sum type as the same=20
concept, it seems to me that it would be beneficial for the group to agree=
=20
on well-defined, common terminology for clear communication.
It seems that Agust=C3=ADn refers to *discriminated union* to mean a generi=
c,=20
type-safe version of C++ union, whereas others have referred to a *sum*=20
*type* in the functional language sense, which has characteristics such as=
=20
the order types is insensitive, and duplicates types aren't distinct states=
..
We can either provide them as separate class templates, or try to provide a=
=20
single class template that satisfies both camps.
We could consider perhaps introducing separate class templates=20
*discriminated_union*, which is a generic, type-safe replacement for C++=20
union, and *variant*, as a sum type. (Please don't pay too much attention=
=20
to the names, my point is that we could introduce 2 separate class=20
templates.)
Now, of course introducing one class template *variant* that supports both=
=20
use cases would be (more?) desirable. I think the way we would do this is:
- If types are unique, both index-based and type-based operations are=20
available, and a type_switch can also be used.
(Both discriminated union and sum types behave normally, as expected)
- If types contain duplicates, we lose the type-based operations for the=
=20
ones that are duplicated.
e.g. For *variant<T, T, U>*, *get<T>* is invalid, *get<U>* is valid.
(As a discriminated union, everything is fine since the index-based=20
operations will be used anyway unless using types is more convenient. As=
a=20
sum type, the expectation would be that *variant<T, T, U>* behave=20
equivalently as *variant<T, U>*. Since the support for duplicate types=
=20
is only to facilitate meta-programming which is a niche within (typicall=
y)=20
C++ experts, it seems reasonable to put the burden on them to perform=20
*unique* on the types.)
*Q:* Why not just make type-based operations such as *get<T>* use the first=
=20
*T* in *variant<T, T, **U>*?
*A:* After Anthony Williams presented his approach to this problem, it=20
seemed to me that we can perfectly satisfy both discriminated union and sum=
=20
type use cases.
I think this is true if index-based operations are not mixed with=20
type-based operations. That is, discriminated union use cases will use=20
index-based operations, and type-based operations when convenient, and sum=
=20
type use cases only use type-based operations. The sum type use cases=20
effectively would simply ignore the second *T* in *variant<T, T, U>*.=20
However, given that the index-based operations are still *available* even=
=20
under the sum type use cases, it's totally feasible for a variant meant to=
=20
be used as a sum type gets into a bad state from someone using an=20
index-based operation to get it into an unexpected state.
I think disabling the type-based operations for the types that duplicate,=
=20
and forcing the deduplication in the cases where it is the desired=20
semantics is a good compromise.
What do you think?
On Tuesday, September 22, 2015 at 8:32:53 PM UTC-7, Agust=C3=ADn K-ballo Be=
rg=C3=A9=20
wrote:
>
> On 9/22/2015 9:21 PM, David Krauss wrote:=20
> > std::variant uses so many defaults and shortcuts, just due to being a=
=20
> > template, that it can=E2=80=99t compete with the actual C unions it mod=
els.=20
>
> `std::variant` does not model a C union, it does not model a C++ union=20
> either, it models a discriminated union.=20
>
> Which defaults and shortcuts are you referring to, and how do those=20
> prevent any kind of competition?=20
>
> > What=E2=80=99s its real-world use case? What advantage besides saying =
=E2=80=9CLook ma,=20
> > I=E2=80=99m using templates!=E2=80=9D=20
>
> From the top of my head, unlike a plain union, it has the following=20
> additional semantics:=20
>
> - A discriminated union knows which member is active (if any).=20
>
> - A discriminated union is type-safe.=20
>
> - A discriminated union can have non-trivial non-deleted special member=
=20
> functions (copy/move constructor, copy/move assignment, destructor).=20
>
> - A discriminated union can have relational operators.=20
>
> Furthermore, a library solution brings the following additional benefits:=
=20
>
> - A generic discriminated union can have a variadic number of members,=20
> whereas one can't expand a pack as members of a raw union.=20
>
> - A generic discriminated union can be constexpr-enabled once, which is=
=20
> an incredibly cumbersome process due to constexpr limitations, and=20
> trivially exploited as many times as necessary (right away by=20
> `std::experimental::optional`, for starters).=20
>
> There's more, those are just from the top of my head.=20
>
> > The union keyword is not deprecated. We have unions already.=20
>
> True, but unrelated. We do not have discriminated unions yet.=20
>
> > We don=E2=80=99t=20
> > have sum types, so that=E2=80=99s the solution I anticipated more.=20
>
> Please note that just like a discriminated union is not a sum type, a=20
> discriminated union and a plain union are different concepts too. For a=
=20
> plain union, the knowledge of which member is active (if any) exists=20
> only in the mind of the developers, so the concept, the model, and the=20
> compiler can't build on it.=20
>
> Regards,=20
> --=20
> Agust=C3=ADn K-ballo Berg=C3=A9.-=20
> http://talesofcpp.fusionfenix.com=20
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1270_1507373809.1442983677577
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Since the Wikipedia article for <b>tagged union</b> r=
efers to tagged union, variant, discriminated union, disjoint union, and su=
m type as the same concept, it seems to me that it would be beneficial for =
the group to agree on well-defined, common terminology for clear communicat=
ion.<br></div><div><br></div><div>It seems that Agust=C3=ADn<span style=3D"=
white-space: nowrap;">=C2=A0</span>refers to <b>discriminated union</b>=C2=
=A0to mean a generic, type-safe version of C++ union, whereas others have r=
eferred to a <b>sum</b>=C2=A0<b>type</b>=C2=A0in the functional language se=
nse, which has characteristics such as the order types is insensitive, and =
duplicates types aren't distinct states.</div><div><br></div><div>We ca=
n either provide them as separate class templates, or try to provide a sing=
le class template that satisfies both camps.</div><div><br></div><div>We co=
uld consider perhaps introducing separate class templates=C2=A0<b style=3D"=
line-height: 17px;">discriminated_union</b><span style=3D"line-height: 17px=
;">,</span><span style=3D"line-height: 17px;">=C2=A0which is a generic, typ=
e-safe replacement for C++ union, and <b>variant</b>, as a sum type. (Pleas=
e don't pay too much attention to the names, my point is that we could =
introduce 2 separate class templates.)</span></div><div><br></div><div>Now,=
of course introducing one class template <b>variant</b>=C2=A0that supports=
both use cases would be (more?) desirable. I think the way we would do thi=
s is:</div><div><ul><li><span style=3D"line-height: normal;">If types are u=
nique, both index-based and type-based operations are available, and a=C2=
=A0type_switch can also be used.<br>(Both discriminated union and sum types=
behave normally, as expected)</span></li><li><span style=3D"line-height: n=
ormal;">If types contain duplicates, we lose the type-based operations for =
the ones that are duplicated.<br></span><span style=3D"line-height: normal;=
">e.g. For <b>variant<T, T, U></b>, <b>get<T></b> is invalid, <=
b>get<U></b> is valid.<br>(As a discriminated union, everything is fi=
ne since the index-based operations will be used anyway unless using types =
is more convenient. As a sum type, the expectation would be that <b>variant=
<T, T, U></b>=C2=A0behave equivalently as <b>variant<T, U></b>.=
Since the support for duplicate types is only to facilitate meta-programmi=
ng which is a niche within (typically) C++ experts, it seems reasonable to =
put the burden on them to perform=C2=A0<b>unique</b>=C2=A0on the types.)</s=
pan></li></ul></div><div><b>Q:</b> Why not just make type-based operations =
such as=C2=A0<b>get<T></b>=C2=A0use the first <b>T</b> in <b>variant&=
lt;T, T,=C2=A0</b><b>U></b>?</div><div><br></div><div><b>A:</b> After An=
thony Williams presented his approach to this problem, it seemed to me that=
we can perfectly satisfy both discriminated union and sum type use cases.<=
/div><div><br></div><div>I think this is true if index-based operations are=
not mixed with type-based operations. That is, discriminated union use cas=
es will use index-based operations, and type-based operations when convenie=
nt, and sum type use cases only use type-based operations. The sum type use=
cases effectively would simply ignore the second <b>T</b> in <b>variant<=
;T, T, U></b>. However, given that the index-based operations are still =
<b>available</b>=C2=A0even under the sum type use cases, it's totally f=
easible for a variant meant to be used as a sum type gets into a bad state =
from someone using an index-based operation to get it into an unexpected st=
ate.</div><div><br></div><div>I think disabling the type-based operations f=
or the types that duplicate, and forcing the deduplication in the cases whe=
re it is the desired semantics is a good compromise.</div><div><br></div><d=
iv>What do you think?</div><div><br></div><div>On Tuesday, September 22, 20=
15 at 8:32:53 PM UTC-7, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">On 9/22/2015 9:21 PM, David Krauss wrote:
<br>> std::variant uses so many defaults and shortcuts, just due to bein=
g a
<br>> template, that it can=E2=80=99t compete with the actual C unions i=
t models.
<br>
<br>`std::variant` does not model a C union, it does not model a C++ union=
=20
<br>either, it models a discriminated union.
<br>
<br>Which defaults and shortcuts are you referring to, and how do those=20
<br>prevent any kind of competition?
<br>
<br>> What=E2=80=99s its real-world use case? What advantage besides say=
ing =E2=80=9CLook ma,
<br>> I=E2=80=99m using templates!=E2=80=9D
<br>
<br>=C2=A0From the top of my head, unlike a plain union, it has the followi=
ng=20
<br>additional semantics:
<br>
<br>- A discriminated union knows which member is active (if any).
<br>
<br>- A discriminated union is type-safe.
<br>
<br>- A discriminated union can have non-trivial non-deleted special member=
=20
<br>functions (copy/move constructor, copy/move assignment, destructor).
<br>
<br>- A discriminated union can have relational operators.
<br>
<br>Furthermore, a library solution brings the following additional benefit=
s:
<br>
<br>- A generic discriminated union can have a variadic number of members,=
=20
<br>whereas one can't expand a pack as members of a raw union.
<br>
<br>- A generic discriminated union can be constexpr-enabled once, which is=
=20
<br>an incredibly cumbersome process due to constexpr limitations, and=20
<br>trivially exploited as many times as necessary (right away by=20
<br>`std::experimental::optional`, for starters).
<br>
<br>There's more, those are just from the top of my head.
<br>
<br>> The union keyword is not deprecated. We have unions already.
<br>
<br>True, but unrelated. We do not have discriminated unions yet.
<br>
<br>> We don=E2=80=99t
<br>> have sum types, so that=E2=80=99s the solution I anticipated more.
<br>
<br>Please note that just like a discriminated union is not a sum type, a=
=20
<br>discriminated union and a plain union are different concepts too. For a=
=20
<br>plain union, the knowledge of which member is active (if any) exists=20
<br>only in the mind of the developers, so the concept, the model, and the=
=20
<br>compiler can't build on it.
<br>
<br>Regards,
<br>--=20
<br>Agust=C3=ADn K-ballo Berg=C3=A9.-
<br><a href=3D"http://talesofcpp.fusionfenix.com" target=3D"_blank" rel=3D"=
nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75htt=
p%3A%2F%2Ftalesofcpp.fusionfenix.com\46sa\75D\46sntz\0751\46usg\75AFQjCNGrO=
c8fm1PhW0305mMc5XVd9NU-_Q';return true;" onclick=3D"this.href=3D'ht=
tp://www.google.com/url?q\75http%3A%2F%2Ftalesofcpp.fusionfenix.com\46sa\75=
D\46sntz\0751\46usg\75AFQjCNGrOc8fm1PhW0305mMc5XVd9NU-_Q';return true;"=
>http://talesofcpp.fusionfenix.<wbr>com</a>
<br></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1270_1507373809.1442983677577--
------=_Part_1269_380024764.1442983677577--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 21:58:46 -0700
Raw View
--001a1134e21235ca1e052062f88b
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 9:03 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 22 September 2015 at 20:02, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> It's not over-constraining the problem, it's just the solution that
>> avoids forcing implementation trade-offs on people.
>>
>
> How exactly is this NOT a tradeoff?? Yes, we all get this is the solution
> you personally want, but that doesn't make it any less of a tradeoff.
>
Because it puts the trade-off into the hands of the user, where it belongs,
rather than making it an internal part of the library that the user has no
control over. All the user has to do to get the equivalent of the invalid
state is to be explicit in the ways I've already mentioned.
On Tue, Sep 22, 2015 at 9:03 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> So your requirement is basically the same as the one described at <
> http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty.optimizations>in
> the Enabling Optimizations section, assuming that document had been updated
> for move semantics. You differ with Boost in that if the types cannot meet
> those requirements, it should be a compile time error instead of double
> buffering.
>
> The Boost people seem to have thought it was better to double buffer than
> to restrict types.
>
No, Boost actually decided that by default you go to heap and not use
permanent double storage. I know because I've been following and
participating in these discussions since about the time that variant was
introduced into Boost. This is even detailed on that page that you linked.
For the record, had we actually had a portable way to check if an exception
were noexcept at the time that variant were proposed for boost, then
causing a compile error probably would have come up during review, but this
simply wasn't an option at the time because we didn't get such a language
feature until C++11, which was many years later.
> On Tue, Sep 22, 2015 at 9:03 PM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
> Oh, and don't forget it is a pessimization to do
> construct-then-noexcept-move instead of just construct when the variant is
> changing types, so you are penalizing all users.
>
You don't have to do that. You only ever do that under circumstances that
make direct construction not possible (i.e. you have no fallback type but
the construction can throw). In other words, when you have the fallback
type, you always have similar behavior to having an invalid state down to
specifically what kinds of operations are invoked. They really are
equivalent but without the need to sacrifice the never-empty guarantee.
Which approach is "more" equivalent, optional<variant<T...>> or
variant<Fallback,T...>, is dependent on precisely how you imagine the
invalid state would be treated during things like visitation. If visitation
is UB when in the invalid state, it's more similar to the optional
solution. If visitation expands out the "invalid" state to some dummy type,
then it is more similar to the fallback choice. Both of these options are
directly implementable without introducing some intrinsic invalid state to
variant and it remains completely agnostic. All it cares about are what
operations it has the capability of implementing as based on your field
types' operations. It doesn't need an invalid state to do this. It is
entirely unnecessary and only complicates specification.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134e21235ca1e052062f88b
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=
ue, Sep 22, 2015 at 9:03 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On =
22 September 2015 at 20:02, 'Matt Calabrese' via ISO C++ Standard -=
Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@iso=
cpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<b=
r></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>It's not over-constraining the problem, it'=
s just the solution that avoids forcing implementation trade-offs on people=
.. </div></div></div></div></blockquote><div><br></div></span><div>How exact=
ly is this NOT a tradeoff??=C2=A0 Yes, we all get this is the solution you =
personally want, but that doesn't make it any less of a tradeoff.</div>=
</div></div></div></blockquote><div><br></div><div>Because it puts the trad=
e-off into the hands of the user, where it belongs, rather than making it a=
n internal part of the library that the user has no control over. All the u=
ser has to do to get the equivalent of the invalid state is to be explicit =
in the ways I've already mentioned.</div><div><br></div><div>On Tue, Se=
p 22, 2015 at 9:03 PM, Nevin Liber=C2=A0<span dir=3D"ltr"><<a href=3D"ma=
ilto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&g=
t;</span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204=
);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"=
gmail_extra"><div class=3D"gmail_quote"><div>So your requirement is basical=
ly the same as the one described at <<a href=3D"http://www.boost.org/doc=
/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty.optimi=
zations" target=3D"_blank">http://www.boost.org/doc/libs/1_59_0/doc/html/va=
riant/design.html#variant.design.never-empty.optimizations</a>>in the En=
abling Optimizations section, assuming that document had been updated for m=
ove semantics.=C2=A0 You differ with Boost in that if the types cannot meet=
those requirements, it should be a compile time error instead of double bu=
ffering.</div><div><br></div><div>The Boost people seem to have thought it =
was better to double buffer than to restrict types.</div></div></div></div>=
</blockquote><div><br></div><div>No, Boost actually decided that by default=
you go to heap and not use permanent double storage. I know because I'=
ve been following and participating in these discussions since about the ti=
me that variant was introduced into Boost. This is even detailed on that pa=
ge that you linked. For the record, had we actually had a portable way to c=
heck if an exception were noexcept at the time that variant were proposed f=
or boost, then causing a compile error probably would have come up during r=
eview, but this simply wasn't an option at the time because we didn'=
;t get such a language feature until C++11, which was many years later.</di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 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_ex=
tra"><div class=3D"gmail_quote">On Tue, Sep 22, 2015 at 9:03 PM, Nevin Libe=
r=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:nevin@eviloverlord.com" targ=
et=3D"_blank">nevin@eviloverlord.com</a>></span>=C2=A0wrote:<div>Oh, and=
don't forget it is a pessimization to do construct-then-noexcept-move =
instead of just construct when the variant is changing types, so you are pe=
nalizing all users.</div></div></div></div></blockquote><div><br></div><div=
>You don't have to do that. You only ever do that under circumstances t=
hat make direct construction not possible (i.e. you have no fallback type b=
ut the construction can throw). In other words, when you have the fallback =
type, you always have similar behavior to having an invalid state down to s=
pecifically what kinds of operations are invoked. They really are equivalen=
t but without the need to sacrifice the never-empty guarantee. Which approa=
ch is "more" equivalent, optional<variant<T...>> or v=
ariant<Fallback,T...>, is dependent on precisely how you imagine the =
invalid state would be treated during things like visitation. If visitation=
is UB when in the invalid state, it's more similar to the optional sol=
ution. If visitation expands out the "invalid" state to some dumm=
y type, then it is more similar to the fallback choice. Both of these optio=
ns are directly implementable without introducing some intrinsic invalid st=
ate to variant and it remains completely agnostic. All it cares about are w=
hat operations it has the capability of implementing as based on your field=
types' operations. It doesn't need an invalid state to do this. It=
is entirely unnecessary and only complicates specification.</div></div></d=
iv></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--001a1134e21235ca1e052062f88b--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 22:15:48 -0700
Raw View
--94eb2c0961c426cbe10520633570
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 9:31 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
>
> variant<int, float>
>
> Should it:
>
> 1. Be the exact same type as variant<float, int>?
> 2. Be a different type but have exactly the same behavior (default
> construction, comparison ops, etc.) as variant<float, int>?
> 3. Work as described in the current proposal?
>
> (1) and (2) require a compile time portable canonical total ordering for
> all types, which is currently impossible without compiler support (if you
> disagree with this, please show the code).
>
> Of course, maybe you believe adding such support is trivially easy. Good
> luck with that.
>
This at least we agree on. I also don't see the benefit of having ordering
not matter, but rather, I only see drawbacks. Portable serialization for a
variant when ordering provides reliable discriminators, for example, is
trivial, since you can serialize the discriminator followed by the held
type. Deserialization goes the other direction and is similarly easy to be
portable (I suggest that we also provide a run-time-to-compile-time integer
facility to make this kind of operation more feasible, such as Steven
Watanabe's provisional Boost.Switch). If you have no consistent notion of a
discriminator and no canonical ordering of types, then what do you do for
real-world cases like this? Manually register the type info in some kind of
portable manner? It's impractical and unnecessary. I don't buy the supposed
gains that come from hiding the discriminator. Ordering in template
argument lists already matters in C++ and we can't really change that. They
are different instantiations. Even with some kind of canonical ordering
this would still be true, and it would only potentially affect the backend
(I.E. by perhaps minimizing instantiations in the case where you have
similar variants appear with varying orderings). That's outside of the
realm of the standard anyway, so it's sort of questionable to even bring it
up. There aren't tangible gains regardless.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--94eb2c0961c426cbe10520633570
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=
ue, Sep 22, 2015 at 9:31 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div><div>variant<int, float=
></div></div><div><br></div><div>Should it:</div><div><ol><li>Be the exa=
ct same type as variant<float, int>?</li><li>Be a different type but =
have exactly the same behavior (default construction, comparison ops, etc.)=
as variant<float, int>?</li><li>Work as described in the current pro=
posal?</li></ol><div>(1) and (2) require a compile time portable canonical =
total ordering for all types, which is currently impossible without compile=
r support (if you disagree with this, please show the code).</div></div><di=
v><br></div><div>Of course, maybe you believe adding such support is trivia=
lly easy.=C2=A0 Good luck with that.</div></div></div></div></blockquote><d=
iv><br></div><div>This at least we agree on. I also don't see the benef=
it of having ordering not matter, but rather, I only see drawbacks. Portabl=
e serialization for a variant when ordering provides reliable discriminator=
s, for example, is trivial, since you can serialize the discriminator follo=
wed by the held type. Deserialization goes the other direction and is simil=
arly easy to be portable (I suggest that we also provide a run-time-to-comp=
ile-time integer facility to make this kind of operation more feasible, suc=
h as Steven Watanabe's provisional Boost.Switch). If you have no consis=
tent notion of a discriminator and no canonical ordering of types, then wha=
t do you do for real-world cases like this? Manually register the type info=
in some kind of portable manner? It's impractical and unnecessary. I d=
on't buy the supposed gains that come from hiding the discriminator. Or=
dering in template argument lists already matters in C++ and we can't r=
eally change that. They are different instantiations. Even with some kind o=
f canonical ordering this would still be true, and it would only potentiall=
y affect the backend (I.E. by perhaps minimizing instantiations in the case=
where you have similar variants appear with varying orderings). That's=
outside of the realm of the standard anyway, so it's sort of questiona=
ble to even bring it up. There aren't tangible gains regardless.</div><=
/div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--94eb2c0961c426cbe10520633570--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 22:43:56 -0700
Raw View
--001a11c18226bca18e0520639946
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 9:47 PM, Michael Park <mcypark@gmail.com> wrote:
>
> We could consider perhaps introducing separate class templates
> *discriminated_union*, which is a generic, type-safe replacement for C++
> union, and *variant*, as a sum type. (Please don't pay too much attention
> to the names, my point is that we could introduce 2 separate class
> templates.)
>
+1
I have suggested this in the past in boost when the topic has come up. IMO,
to be complete, we would ideally have:
variant<>
discriminated_union<>
union_<>
destructible_union<>
variant has no duplicate types and has direct value semantics, allowing
assignment directly into the variant of one of the field types and not by
field name/id. This is suitable for representing something like a
variant<triangle, circle, square> to be used during collision detection in
some kind of simulation.
discriminated union allows duplicates and is truly more equivalent to a
union with an automatically managed discriminator. You access fields by
"name" (id). This is suitable for things like the implementation of Eric's
join operation for ranges, and is more generally useful in many
applications that involve metaprogramming
union_<> is just a nice-to-have that isn't strictly necessary and would be
a C++ union type that is made via a variadic argument list (this pretty
much necessary for variant's implementation anyway if it is to be
constexpr-aware, so we may as well expose it if an interface can be agreed
upon). This is non-trivial to properly implement, so providing it may be
useful.
destructibe_union<> is similar to union_<> only it is guaranteed to be
destructible even if one of the members has a nontrivial destructor (again,
this is pretty much required for a proper, constexpr-aware
variant-like-type).
On Tue, Sep 22, 2015 at 9:47 PM, Michael Park <mcypark@gmail.com> wrote:
> *Q:* Why not just make type-based operations such as *get<T>* use the
> first *T* in *variant<T, T, **U>*?
>
This seems scary to me. I'd say just leave it as ambiguous and produce a
compile error? In other words, you can access U perfectly fine, but T would
be a compile-time error. Visitation is generally preferred over get<>
operations anyway, so I don't see this as really being much of a legitimate
issue. If variant can't be passed in duplicates then this is also not
really an issue.
On Tue, Sep 22, 2015 at 9:47 PM, Michael Park <mcypark@gmail.com> wrote:
> The sum type use cases effectively would simply ignore the second *T* in *variant<T,
> T, U>*.
>
If we have discriminated_union, I'd suggest making variant<T, T, U> instead
be a compile error. A user can always explicitly make sure that they don't
pass duplicates in the case that they start with a list that potentially
has them, but by making variant<T, T, U> a compile error, we prevent people
from accidentally assuming that the second T is meaningful in the way that
it is with a discriminated_union<>. It also makes more abstract code easier
to deal with if you encounter an object of type "variant<T...>," since you
know that you have a variant with sizeof...(T) fields (and it's trivial to
access them), and any metaprogramming that deals with such a type is simple
without having to trim duplicates or access an associated type list of
non-duplicate field types, etc..
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c18226bca18e0520639946
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=
ue, Sep 22, 2015 at 9:47 PM, Michael Park <span dir=3D"ltr"><<a href=3D"=
mailto:mcypark@gmail.com" target=3D"_blank">mcypark@gmail.com</a>></span=
> 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"><div>We could consider perhaps in=
troducing separate class templates=C2=A0<b style=3D"line-height:17px">discr=
iminated_union</b><span style=3D"line-height:17px">,</span><span style=3D"l=
ine-height:17px">=C2=A0which is a generic, type-safe replacement for C++ un=
ion, and <b>variant</b>, as a sum type. (Please don't pay too much atte=
ntion to the names, my point is that we could introduce 2 separate class te=
mplates.)</span></div></div></blockquote><div><br></div><div>+1</div><div><=
br></div><div>I have suggested this in the past in boost when the topic has=
come up. IMO, to be complete, we would ideally have:</div><div><br></div><=
div>variant<></div><div>discriminated_union<></div><div>union_&=
lt;></div><div>destructible_union<></div><div><br></div><div>varia=
nt has no duplicate types and has direct value semantics, allowing assignme=
nt directly into the variant of one of the field types and not by field nam=
e/id. This is suitable for representing something like a variant<triangl=
e, circle, square> to be used during collision detection in some kind of=
simulation.</div><div><br></div><div>discriminated union allows duplicates=
and is truly more equivalent to a union with an automatically managed disc=
riminator. You access fields by "name" (id). This is suitable for=
things like the implementation of Eric's join operation for ranges, an=
d is more generally useful in many applications that involve metaprogrammin=
g</div><div><br></div><div>union_<> is just a nice-to-have that isn&#=
39;t strictly necessary and would be a C++ union type that is made via a va=
riadic argument list (this pretty much necessary for variant's implemen=
tation anyway if it is to be constexpr-aware, so we may as well expose it i=
f an interface can be agreed upon). This is non-trivial to properly impleme=
nt, so providing it may be useful.</div><div><br></div><div>destructibe_uni=
on<> is similar to union_<> only it is guaranteed to be destruc=
tible even if one of the members has a nontrivial destructor (again, this i=
s pretty much required for a proper, constexpr-aware variant-like-type).</d=
iv><div><br></div><div>On Tue, Sep 22, 2015 at 9:47 PM, Michael Park=C2=A0<=
span dir=3D"ltr"><<a href=3D"mailto:mcypark@gmail.com" target=3D"_blank"=
>mcypark@gmail.com</a>></span>=C2=A0wrote:<br></div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;borde=
r-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><di=
v dir=3D"ltr"><div><b>Q:</b> Why not just make type-based operations such a=
s=C2=A0<b>get<T></b>=C2=A0use the first <b>T</b> in <b>variant<T, =
T,=C2=A0</b><b>U></b>?</div></div></blockquote><div><br></div><div>This =
seems scary to me. I'd say just leave it as ambiguous and produce a com=
pile error? In other words, you can access U perfectly fine, but T would be=
a compile-time error. Visitation is generally preferred over get<> o=
perations anyway, so I don't see this as really being much of a legitim=
ate issue. If variant can't be passed in duplicates then this is also n=
ot really an issue.</div><div><br></div><div>=C2=A0On Tue, Sep 22, 2015 at =
9:47 PM, Michael Park=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:mcypark@=
gmail.com" target=3D"_blank">mcypark@gmail.com</a>></span>=C2=A0wrote:</=
div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:sol=
id;padding-left:1ex"><div dir=3D"ltr"><div>The sum type use cases effective=
ly would simply ignore the second <b>T</b> in <b>variant<T, T, U></b>=
..</div></div></blockquote><div><br></div><div>If we have discriminated_unio=
n, I'd suggest making variant<T, T, U> instead be a compile error=
.. A user can always explicitly make sure that they don't pass duplicate=
s in the case that they start with a list that potentially has them, but by=
making variant<T, T, U> a compile error, we prevent people from acci=
dentally assuming that the second T is meaningful in the way that it is wit=
h a discriminated_union<>. It also makes more abstract code easier to=
deal with if you encounter an object of type "variant<T...>,&qu=
ot; since you know that you have a variant with sizeof...(T) fields (and it=
's trivial to access them), and any metaprogramming that deals with suc=
h a type is simple without having to trim duplicates or access an associate=
d type list of non-duplicate field types, etc..</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c18226bca18e0520639946--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 22 Sep 2015 23:26:01 -0700
Raw View
--001a11c182263a2eee0520643017
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 9:37 PM, Matt Calabrese <calabrese@google.com>
wrote:
>
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> That was the feature as you suggested it, and that's the only way to turn
>> it into a proper compiler error (rather than throwing an exception at
>> runtime if you try to copy a variant that happens to hold a non-noexcept
>> type). The `variant` becomes an immobile type if one of its members isn't
>> noexcept moveable.
>>
>
> No, only if one of its types has a move-constructor that is noexcept and
> there is also no field that has a noexcept default constructor.
>
*sigh* Probably already clear, but in case there is any confusion, that
should say "has a move-constructor that is *not* noexcept."
There are too many double-negatives when talking about noexcept :|
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c182263a2eee0520643017
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=
ue, Sep 22, 2015 at 9:37 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> wrote:=C2=A0<blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D""><div>On=
Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a hr=
ef=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>=
></span>=C2=A0wrote:<br></div><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,2=
04,204);border-left-style:solid;padding-left:1ex">That was the feature as y=
ou suggested it, and that's the only way to turn it into a proper compi=
ler error (rather than throwing an exception at runtime if you try to copy =
a variant that happens to hold a non-noexcept type). The `variant` becomes =
an immobile type if one of its members isn't noexcept moveable.<br></bl=
ockquote><div><br></div></span><div>No, only if one of its types has a move=
-constructor that is noexcept and there is also no field that has a noexcep=
t default constructor.</div></div></div></div></blockquote><div><br></div><=
div>*sigh* Probably already clear, but in case there is any confusion, that=
should say "has a move-constructor that is *not* noexcept."</div=
><div><br></div><div>There are too many double-negatives when talking about=
noexcept :|</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c182263a2eee0520643017--
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 23 Sep 2015 14:38:28 +0800
Raw View
--Apple-Mail=_A86B423C-003B-4050-80B8-F125F4299511
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9323, at 11:32 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> On 9/22/2015 9:21 PM, David Krauss wrote:
>> std::variant uses so many defaults and shortcuts, just due to being a
>> template, that it can=E2=80=99t compete with the actual C unions it mode=
ls.
>=20
> `std::variant` does not model a C union, it does not model a C++ union ei=
ther, it models a discriminated union.
C unions can be discriminated by a member within the initial common subsequ=
ence. You can even have a hierarchy of multiple discriminators this way. (T=
he former is common practice, the latter is a bit unusual.)
> Which defaults and shortcuts are you referring to, and how do those preve=
nt any kind of competition?
Having the discriminator as a separate member outside the union but inside =
its enclosing class, and (in all likelihood) giving it type size_t, pessimi=
zes the layout. There=E2=80=99s no way to stick it into unused bits or foll=
ow a predefined binary format.
> - A generic discriminated union can have a variadic number of members, wh=
ereas one can't expand a pack as members of a raw union.
>=20
> - A generic discriminated union can be constexpr-enabled once, which is a=
n incredibly cumbersome process due to constexpr limitations, and trivially=
exploited as many times as necessary (right away by `std::experimental::op=
tional`, for starters).
This is orthogonal to discrimination. The library should have a variadic li=
teral union template with no discriminator, so the user can decide how to d=
o discrimination.
> Please note that just like a discriminated union is not a sum type, a dis=
criminated union and a plain union are different concepts too. For a plain =
union, the knowledge of which member is active (if any) exists only in the =
mind of the developers,
When I said =E2=80=9CC union=E2=80=9D I assumed that discrimination was bui=
lt in. I should have clarified that.
> so the concept, the model, and the compiler can't build on it.
An IntrusiveDiscriminatedUnion concept with user-defined which() would do j=
ust as well.
--=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/.
--Apple-Mail=_A86B423C-003B-4050-80B8-F125F4299511
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9323, at 11:32 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"ma=
ilto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:=
</div><br class=3D"Apple-interchange-newline"><div class=3D"">On 9/22/2015 =
9:21 PM, David Krauss wrote:<br class=3D""><blockquote type=3D"cite" class=
=3D"">std::variant uses so many defaults and shortcuts, just due to being a=
<br class=3D"">template, that it can=E2=80=99t compete with the actual C un=
ions it models.<br class=3D""></blockquote><br class=3D"">`std::variant` do=
es not model a C union, it does not model a C++ union either, it models a d=
iscriminated union.<br class=3D""></div></blockquote><div><br class=3D""></=
div><div>C unions can be discriminated by a member within the initial commo=
n subsequence. You can even have a hierarchy of multiple discriminators thi=
s way. (The former is common practice, the latter is a bit unusual.)</div><=
br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">Which de=
faults and shortcuts are you referring to, and how do those prevent any kin=
d of competition?<br class=3D""></div></blockquote><div><br class=3D""></di=
v><div>Having the discriminator as a separate member outside the union but =
inside its enclosing class, and (in all likelihood) giving it type <font fa=
ce=3D"Courier" class=3D"">size_t</font>, pessimizes the layout. There=E2=80=
=99s no way to stick it into unused bits or follow a predefined binary form=
at.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"=
">- A generic discriminated union can have a variadic number of members, wh=
ereas one can't expand a pack as members of a raw union.<br class=3D""></di=
v></blockquote><div><blockquote type=3D"cite" class=3D""><br class=3D""></b=
lockquote></div><blockquote type=3D"cite" class=3D""><div class=3D"">- A ge=
neric discriminated union can be constexpr-enabled once, which is an incred=
ibly cumbersome process due to constexpr limitations, and trivially exploit=
ed as many times as necessary (right away by `std::experimental::optional`,=
for starters).<br class=3D""></div></blockquote><div><br class=3D""></div>=
<div>This is orthogonal to discrimination. The library should have a variad=
ic literal union template with no discriminator, so the user can decide how=
to do discrimination.</div><div class=3D""><br class=3D""></div><blockquot=
e type=3D"cite" class=3D""><div class=3D"">Please note that just like a dis=
criminated union is not a sum type, a discriminated union and a plain union=
are different concepts too. For a plain union, the knowledge of which memb=
er is active (if any) exists only in the mind of the developers,</div></blo=
ckquote><div><br class=3D""></div><div class=3D"">When I said =E2=80=9CC un=
ion=E2=80=9D I assumed that discrimination was built in. I should have clar=
ified that.</div><div class=3D""><br class=3D""></div><blockquote type=3D"c=
ite" class=3D""><div class=3D"">so the concept, the model, and the compiler=
can't build on it.<br class=3D""></div></blockquote></div><div class=3D"">=
<br class=3D""></div><div class=3D"">An IntrusiveDiscriminatedUnion concept=
with user-defined <font face=3D"Courier" class=3D"">which()</font> would d=
o just as well.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_A86B423C-003B-4050-80B8-F125F4299511--
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 23 Sep 2015 15:11:39 +0800
Raw View
--Apple-Mail=_CB7BDD1B-C7F8-4078-9D4E-53465EA80FB0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9323, at 11:44 AM, Nicol Bolas <jmckesson@gmail.=
com> wrote:
>=20
> Um, maybe you need to count your memory again. But "without taking a byte=
" is not the same as "someone else provides the storage for me." Storage fo=
r the discriminator still exists; it's just not directly a member of `varia=
nt`.
A bitfield member. =E2=80=9CLess than a byte=E2=80=9D as in =E2=80=9Cthree =
bits.=E2=80=9D The discriminator might also be a function of the values in =
several header bytes.
> Also, this dramatically limits what types you can use. Like, not being ab=
le to use virtual classes or anything that isn't standard layout.
True, but the current restrictions are excessive. Anyway, these are differe=
nt use cases. Pinching bits is mostly exclusive of high-level types.
What=E2=80=99s the connection? Using variant::index() to store some state i=
n addition to identifying the type is the same sort of bit-pinching optimiz=
ation as you find in a C discriminated union. If you have a bunch of states=
to distinguish, declare a state variable and manage it yourself. That=E2=
=80=99s the high-level programming way =E2=80=94 don=E2=80=99t try to pack =
functionality into a class with enough of its own concerns.
Come to think of it, duplicated types are a can of worms. According to the =
proposal, "variant employs same-type optimizations, using the assignment op=
erator instead of construction if the variant already contains a value of t=
he assigned / emplaced type.=E2=80=9D But when assignment isn=E2=80=99t equ=
ivalent to destruction and reconstruction, this optimization isn=E2=80=99t =
valid. For example:
typedef std::vector< int, stateful_alloc< int > > val;
typedef variant< al, T > var;
If the user gives type al for template parameter T, then when this variant =
changes from its library-owned state <0> to the user-owned state <1>, it wi=
ll unexpectedly start putting things in the wrong memory pool. This is what=
you get for combining separate concerns.
> std::variant uses so many defaults and shortcuts, just due to being a tem=
plate, that it can=E2=80=99t compete with the actual C unions it models. Wh=
at=E2=80=99s its real-world use case? What advantage besides saying =E2=80=
=9CLook ma, I=E2=80=99m using templates!=E2=80=9D
> =20
> ... are you kidding? Just on visitation alone, I'd never use a `union` ag=
ain.
Note that visitation can=E2=80=99t tell duplicate members apart=E2=80=A6 So=
rry, I meant to ask for use-cases distinct from sum types.
> C++ is not a functional language. We don't need "sum t=20
Fundamental principles taught in CS classes are not limited to theoreticall=
y pure languages. They=E2=80=99re often solid guidelines to follow.
--=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/.
--Apple-Mail=_CB7BDD1B-C7F8-4078-9D4E-53465EA80FB0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9323, at 11:44 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail=
..com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple=
-interchange-newline"><div class=3D""><div class=3D"">Um, maybe you need to=
count your memory again. But "without taking a byte" is not the same as "s=
omeone else provides the storage for me." Storage for the discriminator <i =
class=3D"">still exists</i>; it's just not directly a member of `variant`.<=
br class=3D""></div></div></blockquote><div><br class=3D""></div><div>A bit=
field member. =E2=80=9CLess than a byte=E2=80=9D as in =E2=80=9Cthree bits.=
=E2=80=9D The discriminator might also be a function of the values in sever=
al header bytes.</div><br class=3D""><blockquote type=3D"cite" class=3D""><=
div class=3D""><div class=3D"">Also, this <i class=3D"">dramatically</i> li=
mits what types you can use. Like, not being able to use virtual classes or=
anything that isn't standard layout.<br class=3D""></div></div></blockquot=
e><div><br class=3D""></div><div>True, but the current restrictions are exc=
essive. Anyway, these are different use cases. Pinching bits is mostly excl=
usive of high-level types.</div><div><br class=3D""></div><div>What=E2=80=
=99s the connection? Using <font face=3D"Courier" class=3D"">variant::index=
()</font> to store some state in addition to identifying the type is the sa=
me sort of bit-pinching optimization as you find in a C discriminated union=
.. If you have a bunch of states to distinguish, declare a <font face=3D"Cou=
rier" class=3D"">state</font> variable and manage it yourself. That=E2=80=
=99s the high-level programming way =E2=80=94 don=E2=80=99t try to pack fun=
ctionality into a class with enough of its own concerns.</div><div><br clas=
s=3D""></div><div>Come to think of it, duplicated types are a can of worms.=
According to the proposal, "<font face=3D"Courier" class=3D"">variant</fon=
t> employs same-type optimizations, using the assignment operator =
;instead of construction if the variant already contains a value =
of the assigned / emplaced type.=E2=80=9D But when assignment isn=E2=
=80=99t equivalent to destruction and reconstruction, this optimization isn=
=E2=80=99t valid. For example:</div><div><br class=3D""></div><div><font fa=
ce=3D"Courier" class=3D"">typedef std::vector< int, stateful_alloc< i=
nt > > val;</font></div><div><font face=3D"Courier" class=3D"">typede=
f variant< al, T > var;</font></div><div><br class=3D""></div><div>If=
the user gives type <font face=3D"Courier" class=3D"">al</font> for templa=
te parameter <font face=3D"Courier" class=3D"">T</font>, then when this var=
iant changes from its library-owned state <font face=3D"Courier" class=3D""=
><0></font> to the user-owned state <font face=3D"Courier" class=3D""=
><1></font>, it will unexpectedly start putting things in the wrong m=
emory pool. This is what you get for combining separate concerns.</div><br =
class=3D""><blockquote type=3D"cite" class=3D""><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div style=3D"word-wrap:break-word" class=3D""><div class=
=3D""><div class=3D""><font face=3D"Courier" class=3D"">std::variant</font>=
uses so many defaults and shortcuts, just due to being a template, that it=
can=E2=80=99t compete with the actual C <font face=3D"Courier" class=3D"">=
union</font>s it models. What=E2=80=99s its real-world use case? What advan=
tage besides saying =E2=80=9CLook ma, I=E2=80=99m using templates!=E2=80=9D=
</div></div></div></blockquote><div class=3D""> </div><div class=3D"">=
.... are you kidding? Just on visitation <i class=3D"">alone</i>, I'd never =
use a `union` again. </div></blockquote><div><br class=3D""></div><div>Note=
that visitation can=E2=80=99t tell duplicate members apart=E2=80=A6 Sorry,=
I meant to ask for use-cases distinct from sum types.</div><br class=3D"">=
<blockquote type=3D"cite" class=3D""><div class=3D""><div class=3D"">C++ is=
not a functional language. We don't need "sum t </div></div></blockqu=
ote><br class=3D""></div><div>Fundamental principles taught in CS classes a=
re not limited to theoretically pure languages. They=E2=80=99re often solid=
guidelines to follow.</div><br class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_CB7BDD1B-C7F8-4078-9D4E-53465EA80FB0--
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 23 Sep 2015 15:26:07 +0800
Raw View
--Apple-Mail=_3F48D51D-421A-4114-9B83-75C77F77E040
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9323, at 3:11 PM, David Krauss <potswa@gmail.com=
> wrote:
>=20
> typedef std::vector< int, stateful_alloc< int > > val;
that should be al not val.
> typedef variant< al, T > var;
>=20
> If the user gives type al for template parameter T, then when this varian=
t changes from its library-owned state <0> to the user-owned state <1>, it =
will unexpectedly start putting things in the wrong memory pool. This is wh=
at you get for combining separate concerns.
>=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_3F48D51D-421A-4114-9B83-75C77F77E040
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9323, at 3:11 PM, David Krauss <<a href=3D"mailto:potswa@gmail.co=
m" class=3D"">potswa@gmail.com</a>> wrote:</div><br class=3D"Apple-inter=
change-newline"><div class=3D""><div style=3D"font-family: Helvetica; font-=
size: 12px; font-style: normal; font-variant: normal; font-weight: normal; =
letter-spacing: normal; line-height: normal; orphans: auto; text-align: sta=
rt; text-indent: 0px; text-transform: none; white-space: normal; widows: au=
to; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><font fa=
ce=3D"Courier" class=3D"">typedef std::vector< int, stateful_alloc< i=
nt > > val;</font></div></div></blockquote><div><br class=3D""></div>=
<div>that should be <font face=3D"Courier" class=3D"">al</font> not <font f=
ace=3D"Courier" class=3D"">val</font>.</div><br class=3D""><blockquote type=
=3D"cite" class=3D""><div class=3D""><div style=3D"font-family: Helvetica; =
font-size: 12px; font-style: normal; font-variant: normal; font-weight: nor=
mal; letter-spacing: normal; line-height: normal; orphans: auto; text-align=
: start; text-indent: 0px; text-transform: none; white-space: normal; widow=
s: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><fo=
nt face=3D"Courier" class=3D"">typedef variant< al, T > var;</font></=
div><div style=3D"font-family: Helvetica; font-size: 12px; font-style: norm=
al; font-variant: normal; font-weight: normal; letter-spacing: normal; line=
-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-t=
ransform: none; white-space: normal; widows: auto; word-spacing: 0px; -webk=
it-text-stroke-width: 0px;" class=3D""><br class=3D""></div><div style=3D"f=
ont-family: Helvetica; font-size: 12px; font-style: normal; font-variant: n=
ormal; font-weight: normal; letter-spacing: normal; line-height: normal; or=
phans: auto; text-align: start; text-indent: 0px; text-transform: none; whi=
te-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-widt=
h: 0px;" class=3D"">If the user gives type<span class=3D"Apple-converted-sp=
ace"> </span><font face=3D"Courier" class=3D"">al</font><span class=3D=
"Apple-converted-space"> </span>for template parameter<span class=3D"A=
pple-converted-space"> </span><font face=3D"Courier" class=3D"">T</fon=
t>, then when this variant changes from its library-owned state<span class=
=3D"Apple-converted-space"> </span><font face=3D"Courier" class=3D"">&=
lt;0></font><span class=3D"Apple-converted-space"> </span>to the us=
er-owned state<span class=3D"Apple-converted-space"> </span><font face=
=3D"Courier" class=3D""><1></font>, it will unexpectedly start puttin=
g things in the wrong memory pool. This is what you get for combining separ=
ate concerns.</div><br class=3D"Apple-interchange-newline"></div></blockquo=
te></div><br class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_3F48D51D-421A-4114-9B83-75C77F77E040--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Wed, 23 Sep 2015 08:39:13 +0100
Raw View
On 23/09/15 07:38, David Krauss wrote:
>=20
>> On 2015=E2=80=9309=E2=80=9323, at 11:32 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> On 9/22/2015 9:21 PM, David Krauss wrote:
>>> std::variant uses so many defaults and shortcuts, just due to being a
>>> template, that it can=E2=80=99t compete with the actual C unions it mod=
els.
>>
>> `std::variant` does not model a C union, it does not model a C++ union
>> either, it models a discriminated union.
>=20
> C unions can be discriminated by a member within the initial common
> subsequence. You can even have a hierarchy of multiple discriminators
> this way. (The former is common practice, the latter is a bit unusual.)
>=20
>> Which defaults and shortcuts are you referring to, and how do those
>> prevent any kind of competition?
>=20
> Having the discriminator as a separate member outside the union but
> inside its enclosing class, and (in all likelihood) giving it type
> size_t, pessimizes the layout. There=E2=80=99s no way to stick it into un=
used
> bits or follow a predefined binary format.
A quality implementation will use the smallest discriminator that would
cover the required values.
It only needs to be explicitly separate for constexpr compatibility,
otherwise it can be the leading member of a built-in union, just like a
C-style discriminated union.
Anthony
--=20
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 23 Sep 2015 17:41:53 +0800
Raw View
--Apple-Mail=_BA7EB44F-4D3B-4904-8EC2-E5638A69D473
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9323, at 3:39 PM, Anthony Williams <anthony.ajw@=
gmail.com> wrote:
>=20
> A quality implementation will use the smallest discriminator that would
> cover the required values.
See std::bitset for something that could be small but never is.
> It only needs to be explicitly separate for constexpr compatibility,
> otherwise it can be the leading member of a built-in union, just like a
> C-style discriminated union.
Adding a leading member before a member of user-provided class type likely =
only causes padding to be added between the two. Intrusiveness, i.e. a user=
-defined accessor function, is needed to gain anything.
Anyway, I=E2=80=99m not arguing for variant to go down this path. I=E2=80=
=99m saying that if you really want to minimize memory usage, C unions can =
do better. And if you want a cleanly factored architecture, sum types do be=
tter. Treating the discriminator as if it were user-defined state, like you=
find in a C discriminated union, muddles variant and turns it into a conte=
ntious compromise.
--=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/.
--Apple-Mail=_BA7EB44F-4D3B-4904-8EC2-E5638A69D473
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9323, at 3:39 PM, Anthony Williams <<a href=3D"mailto:anthony.ajw=
@gmail.com" class=3D"">anthony.ajw@gmail.com</a>> wrote:</div><br class=
=3D"Apple-interchange-newline"><div class=3D""><span style=3D"font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-=
weight: normal; letter-spacing: normal; line-height: normal; orphans: auto;=
text-align: start; text-indent: 0px; text-transform: none; white-space: no=
rmal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; floa=
t: none; display: inline !important;" class=3D"">A quality implementation w=
ill use the smallest discriminator that would</span><br style=3D"font-famil=
y: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; fo=
nt-weight: normal; letter-spacing: normal; line-height: normal; orphans: au=
to; text-align: start; text-indent: 0px; text-transform: none; white-space:=
normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" =
class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; font-sty=
le: normal; font-variant: normal; font-weight: normal; letter-spacing: norm=
al; line-height: normal; orphans: auto; text-align: start; text-indent: 0px=
; text-transform: none; white-space: normal; widows: auto; word-spacing: 0p=
x; -webkit-text-stroke-width: 0px; float: none; display: inline !important;=
" class=3D"">cover the required values.</span><br style=3D"font-family: Hel=
vetica; font-size: 12px; font-style: normal; font-variant: normal; font-wei=
ght: normal; letter-spacing: normal; line-height: normal; orphans: auto; te=
xt-align: start; text-indent: 0px; text-transform: none; white-space: norma=
l; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=
=3D""></div></blockquote><div><br class=3D""></div><div>See <font face=3D"C=
ourier" class=3D"">std::bitset</font> for something that could be small but=
never is.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div cl=
ass=3D""><span style=3D"font-family: Helvetica; font-size: 12px; font-style=
: normal; font-variant: normal; font-weight: normal; letter-spacing: normal=
; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;=
-webkit-text-stroke-width: 0px; float: none; display: inline !important;" =
class=3D"">It only needs to be explicitly separate for constexpr compatibil=
ity,</span><br style=3D"font-family: Helvetica; font-size: 12px; font-style=
: normal; font-variant: normal; font-weight: normal; letter-spacing: normal=
; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;=
-webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: He=
lvetica; font-size: 12px; font-style: normal; font-variant: normal; font-we=
ight: normal; letter-spacing: normal; line-height: normal; orphans: auto; t=
ext-align: start; text-indent: 0px; text-transform: none; white-space: norm=
al; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float:=
none; display: inline !important;" class=3D"">otherwise it can be the lead=
ing member of a built-in union, just like a</span><br style=3D"font-family:=
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font=
-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto=
; text-align: start; text-indent: 0px; text-transform: none; white-space: n=
ormal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" cl=
ass=3D""><span style=3D"font-family: Helvetica; font-size: 12px; font-style=
: normal; font-variant: normal; font-weight: normal; letter-spacing: normal=
; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;=
-webkit-text-stroke-width: 0px; float: none; display: inline !important;" =
class=3D"">C-style discriminated union.</span><br style=3D"font-family: Hel=
vetica; font-size: 12px; font-style: normal; font-variant: normal; font-wei=
ght: normal; letter-spacing: normal; line-height: normal; orphans: auto; te=
xt-align: start; text-indent: 0px; text-transform: none; white-space: norma=
l; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=
=3D""></div></blockquote></div><br class=3D""><div class=3D"">Adding a lead=
ing member before a member of user-provided class type likely only causes p=
adding to be added between the two. Intrusiveness, i.e. a user-defined acce=
ssor function, is needed to gain anything.</div><div class=3D""><br class=
=3D""></div><div class=3D"">Anyway, I=E2=80=99m not arguing for <font face=
=3D"Courier" class=3D"">variant</font> to go down this path. I=E2=80=99m sa=
ying that if you really want to minimize memory usage, C unions can do bett=
er. And if you want a cleanly factored architecture, sum types do better. T=
reating the discriminator as if it were user-defined state, like you find i=
n a C discriminated union, muddles <span style=3D"font-family: Courier=
;" class=3D"">variant</span> and turns it into a contentious compromis=
e.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_BA7EB44F-4D3B-4904-8EC2-E5638A69D473--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 23 Sep 2015 08:53:48 -0300
Raw View
On 9/23/2015 12:49 AM, Nicol Bolas wrote:
> On Tuesday, September 22, 2015 at 11:32:53 PM UTC-4, Agust=C3=ADn K-ballo
> Berg=C3=A9 wrote:
>
> - A discriminated union can have non-trivial non-deleted special memb=
er
> functions (copy/move constructor, copy/move assignment, destructor).
>
> Technically, so can C++11 unions. You just have to write those
> operations for the union manually.
>
> Now, that's terrible, fragile, and highly annoying for obvious reasons.
> But it is technically possible.
Not in a meaningful way, as any non-trivial semantic depends on the=20
discriminator:
union X {
int i;
std::string s;
~X() { /*now what???*/ }
};
As far as being able to define those syntactically, I think you could do=20
that with C++98 unions too, but don't quote me on that.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 23 Sep 2015 09:06:30 -0300
Raw View
On 9/23/2015 4:39 AM, Anthony Williams wrote:
> On 23/09/15 07:38, David Krauss wrote:
>>
>>> On 2015=E2=80=9309=E2=80=9323, at 11:32 AM, Agust=C3=ADn K-ballo Berg=
=C3=A9
>>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>>
>>> Which defaults and shortcuts are you referring to, and how do those
>>> prevent any kind of competition?
>>
>> Having the discriminator as a separate member outside the union but
>> inside its enclosing class, and (in all likelihood) giving it type
>> size_t, pessimizes the layout. There=E2=80=99s no way to stick it into u=
nused
>> bits or follow a predefined binary format.
>
> It only needs to be explicitly separate for constexpr compatibility,
> otherwise it can be the leading member of a built-in union, just like a
> C-style discriminated union.
The common initial sequence special rule is for standard-layout unions=20
only. A standard-layout union must have standard-layout members only.=20
The discriminator has to be explicitly separate for supporting any=20
non-standard-layout member.
http://talesofcpp.fusionfenix.com/post-20/eggs.variant---part-ii-the-conste=
xpr-experience#a-note-on-standard-layout-unions
As far as I can tell, the standard does not guarantee types being=20
standard-layout types other than for a handful of threading facilities=20
(surprisingly, I don't know what the rationale was). And I assume the=20
special layout requirements for `std::complex` force it into being a=20
standard-layout class too, but I'm not sure of that.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Wed, 23 Sep 2015 13:26:31 +0100
Raw View
On 23/09/15 13:06, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
> On 9/23/2015 4:39 AM, Anthony Williams wrote:
>> On 23/09/15 07:38, David Krauss wrote:
>>>
>>>> On 2015=E2=80=9309=E2=80=9323, at 11:32 AM, Agust=C3=ADn K-ballo Berg=
=C3=A9
>>>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>>>
>>>> Which defaults and shortcuts are you referring to, and how do those
>>>> prevent any kind of competition?
>>>
>>> Having the discriminator as a separate member outside the union but
>>> inside its enclosing class, and (in all likelihood) giving it type
>>> size_t, pessimizes the layout. There=E2=80=99s no way to stick it into =
unused
>>> bits or follow a predefined binary format.
>>
>> It only needs to be explicitly separate for constexpr compatibility,
>> otherwise it can be the leading member of a built-in union, just like a
>> C-style discriminated union.
>=20
> The common initial sequence special rule is for standard-layout unions
> only. A standard-layout union must have standard-layout members only.
> The discriminator has to be explicitly separate for supporting any
> non-standard-layout member.
My trial implementation of this is essentially:
template<typename T>
struct wrapper{
int discriminator;
aligned_storage<T>::type storage;
};
union{
wrapper<T> a;
wrapper<U> b;
} u;
You can then access u.a.discriminator or u.b.discriminator to determine
the type, and perform appropriate operations on either u.a.storage or
u.b.storage.
This works well, but can't be constexpr because the
common-initial-sequence stuff doesn't work for constexpr unions --- you
can only access the currently-active member, which you don't know until
you've read the discriminator.
Anthony
--=20
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Larry Evans <cppljevans@suddenlink.net>
Date: Wed, 23 Sep 2015 07:28:24 -0500
Raw View
On 09/23/2015 02:11 AM, David Krauss wrote:
>=20
>> On 2015=E2=80=9309=E2=80=9323, at 11:44 AM, Nicol Bolas <jmckesson@gmail=
..com
>> <mailto:jmckesson@gmail.com>> wrote:
[snip]
>> ... are you kidding? Just on visitation /alone/, I'd never use a
>> `union` again.=20
>=20
> Note that visitation can=E2=80=99t tell duplicate members apart=E2=80=A6 =
Sorry, I meant
> to ask for use-cases distinct from sum types.
>=20
It can if the visitor dispatches on the index instead of
the type while holding the variant as a reference:
template<std::size_t I>
using index=3Dstd::integral_constant<std::size_t,I>;
struct visitor
{
variant<T0,T1>& my_var;
visitor(variant<T0,T1>& a_var)
:my_var(a_var)
{}
void visit(index<0>)
{ //do something with get<0>(my_var)
}
void visit(index<1>)
{ //do something with get<1>(my_var)
}
};
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 23 Sep 2015 09:31:01 -0300
Raw View
On 9/23/2015 2:43 AM, 'Matt Calabrese' via ISO C++ Standard - Future=20
Proposals wrote:
> I have suggested this in the past in boost when the topic has come up.
> IMO, to be complete, we would ideally have:
>
> variant<>
> discriminated_union<>
+1 This would allow to better serve both goals, without muddying the waters=
..
> union_<> is just a nice-to-have that isn't strictly necessary and would
> be a C++ union type that is made via a variadic argument list (this
> pretty much necessary for variant's implementation anyway if it is to be
> constexpr-aware, so we may as well expose it if an interface can be
> agreed upon). This is non-trivial to properly implement, so providing it
> may be useful.
This would be almost useless, once you have a non-trivially-destructible=20
member then `union_` would have a deleted destructor. You wouldn't be=20
able to do much with it unless you are prepared to dynamically allocate=20
it and then leak it.
> destructibe_union<> is similar to union_<> only it is guaranteed to be
> destructible even if one of the members has a nontrivial destructor
> (again, this is pretty much required for a proper, constexpr-aware
> variant-like-type).
Which, I assume, is why you propose this too. This is an incomplete=20
class with a broken invariant, whose sole purpose is to workaround rough=20
areas in the language.
`union_<>` may come in handy if restricted to trivially-destructible=20
types only. `destructible_union<>` is not even half a type, I feel=20
uneasy about this being anything other than a shameful implementation=20
detail.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 23 Sep 2015 09:39:11 -0300
Raw View
On 9/23/2015 9:26 AM, Anthony Williams wrote:
> On 23/09/15 13:06, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
>> On 9/23/2015 4:39 AM, Anthony Williams wrote:
>>> It only needs to be explicitly separate for constexpr compatibility,
>>> otherwise it can be the leading member of a built-in union, just like a
>>> C-style discriminated union.
>>
>> The common initial sequence special rule is for standard-layout unions
>> only. A standard-layout union must have standard-layout members only.
>> The discriminator has to be explicitly separate for supporting any
>> non-standard-layout member.
>
> My trial implementation of this is essentially:
>
> template<typename T>
> struct wrapper{
> int discriminator;
> aligned_storage<T>::type storage;
> };
This explains how constexpr gets in the way, you force all members to be=20
represented as a standard-layout blob.
A raw storage implementation has many other implementation benefits=20
besides that one. However, once you go that way, you can no longer be=20
constexpr-aware at all regardless of the common initial sequence special=20
rule.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Wed, 23 Sep 2015 13:46:10 +0100
Raw View
On 23/09/15 13:39, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
> On 9/23/2015 9:26 AM, Anthony Williams wrote:
>> On 23/09/15 13:06, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
>>> On 9/23/2015 4:39 AM, Anthony Williams wrote:
>>>> It only needs to be explicitly separate for constexpr compatibility,
>>>> otherwise it can be the leading member of a built-in union, just like =
a
>>>> C-style discriminated union.
>>>
>>> The common initial sequence special rule is for standard-layout unions
>>> only. A standard-layout union must have standard-layout members only.
>>> The discriminator has to be explicitly separate for supporting any
>>> non-standard-layout member.
>>
>> My trial implementation of this is essentially:
>>
>> template<typename T>
>> struct wrapper{
>> int discriminator;
>> aligned_storage<T>::type storage;
>> };
>=20
> This explains how constexpr gets in the way, you force all members to be
> represented as a standard-layout blob.
>=20
> A raw storage implementation has many other implementation benefits
> besides that one. However, once you go that way, you can no longer be
> constexpr-aware at all regardless of the common initial sequence special
> rule.
Check out my implementation on bitbucket
(https://bitbucket.org/anthonyw/variant). It uses raw storage and is
constexpr aware. It's just the common-initial-sequence stuff that gets
in the way of reducing the space to that of an optimized C-style
discriminated union.
I had to jump through hoops, but it's doable.
Anthony
--=20
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 23 Sep 2015 10:04:13 -0300
Raw View
On 9/23/2015 9:46 AM, Anthony Williams wrote:
> On 23/09/15 13:39, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
>> On 9/23/2015 9:26 AM, Anthony Williams wrote:
>>> On 23/09/15 13:06, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
>>>> On 9/23/2015 4:39 AM, Anthony Williams wrote:
>>>>> It only needs to be explicitly separate for constexpr compatibility,
>>>>> otherwise it can be the leading member of a built-in union, just like=
a
>>>>> C-style discriminated union.
>>>>
>>>> The common initial sequence special rule is for standard-layout unions
>>>> only. A standard-layout union must have standard-layout members only.
>>>> The discriminator has to be explicitly separate for supporting any
>>>> non-standard-layout member.
>>>
>>> My trial implementation of this is essentially:
>>>
>>> template<typename T>
>>> struct wrapper{
>>> int discriminator;
>>> aligned_storage<T>::type storage;
>>> };
>>
>> This explains how constexpr gets in the way, you force all members to be
>> represented as a standard-layout blob.
>>
>> A raw storage implementation has many other implementation benefits
>> besides that one. However, once you go that way, you can no longer be
>> constexpr-aware at all regardless of the common initial sequence special
>> rule.
>
> Check out my implementation on bitbucket
> (https://bitbucket.org/anthonyw/variant). It uses raw storage and is
> constexpr aware.
As far as I can tell it still uses recursive unions, it does not use raw=20
storage. One just can't put anything into raw storage in a constexpr=20
fashion, because the memory model does not exist during constant=20
expression evaluation.
But I also see things that confuse me, like the use of placement new in=20
a function template flagged constexpr, which AFAIK will never be a=20
constexpr function. I will try having a deeper look at it.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Wed, 23 Sep 2015 14:43:31 +0100
Raw View
On 23/09/15 14:04, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
>> Check out my implementation on bitbucket
>> (https://bitbucket.org/anthonyw/variant). It uses raw storage and is
>> constexpr aware.
>=20
> As far as I can tell it still uses recursive unions, it does not use raw
> storage. One just can't put anything into raw storage in a constexpr
> fashion, because the memory model does not exist during constant
> expression evaluation.
>=20
> But I also see things that confuse me, like the use of placement new in
> a function template flagged constexpr, which AFAIK will never be a
> constexpr function. I will try having a deeper look at it.
Yes, it's a recursive union.
__variant_storage has a second template parameter which detects whether
the type is literal or not. Literal types are stored and constructed
directly in the recursive union, so are constexpr compatible. Other
types have raw storage, so they can still be put in the union.
variant<int,string> can never be constexpr because it can't be literal,
since string has a non-trivial destructor.
variant<int,double> can be with my implementation. There's a test for it
in test_variant.cpp.
It's possible there's some spurious constexpr keywords on templated
functions where I forgot to remove them as I changed the implementation
around, and the compiler didn't complain as you can always declare a
templated function constexpr, even if it violates the rules.
Anthony
--=20
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 23 Sep 2015 06:45:58 -0700 (PDT)
Raw View
------=_Part_249_1619079096.1443015958603
Content-Type: multipart/alternative;
boundary="----=_Part_250_673747907.1443015958603"
------=_Part_250_673747907.1443015958603
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, September 23, 2015 at 12:47:57 AM UTC-4, Michael Park wrote:
>
> Since the Wikipedia article for *tagged union* refers to tagged union,=20
> variant, discriminated union, disjoint union, and sum type as the same=20
> concept, it seems to me that it would be beneficial for the group to agre=
e=20
> on well-defined, common terminology for clear communication.
>
> It seems that Agust=C3=ADn refers to *discriminated union* to mean a gene=
ric,=20
> type-safe version of C++ union, whereas others have referred to a *sum*=
=20
> *type* in the functional language sense, which has characteristics such=
=20
> as the order types is insensitive, and duplicates types aren't distinct=
=20
> states.
>
> We can either provide them as separate class templates, or try to provide=
=20
> a single class template that satisfies both camps.
>
> We could consider perhaps introducing separate class templates=20
> *discriminated_union*, which is a generic, type-safe replacement for C++=
=20
> union, and *variant*, as a sum type. (Please don't pay too much attention=
=20
> to the names, my point is that we could introduce 2 separate class=20
> templates.)
>
> Now, of course introducing one class template *variant* that supports=20
> both use cases would be (more?) desirable. I think the way we would do th=
is=20
> is:
>
> - If types are unique, both index-based and type-based operations are=
=20
> available, and a type_switch can also be used.
> (Both discriminated union and sum types behave normally, as expected)
> - If types contain duplicates, we lose the type-based operations for=
=20
> the ones that are duplicated.
> e.g. For *variant<T, T, U>*, *get<T>* is invalid, *get<U>* is valid.
> (As a discriminated union, everything is fine since the index-based=20
> operations will be used anyway unless using types is more convenient. =
As a=20
> sum type, the expectation would be that *variant<T, T, U>* behave=20
> equivalently as *variant<T, U>*. Since the support for duplicate types=
=20
> is only to facilitate meta-programming which is a niche within (typica=
lly)=20
> C++ experts, it seems reasonable to put the burden on them to perform=
=20
> *unique* on the types.)
>
> The big problem here is that this doesn't satisfy the "sum types" people.=
=20
They want `variant<int, float>` to be effectively equivalent to=20
`variant<float, int>`.
This also impacts the behavior of the type. The standard `union` practice=
=20
of "default construct first element" is not acceptable for "sum types"=20
users, since they are order-independent. So either there is no default=20
construction at all or there must be an empty state.
None of these are acceptable to the "discriminated union" people.
A single class will not serve the needs of both. And while I am firmly on=
=20
the "discriminated union" side, what you suggest isn't a compromise for the=
=20
"sum types" side. They don't get what they want, and gain pretty much=20
nothing.
Personally, I say we standardize `variant` as a "discriminated union" and=
=20
tell the "sum types" guys to propose a class for that *separately*. We=20
establish the need for two types, and thus each one needs to justify itself=
=20
independently of the other.
--=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_250_673747907.1443015958603
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, September 23, 2015 at 12:47:57 AM UTC-4, Michael Park wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Since the=
Wikipedia article for <b>tagged union</b> refers to tagged union, variant,=
discriminated union, disjoint union, and sum type as the same concept, it =
seems to me that it would be beneficial for the group to agree on well-defi=
ned, common terminology for clear communication.<br></div><div><br></div><d=
iv>It seems that Agust=C3=ADn<span style=3D"white-space:nowrap">=C2=A0</spa=
n>refers to <b>discriminated union</b>=C2=A0to mean a generic, type-safe ve=
rsion of C++ union, whereas others have referred to a <b>sum</b>=C2=A0<b>ty=
pe</b>=C2=A0in the functional language sense, which has characteristics suc=
h as the order types is insensitive, and duplicates types aren't distin=
ct states.</div><div><br></div><div>We can either provide them as separate =
class templates, or try to provide a single class template that satisfies b=
oth camps.</div><div><br></div><div>We could consider perhaps introducing s=
eparate class templates=C2=A0<b style=3D"line-height:17px">discriminated_un=
ion</b><span style=3D"line-height:17px">,</span><span style=3D"line-height:=
17px"><wbr>=C2=A0which is a generic, type-safe replacement for C++ union, a=
nd <b>variant</b>, as a sum type. (Please don't pay too much attention =
to the names, my point is that we could introduce 2 separate class template=
s.)</span></div><div><br></div><div>Now, of course introducing one class te=
mplate <b>variant</b>=C2=A0that supports both use cases would be (more?) de=
sirable. I think the way we would do this is:</div><div><ul><li><span style=
=3D"line-height:normal">If types are unique, both index-based and type-base=
d operations are available, and a=C2=A0type_switch can also be used.<br>(Bo=
th discriminated union and sum types behave normally, as expected)</span></=
li><li><span style=3D"line-height:normal">If types contain duplicates, we l=
ose the type-based operations for the ones that are duplicated.<br></span><=
span style=3D"line-height:normal">e.g. For <b>variant<T, T, U></b>, <=
b>get<T></b> is invalid, <b>get<U></b> is valid.<br>(As a discr=
iminated union, everything is fine since the index-based operations will be=
used anyway unless using types is more convenient. As a sum type, the expe=
ctation would be that <b>variant<T, T, U></b>=C2=A0behave equivalentl=
y as <b>variant<T, U></b>. Since the support for duplicate types is o=
nly to facilitate meta-programming which is a niche within (typically) C++ =
experts, it seems reasonable to put the burden on them to perform=C2=A0<b>u=
nique</b>=C2=A0on the types.)</span></li></ul></div></div></blockquote><div=
>The big problem here is that this doesn't satisfy the "sum types&=
quot; people. They want `variant<int, float>` to be effectively equiv=
alent to `variant<float, int>`.<br><br>This also impacts the behavior=
of the type. The standard `union` practice of "default construct firs=
t element" is not acceptable for "sum types" users, since th=
ey are order-independent. So either there is no default construction at all=
or there must be an empty state.<br><br>None of these are acceptable to th=
e "discriminated union" people.<br><br>A single class will not se=
rve the needs of both. And while I am firmly on the "discriminated uni=
on" side, what you suggest isn't a compromise for the "sum ty=
pes" side. They don't get what they want, and gain pretty much not=
hing.<br></div><br>Personally, I say we standardize `variant` as a "di=
scriminated union" and tell the "sum types" guys to propose =
a class for that <i>separately</i>. We establish the need for two types, an=
d thus each one needs to justify itself independently of the other.<br>
<p></p>
-- <br />
<br />
--- <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 />
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_250_673747907.1443015958603--
------=_Part_249_1619079096.1443015958603--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Wed, 23 Sep 2015 10:16:27 -0400
Raw View
On 2015-09-22 19:39, Nicol Bolas wrote:
> Let's say I have a variant, and I need to put types into it that can
> throw on move. And I catch an exception, resolve something, and move
> on. I inspect the variant, and I find that it is empty.
Let's say you have a type "MyType" that can throw on move. And you catch
an exception, resolve something, and move on. If the exception came from
a move operation on a MyType, how can you reason *anything* about the
state of the MyType?
What makes variant special that it is required to be in a "reasonable"
state when modifying it throws an exception?
--
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 23 Sep 2015 07:20:04 -0700 (PDT)
Raw View
------=_Part_128_1988709877.1443018004343
Content-Type: multipart/alternative;
boundary="----=_Part_129_279371356.1443018004344"
------=_Part_129_279371356.1443018004344
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> That was the feature as you suggested it, and that's the only way to turn
>> it into a proper compiler error (rather than throwing an exception at
>> runtime if you try to copy a variant that happens to hold a non-noexcept
>> type). The `variant` becomes an immobile type if one of its members isn't
>> noexcept moveable.
>>
>
> No, only if one of its types has a move-constructor that is noexcept and
> there is also no field that has a noexcept default constructor.
>
I missed that part.
*However*, that doesn't change the fact that it's still unusable. Earlier
in the thread, I posed a hypothetical: a failure in a `variant` copy that
is caught and processing proceeds.
How does later code determine if the `variant` is in the state it is in
because of a failure or because the user deliberately set it to that state?
The answer is you can't. And that's *bad*. A user who needs to recover from
such failures* needs* to be able to tell the difference. It introduces very
subtle bugs if the user doesn't do the right thing.
An invalid variant introduces very *noisy* bugs.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> And I don't even know what "make it optional" means; it can't mean to
>> wrap it in an `optional`, since that class probably forwards the throwing
>> behavior of the copy/move operations of T. Do you mean by making it a
>> pointer-to-T of some kind?
>>
>
> No, I really do simply mean optional<variant<T...>>, where one or more of
> T has a move-constructor that can throw.
>
That changes nothing. If your T... list makes the `variant` type immobile,
then the `optional` container will be *similarly* immobile. Remember:
`optional` is a value type, so its copy/move constructor will copy/move its
contents. And if its contained type doesn't have those, then neither will
`optional`.
Wrapping an immobile type in `optional` does not make it mobile. Just like
wrapping an immobile type in `std::pair` doesn't make it mobile.
The only way to hand it off to someone is to heap-allocate it and use it by
pointer.
> In this manner, even though the variant itself may have a move-constructor
> that can throw and where at least one of T is not
> noexcept-default-constructible, the optional itself can properly implement
> a move-assignment operator and copy-assignment operator because it has the
> nullopt state to fall back to.
>
That's not how optional works with copy failure. It does not suddenly
transform into the `nullopt` state.
Even if `optional` worked exactly as you think it does, why should users
have to add the syntactic noise of `optional<variant<...>>`? Not to mention
the *constant* need to indirectly access the actual contained variant.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> But for `variant`, you want throwing copy/move to mean "immobile". That's
>> not even *remotely* the same thing. That's not merely forwarding the
>> class's restriction; that's making the class *more* restricted.
>>
>
> These requirements don't come out of the blue. They are inherent in the
> operation that you are implementing.
>
No, they are not. As evidenced by N4542, there are other solutions.
There is no reason for a user to *assume* that a variant that only contains
throwing move types will be immobile. That is not something most users have
any experience with. I don't know of *any* variant type that does that.
Indeed, I don't know of any C++ type *period* that does this.
So for users, that requirement most certainly will come "out of the blue."
> Copy-assignment of a sum type that has fields with move-constructors that
> can through is a very different operation from the copy-assignment of a
> struct.
>
.... why? To me as a user, that seems like very esoteric C++ knowledge. Why
do I need to know about such deep elements of copying behavior just to use
a type?
I expect copying inside a variant to be functionally no different from
copying inside a struct. And if it does work differently, I want that
difference to be immediately apparent.
An invalid state is a part of the interface. I can therefore look up what
`is_valid` does and when the object becomes invalid. What you're suggesting
is not something that is apparent to the user.
Neither is the "on exception, become an arbitrary state" solution.
They are completely different problems that have different requirements and
> different solutions. Your intuitions do not carry over, and that's
> unfortunate, but it is also reality. I understand that you personally don't
> find that particular requirement very obvious, but again, one's intuitions
> have no impact on what is actually true. Either yo represent those
> requirements, or you weaken the invariants of the type by introducing an
> invalid state, thereby complicating things further.
>
So, having an invalid state that is only used by people who need it is more
complicated than having a type become immobile even though its contained
types are mobile, just in an unusual way? That is less complicated?
You have a very unique sense of what is "complicated".
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> This requirement exists out of necessity, whether people immediately
>>> understand that or not.
>>>
>>
>> It's only "necessity" because you choose not to accept the (perfectly
>> reasonable) alternative. You're saying that your solution is necessary, if
>> you preemptively define all other solutions as bad.
>>
>
> No, it's necessity if you want to avoid unnecessarily complicating all or
> most contracts that deal with your type.
>
Yes, that's exactly what I said: you arbitrarily decide that all other
solutions are "unnecessarily complicating all or most contracts" or
whatever.
You don't seem to understand that this statement is what is in question
here. We do not agree that having an invalid state "unnecessarily
complicating all or most contracts". That belief is the foundation upon
which your entire proposal rests, and it is that belief which is not a fact
in evidence.
That's what you need to provide a convincing argument for.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>>
>> But please don't pretend that you aren't significantly inconveniencing
>> actual potential users of the class.
>>
>
> I don't have to pretend, it's just a fact.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_129_279371356.1443018004344
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese wrote=
:<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><div cl=
ass=3D"gmail_quote"><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0=
<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfusca=
ted-mailto=3D"Q_Puexk9BgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
9;javascript:';return true;" onclick=3D"this.href=3D'javascript:=
9;;return true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:<br></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">That was the feature as you suggested it, and that's =
the only way to turn it into a proper compiler error (rather than throwing =
an exception at runtime if you try to copy a variant that happens to hold a=
non-noexcept type). The `variant` becomes an immobile type if one of its m=
embers isn't noexcept moveable.<br></blockquote><div><br></div><div>No,=
only if one of its types has a move-constructor that is noexcept and there=
is also no field that has a noexcept default constructor.</div></div></div=
></div></blockquote><div><br>I missed that part.<br><br><i>However</i>, tha=
t doesn't change the fact that it's still unusable. Earlier in the =
thread, I posed a hypothetical: a failure in a `variant` copy that is caugh=
t and processing proceeds.<br><br>How does later code determine if the `var=
iant` is in the state it is in because of a failure or because the user del=
iberately set it to that state?<br><br>The answer is you can't. And tha=
t's <i>bad</i>. A user who needs to recover from such failures<i> needs=
</i> to be able to tell the difference. It introduces very subtle bugs if t=
he user doesn't do the right thing.<br><br>An invalid variant introduce=
s very <i>noisy</i> bugs.<br><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div><=
/div><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"lt=
r"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"Q=
_Puexk9BgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&#=
39;;return true;" onclick=3D"this.href=3D'javascript:';return true;=
">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:<br></div><blockquote cl=
ass=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:1e=
x"> And I don't even know what "make it optional" means; it c=
an't mean to wrap it in an `optional`, since that class probably forwar=
ds the throwing behavior of the copy/move operations of T. Do you mean by m=
aking it a pointer-to-T of some kind?<br></blockquote><div><br></div><div>N=
o, I really do simply mean optional<variant<T...>>, where one o=
r more of T has a move-constructor that can throw.</div></div></div></div><=
/blockquote><div><br>That changes nothing. If your T... list makes the `var=
iant` type immobile, then the `optional` container will be <i>similarly</i>=
immobile. Remember: `optional` is a value type, so its copy/move construct=
or will copy/move its contents. And if its contained type doesn't have =
those, then neither will `optional`.<br><br>Wrapping an immobile type in `o=
ptional` does not make it mobile. Just like wrapping an immobile type in `s=
td::pair` doesn't make it mobile.<br><br>The only way to hand it off to=
someone is to heap-allocate it and use it by pointer.<br>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D=
"gmail_quote"><div>In this manner, even though the variant itself may have =
a move-constructor that can throw and where at least one of T is not noexce=
pt-default-<wbr>constructible, the optional itself can properly implement a=
move-assignment operator and copy-assignment operator because it has the n=
ullopt state to fall back to.</div></div></div></div></blockquote><div><br>=
That's not how optional works with copy failure. It does not suddenly t=
ransform into the `nullopt` state.<br><br>Even if `optional` worked exactly=
as you think it does, why should users have to add the syntactic noise of =
`optional<variant<...>>`? Not to mention the <i>constant</i> ne=
ed to indirectly access the actual contained variant.<br>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"=
gmail_quote"><div></div><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=
=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-o=
bfuscated-mailto=3D"Q_Puexk9BgAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:</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>But for `variant`, you want throwing copy/move to =
mean "immobile". That's not even <i>remotely</i> the same thi=
ng. That's not merely forwarding the class's restriction; that'=
s making the class <i>more</i> restricted.<br></div></blockquote><div><br><=
/div><div>These requirements don't come out of the blue. They are inher=
ent in the operation that you are implementing.</div></div></div></div></bl=
ockquote><div><br>No, they are not. As evidenced by N4542, there are other =
solutions.<br><br>There is no reason for a user to <i>assume</i> that a var=
iant that only contains throwing move types will be immobile. That is not s=
omething most users have any experience with. I don't know of <i>any</i=
> variant type that does that. Indeed, I don't know of any C++ type <i>=
period</i> that does this.<br><br>So for users, that requirement most certa=
inly will come "out of the blue."<br>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quot=
e"><div>Copy-assignment of a sum type that has fields with move-constructor=
s that can through is a very different operation from the copy-assignment o=
f a struct.</div></div></div></div></blockquote><div><br>... why? To me as =
a user, that seems like very esoteric C++ knowledge. Why do I need to know =
about such deep elements of copying behavior just to use a type?<br><br>I e=
xpect copying inside a variant to be functionally no different from copying=
inside a struct. And if it does work differently, I want that difference t=
o be immediately apparent.<br><br>An invalid state is a part of the interfa=
ce. I can therefore look up what `is_valid` does and when the object become=
s invalid. What you're suggesting is not something that is apparent to =
the user.<br><br>Neither is the "on exception, become an arbitrary sta=
te" solution.<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><div class=3D"gmail_quote"><div>They are completely=
different problems that have different requirements and different solution=
s. Your intuitions do not carry over, and that's unfortunate, but it is=
also reality. I understand that you personally don't find that particu=
lar requirement very obvious, but again, one's intuitions have no impac=
t on what is actually true. Either yo represent those requirements, or you =
weaken the invariants of the type by introducing an invalid state, thereby =
complicating things further.</div></div></div></div></blockquote><div><br>S=
o, having an invalid state that is only used by people who need it is more =
complicated than having a type become immobile even though its contained ty=
pes are mobile, just in an unusual way? That is less complicated?<br><br>Yo=
u have a very unique sense of what is "complicated".<br>=C2=A0</d=
iv><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><div =
class=3D"gmail_quote"><div></div><div></div><div>On Tue, Sep 22, 2015 at 8:=
16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" targe=
t=3D"_blank" gdf-obfuscated-mailto=3D"Q_Puexk9BgAJ" rel=3D"nofollow" onmous=
edown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hr=
ef=3D'javascript:';return true;">jmck...@gmail.com</a>></span>=
=C2=A0<wbr>wrote:=C2=A0</div><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><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div>This requirement exists out=
of necessity, whether people immediately understand that or not.</div></di=
v></div></div></blockquote></span><div><br>It's only "necessity&qu=
ot; because you choose not to accept the (perfectly reasonable) alternative=
.. You're saying that your solution is necessary, if you preemptively de=
fine all other solutions as bad.<br></div></blockquote><div><br></div><div>=
No, it's necessity if you want to avoid unnecessarily complicating all =
or most contracts that deal with your type.</div></div></div></div></blockq=
uote><div><br>Yes, that's exactly what I said: you arbitrarily decide t=
hat all other solutions are "unnecessarily complicating all or most co=
ntracts" or whatever.<br><br>You don't seem to understand that thi=
s statement is what is in question here. We do not agree that having an inv=
alid state "unnecessarily complicating all or most contracts". Th=
at belief is the foundation upon which your entire proposal rests, and it i=
s that belief which is not a fact in evidence.<br><br>That's what you n=
eed to provide a convincing argument for.<br>=C2=A0<br></div><blockquote cl=
ass=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 class=3D"gmail_qu=
ote">On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr">&l=
t;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"Q_Puex=
k9BgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';r=
eturn true;" onclick=3D"this.href=3D'javascript:';return true;">jmc=
k...@gmail.com</a>></span>=C2=A0wrote:=C2=A0<blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>But pl=
ease don't pretend that you aren't significantly inconveniencing ac=
tual potential users of the class.<br></div></blockquote><div><br></div><di=
v>I don't have to pretend, it's just a fact.</div></div></div></div=
>
</blockquote>
<p></p>
-- <br />
<br />
--- <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 />
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_129_279371356.1443018004344--
------=_Part_128_1988709877.1443018004343--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 23 Sep 2015 07:29:59 -0700 (PDT)
Raw View
------=_Part_492_838105734.1443018599740
Content-Type: multipart/alternative;
boundary="----=_Part_493_1910689646.1443018599740"
------=_Part_493_1910689646.1443018599740
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 23, 2015 at 10:16:43 AM UTC-4, Matthew Woehlke
wrote:
>
> On 2015-09-22 19:39, Nicol Bolas wrote:
> > Let's say I have a variant, and I need to put types into it that can
> > throw on move. And I catch an exception, resolve something, and move
> > on. I inspect the variant, and I find that it is empty.
>
> Let's say you have a type "MyType" that can throw on move. And you catch
> an exception, resolve something, and move on. If the exception came from
> a move operation on a MyType, how can you reason *anything* about the
> state of the MyType?
>
Because presumably, MyType has some exception guarantee built into it. And
if it doesn't, that's *all your fault* for writing your type so badly. Even
"valid-but-unknown" at least makes the type semi-useful.
> What makes variant special that it is required to be in a "reasonable"
> state when modifying it throws an exception?
>
Because it's a standard library class. And therefore, it can and will be
used by people who know how to implement the strong exception guarantee.
If `MyType` provides the strong exception guarantee, `variant<MyType>`
should not *weaken* that guarantee.
The question is not whether `variant` should be strongly exception safe.
It's *how* to achieve it.
Having an explicit invalid state, only reachable in the event of a throwing
copy/move, avoids lots of overhead. If the user sees an invalid `variant`,
then they know how it got that way: from a throwing copy/move. And
therefore, they know that they forgot to reset it to a known value or
something. It makes it easier to track down bugs.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_493_1910689646.1443018599740
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, September 23, 2015 at 10:16:43 AM UTC-4, Mat=
thew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2015-09-=
22 19:39, Nicol Bolas wrote:
<br>> Let's say I have a variant, and I need to put types into it th=
at can
<br>> throw on move. And I catch an exception, resolve something, and mo=
ve
<br>> on. I inspect the variant, and I find that it is empty.
<br>
<br>Let's say you have a type "MyType" that can throw on move=
.. And you catch
<br>an exception, resolve something, and move on. If the exception came fro=
m
<br>a move operation on a MyType, how can you reason *anything* about the
<br>state of the MyType?
<br></blockquote><div><br>Because presumably, MyType has some exception gua=
rantee built into it. And if it doesn't, that's <i>all your fault</=
i> for writing your type so badly. Even "valid-but-unknown" at le=
ast makes the type semi-useful.<br>=C2=A0</div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;">What makes variant special that it is required to be in a =
"reasonable"
<br>state when modifying it throws an exception?<br></blockquote><div><br>B=
ecause it's a standard library class. And therefore, it can and will be=
used by people who know how to implement the strong exception guarantee.<b=
r><br>If `MyType` provides the strong exception guarantee, `variant<MyTy=
pe>` should not <i>weaken</i> that guarantee.<br><br>The question is not=
whether `variant` should be strongly exception safe. It's <i>how</i> t=
o achieve it.<br><br>Having an explicit invalid state, only reachable in th=
e event of a throwing copy/move, avoids lots of overhead. If the user sees =
an invalid `variant`, then they know how it got that way: from a throwing c=
opy/move. And therefore, they know that they forgot to reset it to a known =
value or something. It makes it easier to track down bugs.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_493_1910689646.1443018599740--
------=_Part_492_838105734.1443018599740--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 23 Sep 2015 11:00:49 -0400
Raw View
--001a11c3cffa55254c05206b616d
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 22, 2015 at 6:23 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Tue, Sep 22, 2015 at 1:43 PM, Matt Calabrese <calabrese@google.com>
> wrote:\
>>
>> I don't think that's a reasonable rationale. If you start with a basic
>> guarantee, you are not impacting people who only need the basic guarantee,
>> and people who need to restore the old state can generally do so if they
>> need to. On the other hand, if you start with the strong guarantee where it
>> doesn't naturally fit (I.E. requires double storage and internally a way to
>> keep track of which location holds the actual instance), then a user can't
>> avoid that overhead even when they don't need it, and in the case of double
>> storage, you're paying for that overhead everywhere even though you only
>> propagate an exception in an "exceptional" case.
>>
>
> I want to reiterate this because I think it might be the most important
> point of the discussion and may get lost in the mix. Even for types with
> move constructors that can throw (I.E. something like a list), the case of
> it throwing is often more theoretical than practical, as in most people
> will never ever see it happen. However, even though they'd likely never see
> it happen, they'd always pay for something like double storage if that were
> what was used to meet the strong guarantee, as has been advocated. This can
> potentially have huge ramifications for an entire program in the
> non-exceptional case, just so that if/when move-construction really does
> propagate an exception, it *might* be easier to handle in some situations,
> depending on what users need to do for that particular case. This seems
> like a really questionable rationale, to me at least. What makes variant so
> much more unique in that the basic guarantee isn't acceptable here?
>
The difference/uniqueness is assignment. Most functions with basic
guarantees can be "upgraded" via assignment or non-throwing swap - ie
assign back a copy of the old value. But for variant, assignment is the
function in question, so there is no easy way to implement strong on top of
basic.
* I want to give Peter Dimov some credit here - this is the conclusion he
reached (from the 800 committee emails). I don't want to take credit for
his thoughts. But at the same time, the above is my interpretation, so you
can blame me, not him.
I agree double-buffering may be too high of a cost. If there was a
formulation that _defaulted_ to double-buffering (only when needed), but
had a non-hacky means of opting-out, I'd be happy with that.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c3cffa55254c05206b616d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 22, 2015 at 6:23 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote">On Tue, Sep 22, 2015 at 1:43 PM, Matt=
Calabrese <span dir=3D"ltr"><<a href=3D"mailto:calabrese@google.com" ta=
rget=3D"_blank">calabrese@google.com</a>></span> wrote:\<span class=3D""=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div>I don't think that's a reasonable =
rationale. If you start with a basic guarantee, you are not impacting peopl=
e who only need the basic guarantee, and people who need to restore the old=
state can generally do so if they need to. On the other hand, if you start=
with the strong guarantee where it doesn't naturally fit (I.E. require=
s double storage and internally a way to keep track of which location holds=
the actual instance), then a user can't avoid that overhead even when =
they don't need it, and in the case of double storage, you're payin=
g for that overhead everywhere even though you only propagate an exception =
in an "exceptional" case.</div></div></div></div></blockquote><di=
v><br></div></span><div>I want to reiterate this because I think it might b=
e the most important point of the discussion and may get lost in the mix. E=
ven for types with move constructors that can throw (I.E. something like a =
list), the case of it throwing is often more theoretical than practical, as=
in most people will never ever see it happen. However, even though they=
9;d likely never see it happen, they'd always pay for something like do=
uble storage if that were what was used to meet the strong guarantee, as ha=
s been advocated. This can potentially have huge ramifications for an entir=
e program in the non-exceptional case, just so that if/when move-constructi=
on really does propagate an exception, it *might* be easier to handle in so=
me situations, depending on what users need to do for that particular case.=
This seems like a really questionable rationale, to me at least. What make=
s variant so much more unique in that the basic guarantee isn't accepta=
ble here?</div></div></div></div></blockquote><div><br></div><div>The diffe=
rence/uniqueness is assignment.=C2=A0 Most functions with basic guarantees =
can be "upgraded" via assignment or non-throwing swap - ie assign=
back a copy of the old value.=C2=A0 But for variant, assignment is the fun=
ction in question, so there is no easy way to implement strong on top of ba=
sic.<br><br></div><div>* I want to give Peter Dimov some credit here - this=
is the conclusion he reached (from the 800 committee emails).=C2=A0 I don&=
#39;t want to take credit for his thoughts.=C2=A0 But at the same time, the=
above is my interpretation, so you can blame me, not him.<br></div><div><b=
r></div><div>I agree double-buffering may be too high of a cost.=C2=A0 If t=
here was a formulation that _defaulted_ to double-buffering (only when need=
ed), but had a non-hacky means of opting-out, I'd be happy with that.<b=
r><br></div><div>Tony<br></div></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3cffa55254c05206b616d--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 23 Sep 2015 13:16:58 -0400
Raw View
--089e011605f431899305206d4822
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wed, Sep 23, 2015 at 12:47 AM, Michael Park <mcypark@gmail.com> wrote:
> Since the Wikipedia article for *tagged union* refers to tagged union,
> variant, discriminated union, disjoint union, and sum type as the same
> concept, it seems to me that it would be beneficial for the group to agre=
e
> on well-defined, common terminology for clear communication.
>
> It seems that Agust=C3=ADn refers to *discriminated union* to mean a gene=
ric,
> type-safe version of C++ union, whereas others have referred to a *sum*
> *type* in the functional language sense, which has characteristics such
> as the order types is insensitive, and duplicates types aren't distinct
> states.
>
Yes, for these discussions at least, we should use "discriminated union"
for a variant with a _list_ of types, so types are ordered, duplicates are
allowed, and duplicates are different states; and "sum type" as a variant
with a _set_ of types, so types are not ordered, and duplicates are
"deduplicated"/collapsed.
> We can either provide them as separate class templates, or try to provide
> a single class template that satisfies both camps.
>
Currently sum types are hard, discriminated unions are easier (still hard,
just easier). I'd also say discriminated unions are also "closer" to C++.
> *Q:* Why not just make type-based operations such as *get<T>* use the
> first *T* in *variant<T, T, **U>*?
>
> *A:* After Anthony Williams presented his approach to this problem, it
> seemed to me that we can perfectly satisfy both discriminated union and s=
um
> type use cases.
>
>
> I think disabling the type-based operations for the types that duplicate,
> and forcing the deduplication in the cases where it is the desired
> semantics is a good compromise.
>
> What do you think?
>
>
I lean that way. get<int> should be a compiler error if there are multiple
ints in the variant. There is a good chance that get<int> is an error in
that case. Same with visitation. Which means we need a by-index visitation
mechanism.
Sucks for portability where variant<size_t, unsigned long> might be
different types on your initial platform, but the same type on your next
platform. ie your get<size_t> code is probably correct, but suddenly
doesn't compile on the new platform.
The alternative, however, is that get<size_t> threw on the first platform
and is now (incorrectly) not throwing on the new platform.
Tony
--=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/.
--089e011605f431899305206d4822
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Sep 23, 2015 at 12:47 AM, Michael Park <span dir=3D"ltr"><<a=
href=3D"mailto:mcypark@gmail.com" target=3D"_blank">mcypark@gmail.com</a>&=
gt;</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"><div>S=
ince the Wikipedia article for <b>tagged union</b> refers to tagged union, =
variant, discriminated union, disjoint union, and sum type as the same conc=
ept, it seems to me that it would be beneficial for the group to agree on w=
ell-defined, common terminology for clear communication.<br></div><div><br>=
</div><div>It seems that Agust=C3=ADn<span style=3D"white-space:nowrap">=C2=
=A0</span>refers to <b>discriminated union</b>=C2=A0to mean a generic, type=
-safe version of C++ union, whereas others have referred to a <b>sum</b>=C2=
=A0<b>type</b>=C2=A0in the functional language sense, which has characteris=
tics such as the order types is insensitive, and duplicates types aren'=
t distinct states.</div></div></blockquote><div><br></div><div>Yes, for the=
se discussions at least, we should use "discriminated union" for =
a variant with a _list_ of types, so types are ordered, duplicates are allo=
wed, and duplicates are different states; and "sum type" as a var=
iant with a _set_ of types, so types are not ordered, and duplicates are &q=
uot;deduplicated"/collapsed.<br><br></div><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"><div><br></div><div>We can either provide them as separ=
ate class templates, or try to provide a single class template that satisfi=
es both camps.</div></div></blockquote><div><br></div><div>Currently sum ty=
pes are hard, discriminated unions are easier (still hard, just easier).=C2=
=A0 I'd also say discriminated unions are also "closer" to C+=
+.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></=
div><b>Q:</b> Why not just make type-based operations such as=C2=A0<b>get&l=
t;T></b>=C2=A0use the first <b>T</b> in <b>variant<T, T,=C2=A0</b><b>=
U></b>?<div><br></div><div><b>A:</b> After Anthony Williams presented hi=
s approach to this problem, it seemed to me that we can perfectly satisfy b=
oth discriminated union and sum type use cases.</div><div><br></div><br><di=
v>I think disabling the type-based operations for the types that duplicate,=
and forcing the deduplication in the cases where it is the desired semanti=
cs is a good compromise.</div><div><br></div><div>What do you think?</div><=
div><div><div><br></div></div></div></div></blockquote><div><br></div><div>=
I lean that way.=C2=A0 get<int> should be a compiler error if there a=
re multiple ints in the variant.=C2=A0 There is a good chance that get<i=
nt> is an error in that case.=C2=A0 Same with visitation. Which means we=
need a by-index visitation mechanism. <br><br></div><div>Sucks for portabi=
lity where variant<size_t, unsigned long> might be different types on=
your initial platform, but the same type on your next platform. ie your ge=
t<size_t> code is probably correct, but suddenly doesn't compile =
on the new platform.<br></div><div>The alternative, however, is that get<=
;size_t> threw on the first platform and is now (incorrectly) not throwi=
ng on the new platform.<br></div><div>=C2=A0</div><br></div><div class=3D"g=
mail_quote">Tony<br></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e011605f431899305206d4822--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 23 Sep 2015 13:53:15 -0400
Raw View
--001a11c377a2f6fe0005206dc9af
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wed, Sep 23, 2015 at 3:11 AM, David Krauss <potswa@gmail.com> wrote:
> Come to think of it, duplicated types are a can of worms. According to th=
e
> proposal, "variant employs same-type optimizations, using the assignment
> operator instead of construction if the variant already contains a value =
of
> the assigned / emplaced type.=E2=80=9D But when assignment isn=E2=80=99t =
equivalent to
> destruction and reconstruction, this optimization isn=E2=80=99t valid. Fo=
r example:
>
> typedef std::vector< int, stateful_alloc< int > > val;
> typedef variant< al, T > var;
>
> If the user gives type al for template parameter T, then when this
> variant changes from its library-owned state <0> to the user-owned state
> <1>, it will unexpectedly start putting things in the wrong memory pool.
> This is what you get for combining separate concerns.
>
>
This is an interesting case. If you are ever changing the variant from
Foo$0 to Foo$1 (if you understand my syntax), I agree that it should
destroy and reconstruct. (But Foo$0 to Foo$0 should use assignment.)
Looking at the (latest?) doc (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4542.pdf)....
That paragraph suggests "optimizations" that I think are not allowed
(although it is a vague paragraph). Reading the proposed standard wording
however:
assignment of T:
variant<int, int> vii;
vii =3D 17;
IIUC, the above doesn't work. ie does not compile. It is ambiguous which
int you are assigning to. So we can't switch ints here.
assignment of variant:
vii =3D vii2;
The wording says that if the indices match, then it uses assignment
("get<j>(*this) =3D get<j>(rhs)"). That's correct to me.
If indices do not match, it specifically destroys and constructs. In the
Effects clause it doesn't actually state that it constructs into the right
index, but it does have index() =3D=3D rhs.index() as a post condition, so
clear enough.
vii =3D std::move(vii2);
Mostly same as above, uses =3D when indices match, else construction.
Missing a post-condition about index() =3D=3D rhs.index() though.
emplace:
emplace() (all forms) always destroys then constructs, never uses
assignment.
In fact, there appears to be no way to do something like assign by index.
That might be useful?
Tony
--=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/.
--001a11c377a2f6fe0005206dc9af
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div><div><div><div><div><br><div class=3D"gmail_extr=
a"><br><div class=3D"gmail_quote">On Wed, Sep 23, 2015 at 3:11 AM, David Kr=
auss <span dir=3D"ltr"><<a href=3D"mailto:potswa@gmail.com" target=3D"_b=
lank">potswa@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_=
quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,=
204);padding-left:1ex"><div style=3D"word-wrap:break-word"><div>Come to thi=
nk of it, duplicated types are a can of worms. According to the proposal, &=
quot;<font face=3D"Courier">variant</font>=C2=A0employs same-type optimizat=
ions, using the assignment operator=C2=A0instead of construction if the=C2=
=A0variant=C2=A0already contains a value of the assigned /=C2=A0emplaced ty=
pe.=E2=80=9D But when assignment isn=E2=80=99t equivalent to destruction an=
d reconstruction, this optimization isn=E2=80=99t valid. For example:</div>=
<div><br></div><div><font face=3D"Courier">typedef std::vector< int, sta=
teful_alloc< int > > val;</font></div><div><font face=3D"Courier">=
typedef variant< al, T > var;</font></div><div><br></div><div>If the =
user gives type <font face=3D"Courier">al</font> for template parameter <fo=
nt face=3D"Courier">T</font>, then when this variant changes from its libra=
ry-owned state <font face=3D"Courier"><0></font> to the user-owned st=
ate <font face=3D"Courier"><1></font>, it will unexpectedly start put=
ting things in the wrong memory pool. This is what you get for combining se=
parate concerns.</div><span class=3D""></span><br></div></blockquote></div>=
<br></div><div class=3D"gmail_extra">This is an interesting case.=C2=A0 If =
you are ever changing the variant from Foo$0 to Foo$1 (if you understand my=
syntax), I agree that it should destroy and reconstruct.=C2=A0 (But Foo$0 =
to Foo$0 should use assignment.)<br><br></div><div class=3D"gmail_extra">Lo=
oking at the (latest?) doc (<a href=3D"http://www.open-std.org/jtc1/sc22/wg=
21/docs/papers/2015/n4542.pdf)..">http://www.open-std.org/jtc1/sc22/wg21/do=
cs/papers/2015/n4542.pdf)..</a>..<br><br></div><div class=3D"gmail_extra">T=
hat paragraph suggests "optimizations" that I think are not allow=
ed (although it is a vague paragraph).=C2=A0 Reading the proposed standard =
wording however:<br><br><br></div><div class=3D"gmail_extra">assignment of =
T:<br><br></div>=C2=A0=C2=A0=C2=A0 variant<int, int> vii;<br></div>=
=C2=A0=C2=A0=C2=A0 vii =3D 17;<br><br></div>IIUC, the above doesn't wor=
k. ie does not compile.=C2=A0 It is ambiguous which int you are assigning t=
o. So we can't switch ints here.<br><br></div>assignment of variant:<br=
><br></div>=C2=A0=C2=A0=C2=A0 vii =3D vii2;<br><br></div>The wording says t=
hat if the indices match, then it uses assignment ("get<j>(*this=
) =3D get<j>(rhs)").=C2=A0 That's correct to me.<br></div>If=
indices do not match, it specifically destroys and constructs.=C2=A0 In th=
e Effects clause it doesn't actually state that it constructs into the =
right index, but it does have index() =3D=3D rhs.index() as a post conditio=
n, so clear enough.<br><div><div><div><div><div><div><div><br></div><div>=
=C2=A0=C2=A0=C2=A0 vii =3D std::move(vii2);<br><br></div><div>Mostly same a=
s above, uses =3D when indices match, else construction.=C2=A0 Missing a po=
st-condition about index() =3D=3D rhs.index() though.<br><br></div><div>emp=
lace:<br><br></div><div>emplace() (all forms) always destroys then construc=
ts, never uses assignment.<br><br></div><div>In fact, there appears to be n=
o way to do something like assign by index.=C2=A0 That might be useful?<br>=
<br></div><div>Tony<br></div></div></div></div></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c377a2f6fe0005206dc9af--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 23 Sep 2015 13:59:58 -0400
Raw View
--047d7b3a84c60282bf05206de263
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wed, Sep 23, 2015 at 8:28 AM, Larry Evans <cppljevans@suddenlink.net>
wrote:
> On 09/23/2015 02:11 AM, David Krauss wrote:
> >
> >> On 2015=E2=80=9309=E2=80=9323, at 11:44 AM, Nicol Bolas <jmckesson@gma=
il.com
> >> <mailto:jmckesson@gmail.com>> wrote:
> [snip]
> >> ... are you kidding? Just on visitation /alone/, I'd never use a
> >> `union` again.
> >
> > Note that visitation can=E2=80=99t tell duplicate members apart=E2=80=
=A6 Sorry, I meant
> > to ask for use-cases distinct from sum types.
> >
> It can if the visitor dispatches on the index instead of
> the type while holding the variant as a reference:
>
> template<std::size_t I>
> using index=3Dstd::integral_constant<std::size_t,I>;
>
> struct visitor
> {
> variant<T0,T1>& my_var;
> visitor(variant<T0,T1>& a_var)
> :my_var(a_var)
> {}
> void visit(index<0>)
> { //do something with get<0>(my_var)
> }
> void visit(index<1>)
> { //do something with get<1>(my_var)
> }
> };
>
>
I don't think the index<N> signature is enough to differentiate by-type
visitation from by-index visitation. Because some day I'll have (via
templates of course) a variant<index<1>, index<0>> class, and be really
sad.
The above is OK if visitation is initiated differently. ie
visit_by_index(visitor, var) instead of visit(visitor, var).
Alternatively, allow the visitor interface to take both index<N> and type,
ie
void visit(T0, index<0>) {}
void visit(T1, index<1>) {}
Tony
--=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/.
--047d7b3a84c60282bf05206de263
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Sep 23, 2015 at 8:28 AM, Larry Evans <span dir=3D"ltr"><<a h=
ref=3D"mailto:cppljevans@suddenlink.net" target=3D"_blank">cppljevans@sudde=
nlink.net</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span cl=
ass=3D"">On 09/23/2015 02:11 AM, David Krauss wrote:<br>
><br>
>> On 2015=E2=80=9309=E2=80=9323, at 11:44 AM, Nicol Bolas <<a hre=
f=3D"mailto:jmckesson@gmail.com">jmckesson@gmail.com</a><br>
</span>>> <mailto:<a href=3D"mailto:jmckesson@gmail.com">jmckesson=
@gmail.com</a>>> wrote:<br>
[snip]<br>
>> ... are you kidding? Just on visitation /alone/, I'd never use=
a<br>
<span class=3D"">>> `union` again.<br>
><br>
> Note that visitation can=E2=80=99t tell duplicate members apart=E2=80=
=A6 Sorry, I meant<br>
> to ask for use-cases distinct from sum types.<br>
><br>
</span>It can if the visitor dispatches on the index instead of<br>
the type while holding the variant as a reference:<br>
<br>
template<std::size_t I><br>
using index=3Dstd::integral_constant<std::size_t,I>;<br>
<br>
struct visitor<br>
{<br>
=C2=A0 =C2=A0 variant<T0,T1>& my_var;<br>
=C2=A0 =C2=A0 visitor(variant<T0,T1>& a_var)<br>
=C2=A0 =C2=A0 =C2=A0 :my_var(a_var)<br>
=C2=A0 =C2=A0 =C2=A0 {}<br>
=C2=A0 =C2=A0 void visit(index<0>)<br>
=C2=A0 =C2=A0 =C2=A0 { //do something with get<0>(my_var)<br>
=C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 void visit(index<1>)<br>
=C2=A0 =C2=A0 =C2=A0 { //do something with get<1>(my_var)<br>
=C2=A0 =C2=A0 =C2=A0 }<br>
};<br>
<div class=3D"HOEnZb"><div class=3D"h5"><br></div></div></blockquote><div><=
br></div><div>I don't think the index<N> signature is enough to d=
ifferentiate by-type visitation from by-index visitation.=C2=A0 Because som=
e day I'll have (via templates of course) a variant<index<1>, =
index<0>> class, and be really sad. <br><br></div><div>The above i=
s OK if visitation is initiated differently.=C2=A0 ie visit_by_index(visito=
r, var) instead of visit(visitor, var).<br></div><div>Alternatively, allow =
the visitor interface to take both index<N> and type, ie<br><br></div=
><div>=C2=A0=C2=A0=C2=A0 void visit(T0, index<0>) {}<br></div><div>=
=C2=A0=C2=A0=C2=A0 void visit(T1, index<1>) {}<br><br></div><div>Tony=
<br></div></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b3a84c60282bf05206de263--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 23 Sep 2015 11:08:58 -0700
Raw View
--047d7b33956d32f72605206e02c3
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wed, Sep 23, 2015 at 5:31 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
>
> union_<> is just a nice-to-have that isn't strictly necessary and would
>> be a C++ union type that is made via a variadic argument list (this
>> pretty much necessary for variant's implementation anyway if it is to be
>> constexpr-aware, so we may as well expose it if an interface can be
>> agreed upon). This is non-trivial to properly implement, so providing it
>> may be useful.
>>
>
> This would be almost useless, once you have a non-trivially-destructible
> member then `union_` would have a deleted destructor. You wouldn't be abl=
e
> to do much with it unless you are prepared to dynamically allocate it and
> then leak it.
Right, though only as useless as a raw union already :p. In other words,
this is just presented mostly for completeness, as it is as close as you
can get to simply having a union type that obeys all of the normal union
rules, only you can now form it via a variadic list of arguments and access
fields accordingly. As was mentioned, destructible_union is the one that is
more directly useful.
On Wed, Sep 23, 2015 at 5:31 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
> destructibe_union<> is similar to union_<> only it is guaranteed to be
>> destructible even if one of the members has a nontrivial destructor
>> (again, this is pretty much required for a proper, constexpr-aware
>> variant-like-type).
>>
>
> Which, I assume, is why you propose this too. This is an incomplete class
> with a broken invariant, whose sole purpose is to workaround rough areas =
in
> the language.
>
Yeah, it's generally an implementation detail, but one that I feel may be
worthy of being exposed, unless there is significant push back. A good
example of why it may be useful to expose is this discussion about variant
possibly not making optimal use of storage for a discriminator. By exposing
something like destructible_union, you make it more feasible for users to
implement their own variant/discriminated_union types that do something
like store the discriminator for a group of types separately in a bitfield,
packed tightly together. As long as the facilities for things like
visitation operate via a customization point (aka a concept that simply
exposes the notions of a "which" and a "get" and a list of field types),
this would be easy, as people could build on top of these lower-level
constructs.
Anyway, union_ and destructible_union aren't usually directly important, so
it's not a big deal, I just feel that they are nice to have since making
them is not immediately obvious, but still useful, and at least
destructible_union or an equivalent is effectively required internally in
order to implement a proper variant.
On Wed, Sep 23, 2015 at 5:31 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
> `union_<>` may come in handy if restricted to trivially-destructible type=
s
> only. `destructible_union<>` is not even half a type, I feel uneasy about
> this being anything other than a shameful implementation detail.
Yeah, calling it "useless" isn't quite fair to the type. It would be usable
in the same places that a raw union would be usable, only you can form the
field list by way of template arguments. That said, unions themselves
aren't often directly used in modern programs, especially if we have
something like variant or discriminated_union, but they are still useful
even then for certain problems.
Anyway, union_ and destructible_union again are just "nice-to-have," but if
desire for them isn't there, then it's not that important. I just feel they
are a good way to make raw unions more directly usable in modern C++
applications.
--=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/.
--047d7b33956d32f72605206e02c3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Sep 23, 2015 at 5:31 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <span dir=3D"l=
tr"><<a href=3D"mailto:kaballo86@hotmail.com" target=3D"_blank">kaballo8=
6@hotmail.com</a>></span> wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><span class=3D"">
<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;p=
adding-left:1ex">
union_<> is just a nice-to-have that isn't strictly necessary and=
would<br>
be a C++ union type that is made via a variadic argument list (this<br>
pretty much necessary for variant's implementation anyway if it is to b=
e<br>
constexpr-aware, so we may as well expose it if an interface can be<br>
agreed upon). This is non-trivial to properly implement, so providing it<br=
>
may be useful.<br>
</blockquote>
<br></span>
This would be almost useless, once you have a non-trivially-destructible me=
mber then `union_` would have a deleted destructor. You wouldn't be abl=
e to do much with it unless you are prepared to dynamically allocate it and=
then leak it.</blockquote><div><br></div><div>Right, though only as useles=
s as a raw union already :p. In other words, this is just presented mostly =
for completeness, as it is as close as you can get to simply having a union=
type that obeys all of the normal union rules, only you can now form it vi=
a a variadic list of arguments and access fields accordingly. As was mentio=
ned, destructible_union is the one that is more directly useful.</div><div>=
<br></div><div>On Wed, Sep 23, 2015 at 5:31 AM, Agust=C3=ADn K-ballo Berg=
=C3=A9=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:kaballo86@hotmail.com" =
target=3D"_blank">kaballo86@hotmail.com</a>></span>=C2=A0wrote:=C2=A0</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"><span class=3D"">
<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;p=
adding-left:1ex">
destructibe_union<> is similar to union_<> only it is guarantee=
d to be<br>
destructible even if one of the members has a nontrivial destructor<br>
(again, this is pretty much required for a proper, constexpr-aware<br>
variant-like-type).<br>
</blockquote>
<br></span>
Which, I assume, is why you propose this too. This is an incomplete class w=
ith a broken invariant, whose sole purpose is to workaround rough areas in =
the language.<br></blockquote><div><br></div><div>Yeah, it's generally =
an implementation detail, but one that I feel may be worthy of being expose=
d, unless there is significant push back. A good example of why it may be u=
seful to expose is this discussion about variant possibly not making optima=
l use of storage for a discriminator. By exposing something like destructib=
le_union, you make it more feasible for users to implement their own varian=
t/discriminated_union types that do something like store the discriminator =
for a group of types separately in a bitfield, packed tightly together. As =
long as the facilities for things like visitation operate via a customizati=
on point (aka a concept that simply exposes the notions of a "which&qu=
ot; and a "get" and a list of field types), this would be easy, a=
s people could build on top of these lower-level constructs.</div><div><br>=
</div><div>Anyway, union_ and destructible_union aren't usually directl=
y important, so it's not a big deal, I just feel that they are nice to =
have since making them is not immediately obvious, but still useful, and at=
least destructible_union or an equivalent is effectively required internal=
ly in order to implement a proper variant.</div><div><br></div><div><br></d=
iv><div>On Wed, Sep 23, 2015 at 5:31 AM, Agust=C3=ADn K-ballo Berg=C3=A9=C2=
=A0<span dir=3D"ltr"><<a href=3D"mailto:kaballo86@hotmail.com" target=3D=
"_blank">kaballo86@hotmail.com</a>></span>=C2=A0wrote:=C2=A0<br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex">
`union_<>` may come in handy if restricted to trivially-destructible =
types only. `destructible_union<>` is not even half a type, I feel un=
easy about this being anything other than a shameful implementation detail.=
</blockquote><div><br></div><div>Yeah, calling it "useless" isn&#=
39;t quite fair to the type. It would be usable in the same places that a r=
aw union would be usable, only you can form the field list by way of templa=
te arguments. That said, unions themselves aren't often directly used i=
n modern programs, especially if we have something like variant or discrimi=
nated_union, but they are still useful even then for certain problems.</div=
><div><br></div><div>Anyway, union_ and destructible_union again are just &=
quot;nice-to-have," but if desire for them isn't there, then it=
9;s not that important. I just feel they are a good way to make raw unions =
more directly usable in modern C++ applications.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b33956d32f72605206e02c3--
.
Author: Larry Evans <cppljevans@suddenlink.net>
Date: Wed, 23 Sep 2015 13:43:59 -0500
Raw View
On 09/23/2015 12:59 PM, Tony V E wrote:
>=20
>=20
> On Wed, Sep 23, 2015 at 8:28 AM, Larry Evans <cppljevans@suddenlink.net
> <mailto:cppljevans@suddenlink.net>> wrote:
>=20
> On 09/23/2015 02:11 AM, David Krauss wrote:
> >
> >> On 2015=E2=80=9309=E2=80=9323, at 11:44 AM, Nicol Bolas <jmckesson=
@gmail.com <mailto:jmckesson@gmail.com>
> >> <mailto:jmckesson@gmail.com <mailto:jmckesson@gmail.com>>> wrote:
> [snip]
> >> ... are you kidding? Just on visitation /alone/, I'd never use a
> >> `union` again.
> >
> > Note that visitation can=E2=80=99t tell duplicate members apart=E2=
=80=A6 Sorry, I meant
> > to ask for use-cases distinct from sum types.
> >
> It can if the visitor dispatches on the index instead of
> the type while holding the variant as a reference:
>=20
> template<std::size_t I>
> using index=3Dstd::integral_constant<std::size_t,I>;
>=20
> struct visitor
> {
> variant<T0,T1>& my_var;
> visitor(variant<T0,T1>& a_var)
> :my_var(a_var)
> {}
> void visit(index<0>)
> { //do something with get<0>(my_var)
> }
> void visit(index<1>)
> { //do something with get<1>(my_var)
> }
> };
>=20
>=20
> I don't think the index<N> signature is enough to differentiate by-type
> visitation from by-index visitation. Because some day I'll have (via
> templates of course) a variant<index<1>, index<0>> class, and be really
> sad.
>=20
> The above is OK if visitation is initiated differently. ie
> visit_by_index(visitor, var) instead of visit(visitor, var).
That's what I meant. Sorry for not explicitly stating this.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 23 Sep 2015 13:30:47 -0700
Raw View
--001a1134e2125dc7a505206ffdce
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 23, 2015 at 7:20 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese
> wrote:
>>
>> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> That was the feature as you suggested it, and that's the only way to
>>> turn it into a proper compiler error (rather than throwing an exception at
>>> runtime if you try to copy a variant that happens to hold a non-noexcept
>>> type). The `variant` becomes an immobile type if one of its members isn't
>>> noexcept moveable.
>>>
>>
>> No, only if one of its types has a move-constructor that is noexcept and
>> there is also no field that has a noexcept default constructor.
>>
>
> I missed that part.
>
> *However*, that doesn't change the fact that it's still unusable. Earlier
> in the thread, I posed a hypothetical: a failure in a `variant` copy that
> is caught and processing proceeds.
>
> How does later code determine if the `variant` is in the state it is in
> because of a failure or because the user deliberately set it to that state?
>
> The answer is you can't. And that's *bad*. A user who needs to recover
> from such failures* needs* to be able to tell the difference. It
> introduces very subtle bugs if the user doesn't do the right thing.
>
I don't understand what point you think you are making. You handle this in
exactly the same way that you always do for absolutely any operation that
fails when the basic guarantee is specified.This is absolutely no different
for variant. As soon as an operation that only meets the basic guarantee
fails, you cannot make any assumptions about the mutated operand(s) other
than that the invariants of the types are still met. You know that there
was a failure because the exception propagated and the operation never
successfully returned. It's not like the exception is swallowed, here. You
either do not handle the exception and it propagates further, or you handle
the exception while understanding that since the basic guarantee was
specified, you can't make assumptions about the object's exact state. It is
at this point that you get your program back into a reasonable state for
you to proceed. This is nothing new to variant. This is fundamental to
exception handling and the exception guarantees.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> And I don't even know what "make it optional" means; it can't mean to
>>> wrap it in an `optional`, since that class probably forwards the throwing
>>> behavior of the copy/move operations of T. Do you mean by making it a
>>> pointer-to-T of some kind?
>>>
>>
>> No, I really do simply mean optional<variant<T...>>, where one or more of
>> T has a move-constructor that can throw.
>>
>
> That changes nothing. If your T... list makes the `variant` type immobile,
> then the `optional` container will be *similarly* immobile.
>
Please reread my post. This is simply not true. Such an operation is
equivalent to an emplace operation. optional implementations such as
boost::optional don't currently define such an overload, but there is no
logical reason why they can't. Note that the initial object isn't fully
"immobile," it is just only move-constructible and not move-assignable.
If you are hung up on the fact that the move-assignment of the optional
would use the move constructor of T in this specific case, understand that
optional implementations already use the move-constructor in such cases
whenever optional<T> happens to be in the nullopt state. In other words:
//////////
optional<T> foo = nullopt;
foo = T(); // This logically "destroys" nullopt and calls move-construct of
T
foo = T(); // This calls move-assign because foo already holds a T (no need
to destroy)
//////////
Now, consider the case where in the above example, T is move-constructible
but not move-assignable:
//////////
optional<T> foo = nullopt;
foo = T(); // ERROR even though we wouldn't actually have to call
move-assign
foo = T(); // ERROR
//////////
If the former case, analyze what is different. When T is in the nullopt
state, we'd move-construct because no T is currently contained. Logically
this is fine because it's just a move regardless of whether it's a
move-assign or a move-construct. Whether explicit or not, we're expressing
equivalence here . If you acknowledge that (maybe you don't?) then you
should also be able to understand that an equivalent operation if foo
already had a T, would be to *destroy* the T and then move-construct. You'd
never do this when T is move-assignable because there is no reason as you
can just call T's move-assign operator directly. In the case that it is not
move-assignable, such as for the reasons that variant would not be
move-assignable (in the subset of cases where it would be impossible for
the variant to be move-assignable without weakening the type's invariants),
then you can equivalently destroy the existing object and move-construct
the variant, just like you'd do if the optional were logically holding a
nullopt. In the event that the move-construct fails by way of exception,
this is not a problem, because we can just leave the optional in the
nullopt state to restore optional's invariants. This is perfectly
acceptable and we have is an assignment operation that meets the basic
exception guarantee.
Note that all of what I've said is not only true of optional, but it is
also true of any sum type where there is logically a
noexcept-default-constructible field. In the optional case, this field is
nullopt, but even in the more general variant case this is true when such a
type exists as one of the fields. Optional is not particularly special here.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Wrapping an immobile type in `optional` does not make it mobile. Just like
> wrapping an immobile type in `std::pair` doesn't make it mobile.
>
I've explained the problem, its requirements, and why those requirements
are there thoroughly already. If you have something specific about that
description that you don't understand then point out exactly what you
disagree with. You can't just compare it to an unrelated type and assume
that your intuitions carry over. I do not argue that these requirements are
obvious -- they're not obvious, they're just true. To understand that you
have to analyze and really understand the problem we are dealing with. In
this instance, instead of understanding the problem, people are *changing*
the problem by weakening the invariants of the type. This is completely
unnecessary and only serves to complicate contracts and introduce more
questions during specification regarding this "invalid" state.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
Even if `optional` worked exactly as you think it does, why should users
> have to add the syntactic noise of `optional<variant<...>>`?
>
I don't "think" it works that way, it doesn't work *any* way because
optional is not in the standard yet. I only explain that this is what it
can (and IMHO should) do in this case, because it is both logically
sensible and also comes up in practice. Users do not have to do
optional<variant<T...>>. They only do optional<variant<T...>> when they
want/need to represent the equivalent of what you are getting from an
"invalid" state. Users that don't have this need do not make their type
optional and they do not have to add any fields, they just make a variant
of their types. This is better than always having an invalid state because
it simplifies the type and related contracts rather than forcing such an
unnecessary state on all users of variant. You lose no functionality. It
also means that in specification we don't even have to decide what to do
when you "visit" an invalid object, etc.. It's not UB, it doesn't expand
out some tag, it's simply not impossible to ever come up because the
variant type has no notion of such a state. It has the never-empty
guarantee just as boost has had since it was first introduced.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
These requirements don't come out of the blue. They are inherent in the
>> operation that you are implementing.
>>
>
> No, they are not. As evidenced by N4542, there are other solutions.
>
Those solutions "work" because they change the type and its invariants
rather than implementing a solution to the problem. They [effectively]
always turn variant<T...> into something like an optional sum type, flatten
the interface, and call the nullopt state "invalid". The suggested solution
here avoids ever having to weaken the type's invariants and yet has the
same benefits. What happens when the variant with an invalid state has an
assignment operation that fails? Assuming the underlying fields of the
left-hand-side and the right-hand-side were different, the variant is left
in this "invalid" state. Similarly, by my suggestion, what happens if the
optional<variant<T...>> assignment fails? Exactly the same thing happens
only we are in the nullopt state rather than some introduced "invalid"
state. A similar comparison exists if you instead added a field. They are
equivalent except for the fact that my suggestion keeps the variant type's
invariants strict.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> There is no reason for a user to *assume* that a variant that only
> contains throwing move types will be immobile.
>
They don't have to assume it or even understand it, it's simply what is
implementable when maintaining strict invariants. Users would know these
requirements because they are specified as a part of the type. Yes, it's
not obvious. I do not argue that it is obvious. I only argue both that it
is a true requirement for defining the operation when maintaining strict
invariants (namely the never-empty guarantee), and that weakening the
type's invariants is worth avoiding.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Copy-assignment of a sum type that has fields with move-constructors that
>> can through is a very different operation from the copy-assignment of a
>> struct.
>>
>
> ... why? To me as a user, that seems like very esoteric C++ knowledge.
>
Call it esoteric or non-obvious, or whatever you want. It's still
ultimately true and we shouldn't pretend that it is not true.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Why do I need to know about such deep elements of copying behavior just to
> use a type?
>
You don't. You only need to know the concept requirements of the associated
functions that you need to use. Again, these requirements aren't invented,
they are lifted from the implementation.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> I expect copying inside a variant to be functionally no different from
> copying inside a struct. And if it does work differently, I want that
> difference to be immediately apparent.
>
The fact is that they are fundamentally different, and that difference will
be apparent because you would get a compile error if a particular operation
on that type is used without the user having satisfied its requirements.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> An invalid state is a part of the interface. I can therefore look up what
> `is_valid` does and when the object becomes invalid. What you're suggesting
> is not something that is apparent to the user.
>
The same is true of my suggested requirements. It's not like these
functions wouldn't document their requirements, and if we ever get concepts
in the language, those requirements would even be more directly represented
right in code, and better in error messages.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese
> wrote:
>
>> They are completely different problems that have different requirements
>> and different solutions. Your intuitions do not carry over, and that's
>> unfortunate, but it is also reality. I understand that you personally don't
>> find that particular requirement very obvious, but again, one's intuitions
>> have no impact on what is actually true. Either yo represent those
>> requirements, or you weaken the invariants of the type by introducing an
>> invalid state, thereby complicating things further.
>>
>
> So, having an invalid state that is only used by people who need it is
> more complicated than having a type become immobile even though its
> contained types are mobile, just in an unusual way? That is less
> complicated?
>
By my suggestion (and boost), what are the possible states that
variant<T...> can be in? Any one of T. What are the preconditions of
apply_visitor? No explicit preconditions. If I write a function that
accepts a reference to a variant, do I know it is "valid?" Yes, because by
the very nature of the type it is impossible to be invalid.
By introducing an invalid state, what are the possible states that
variant<T...> can be in? Any one of T... or it could be invalid. What are
the preconditions of apply_visitor? variant must not be in the invalid
state. If I write a function that accepts a reference to a variant, do I
know it is "valid?" Not unless I specify that as a precondition, and in
practice I'd probably also assert that the variant is valid in the body of
the function.
So yeah, it is less complicated to reason about and work with the type when
it satisfies the never empty guarantee. Are the requirements for getting
certain operations non-obvious? Sure, but they are the necessary
requirements to keep the invariants of the type strict and to make the
contracts of functions that deal with the type simple. You can still get
all of the equivalent behavior of the "invalid" state, you just do so
without weakening the type's invariants.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> you arbitrarily decide that all other solutions are "unnecessarily
> complicating all or most contracts" or whatever.
>
I'm not "arbitrarily deciding it," the contracts are demonstrably more
complicated. See the examples above.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134e2125dc7a505206ffdce
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Sep 23, 2015 at 7:20 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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">On Wednesday, September 23, 2015 at 12:37:4=
6 AM UTC-4, Matt Calabrese wrote:<span class=3D""><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div>On Tue, Sep 22, 2015 at 8:16 =
PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmai=
l.com</a>></span>=C2=A0wrote:<br></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">That was the fea=
ture as you suggested it, and that's the only way to turn it into a pro=
per compiler error (rather than throwing an exception at runtime if you try=
to copy a variant that happens to hold a non-noexcept type). The `variant`=
becomes an immobile type if one of its members isn't noexcept moveable=
..<br></blockquote><div><br></div><div>No, only if one of its types has a mo=
ve-constructor that is noexcept and there is also no field that has a noexc=
ept default constructor.</div></div></div></div></blockquote></span><div><b=
r>I missed that part.<br><br><i>However</i>, that doesn't change the fa=
ct that it's still unusable. Earlier in the thread, I posed a hypotheti=
cal: a failure in a `variant` copy that is caught and processing proceeds.<=
br><br>How does later code determine if the `variant` is in the state it is=
in because of a failure or because the user deliberately set it to that st=
ate?</div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><div><br>The answer is you can'=
t. And that's <i>bad</i>. A user who needs to recover from such failure=
s<i> needs</i> to be able to tell the difference. It introduces very subtle=
bugs if the user doesn't do the right thing.<br></div></blockquote><di=
v><br></div><div><div>I don't understand what point you think you are m=
aking. You handle this in exactly the same way that you always do for absol=
utely any operation that fails when the basic guarantee is specified.This i=
s absolutely no different for variant. As soon as an operation that only me=
ets the basic guarantee fails, you cannot make any assumptions about the mu=
tated operand(s) other than that the invariants of the types are still met.=
You know that there was a failure because the exception propagated and the=
operation never successfully returned. It's not like the exception is =
swallowed, here. You either do not handle the exception and it propagates f=
urther, or you handle the exception while understanding that since the basi=
c guarantee was specified, you can't make assumptions about the object&=
#39;s exact state. It is at this point that you get your program back into =
a reasonable state for you to proceed. This is nothing new to variant. This=
is fundamental to exception handling and the exception guarantees.</div></=
div><div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><span class=3D""><bloc=
kquote 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;paddin=
g-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>On Tue, S=
ep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"no=
follow">jmck...@gmail.com</a>></span>=C2=A0wrote:<br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"> And I don't even know what "make it optional" means; it =
can't mean to wrap it in an `optional`, since that class probably forwa=
rds the throwing behavior of the copy/move operations of T. Do you mean by =
making it a pointer-to-T of some kind?<br></blockquote><div><br></div><div>=
No, I really do simply mean optional<variant<T...>>, where one =
or more of T has a move-constructor that can throw.</div></div></div></div>=
</blockquote></span><div><br>That changes nothing. If your T... list makes =
the `variant` type immobile, then the `optional` container will be <i>simil=
arly</i> immobile.</div></blockquote><div><br></div><div>Please reread my p=
ost. This is simply not true. Such an operation is equivalent to an emplace=
operation. optional implementations such as boost::optional don't curr=
ently define such an overload, but there is no logical reason why they can&=
#39;t. Note that the initial object isn't fully "immobile," i=
t is just only move-constructible and not move-assignable.</div><div><br></=
div><div>If you are hung up on the fact that the move-assignment of the opt=
ional would use the move constructor of T in this specific case, understand=
that optional implementations already use the move-constructor in such cas=
es whenever optional<T> happens to be in the nullopt state. In other =
words:</div><div><br></div><div>//////////</div><div>optional<T> foo =
=3D nullopt;</div><div>foo =3D T(); // This logically "destroys" =
nullopt and calls move-construct of T</div><div>foo =3D T(); // This calls =
move-assign because foo already holds a T (no need to destroy)</div><div>//=
////////</div><div><br></div><div>Now, consider the case where in the above=
example, T is move-constructible but not move-assignable:</div><div>//////=
////</div><div>optional<T> foo =3D nullopt;</div><div>foo =3D T(); //=
ERROR even though we wouldn't actually have to call move-assign</div>f=
oo =3D T(); // ERROR<div>//////////</div><div><br></div><div>If the former =
case, analyze what is different. When T is in the nullopt state, we'd m=
ove-construct because no T is currently contained. Logically this is fine b=
ecause it's just a move regardless of whether it's a move-assign or=
a move-construct. Whether explicit or not, we're expressing equivalenc=
e here . If you acknowledge that (maybe you don't?) then you should als=
o be able to understand that an equivalent operation if foo already had a T=
, would be to *destroy* the T and then move-construct. You'd never do t=
his when T is move-assignable because there is no reason as you can just ca=
ll T's move-assign operator directly. In the case that it is not move-a=
ssignable, such as for the reasons that variant would not be move-assignabl=
e (in the subset of cases where it would be impossible for the variant to b=
e move-assignable without weakening the type's invariants), then you ca=
n equivalently destroy the existing object and move-construct the variant, =
just like you'd do if the optional were logically holding a nullopt. In=
the event that the move-construct fails by way of exception, this is not a=
problem, because we can just leave the optional in the nullopt state to re=
store optional's invariants. This is perfectly acceptable and we have i=
s an assignment operation that meets the basic exception guarantee.</div><d=
iv><br></div><div>Note that all of what I've said is not only true of o=
ptional, but it is also true of any sum type where there is logically a noe=
xcept-default-constructible field. In the optional case, this field is null=
opt, but even in the more general variant case this is true when such a typ=
e exists as one of the fields. Optional is not particularly special here.</=
div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex">On Tue, Sep 22, 2015 at 8:16 PM, Nico=
l Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a=
>></span>=C2=A0wrote:<div>Wrapping an immobile type in `optional` does n=
ot make it mobile. Just like wrapping an immobile type in `std::pair` doesn=
't make it mobile.<br></div></blockquote><div><br></div><div>I've e=
xplained the problem, its requirements, and why those requirements are ther=
e thoroughly already. If you have something specific about that description=
that you don't understand then point out exactly what you disagree wit=
h. You can't just compare it to an unrelated type and assume that your =
intuitions carry over. I do not argue that these requirements are obvious -=
- they're not obvious, they're just true. To understand that you ha=
ve to analyze and really understand the problem we are dealing with. In thi=
s instance, instead of understanding the problem, people are <i>changing</i=
> the problem by weakening the invariants of the type. This is completely u=
nnecessary and only serves to complicate contracts and introduce more quest=
ions during specification regarding this "invalid" state.</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">On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bola=
s=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>><=
/span>=C2=A0wrote:</blockquote><blockquote class=3D"gmail_quote" style=3D"m=
argin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204=
,204);border-left-style:solid;padding-left:1ex"><div>Even if `optional` wor=
ked exactly as you think it does, why should users have to add the syntacti=
c noise of `optional<variant<...>>`?</div></blockquote><div><br=
></div><div>I don't "think" it works that way, it doesn't=
work *any* way because optional is not in the standard yet. I only explain=
that this is what it can (and IMHO should) do in this case, because it is =
both logically sensible and also comes up in practice. Users do not have to=
do optional<variant<T...>>. They only do optional<variant&l=
t;T...>> when they want/need to represent the equivalent of what you =
are getting from an "invalid" state. Users that don't have th=
is need do not make their type optional and they do not have to add any fie=
lds, they just make a variant of their types. This is better than always ha=
ving an invalid state because it simplifies the type and related contracts =
rather than forcing such an unnecessary state on all users of variant. You =
lose no functionality. It also means that in specification we don't eve=
n have to decide what to do when you "visit" an invalid object, e=
tc.. It's not UB, it doesn't expand out some tag, it's simply n=
ot impossible to ever come up because the variant type has no notion of suc=
h a state. It has the never-empty guarantee just as boost has had since it =
was first introduced.</div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On Tue, Sep 22=
, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollo=
w">jmck...@gmail.com</a>></span>=C2=A0wrote:</blockquote><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
"><span class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 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><div class=3D"gma=
il_quote"><div>These requirements don't come out of the blue. They are =
inherent in the operation that you are implementing.</div></div></div></div=
></blockquote></span><div><br>No, they are not. As evidenced by N4542, ther=
e are other solutions.<br></div></blockquote><div><br></div><div>Those solu=
tions "work" because they change the type and its invariants rath=
er than implementing a solution to the problem. They [effectively] always t=
urn variant<T...> into something like an optional sum type, flatten t=
he interface, and call the nullopt state "invalid". The suggested=
solution here avoids ever having to weaken the type's invariants and y=
et has the same benefits. What happens when the variant with an invalid sta=
te has an assignment operation that fails? Assuming the underlying fields o=
f the left-hand-side and the right-hand-side were different, the variant is=
left in this "invalid" state. Similarly, by my suggestion, what =
happens if the optional<variant<T...>> assignment fails? Exactl=
y the same thing happens only we are in the nullopt state rather than some =
introduced "invalid" state. A similar comparison exists if you in=
stead added a field. They are equivalent except for the fact that my sugges=
tion keeps the variant type's invariants strict.</div><div><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex">On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=
=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0wrot=
e:<div>There is no reason for a user to <i>assume</i> that a variant that o=
nly contains throwing move types will be immobile.</div></blockquote><div><=
br></div><div>They don't have to assume it or even understand it, it=
9;s simply what is implementable when maintaining strict invariants. Users =
would know these requirements because they are specified as a part of the t=
ype. Yes, it's not obvious. I do not argue that it is obvious. I only a=
rgue both that it is a true requirement for defining the operation when mai=
ntaining strict invariants (namely the never-empty guarantee), and that wea=
kening the type's invariants is worth avoiding.</div><div>=C2=A0</div><=
div><br></div><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span =
dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0w=
rote:</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-st=
yle:solid;padding-left:1ex"><span class=3D""><blockquote class=3D"gmail_quo=
te" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-col=
or:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"l=
tr"><div><div class=3D"gmail_quote"><div>Copy-assignment of a sum type that=
has fields with move-constructors that can through is a very different ope=
ration from the copy-assignment of a struct.</div></div></div></div></block=
quote></span><div><br>... why? To me as a user, that seems like very esoter=
ic C++ knowledge.</div></blockquote><div><br></div><div>Call it esoteric or=
non-obvious, or whatever you want. It's still ultimately true and we s=
houldn't pretend that it is not true.</div><div><br></div><div>On Tue, =
Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"n=
ofollow">jmck...@gmail.com</a>></span>=C2=A0wrote:<br></div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex"><div> Why do I need to know about such deep elements of copying behavi=
or just to use a type?<br></div></blockquote><div><br></div><div>You don=
9;t. You only need to know the concept requirements of the associated funct=
ions that you need to use. Again, these requirements aren't invented, t=
hey are lifted from the implementation.</div><div><br></div><div>=C2=A0On T=
ue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=
=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0wrote:</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"><div>I expect copying inside a variant to be functionally no differen=
t from copying inside a struct. And if it does work differently, I want tha=
t difference to be immediately apparent.<br></div></blockquote><div><br></d=
iv><div>The fact is that they are fundamentally different, and that differe=
nce will be apparent because you would get a compile error if a particular =
operation on that type is used without the user having satisfied its requir=
ements.</div><div><br></div><div>=C2=A0On Tue, Sep 22, 2015 at 8:16 PM, Nic=
ol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</=
a>></span>=C2=A0wrote:<br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div>An invalid state =
is a part of the interface. I can therefore look up what `is_valid` does an=
d when the object becomes invalid. What you're suggesting is not someth=
ing that is apparent to the user.<br></div></blockquote><div><br></div><div=
>The same is true of my suggested requirements. It's not like these fun=
ctions wouldn't document their requirements, and if we ever get concept=
s in the language, those requirements would even be more directly represent=
ed right in code, and better in error messages.</div><div><br></div><div>=
=C2=A0On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr">&=
lt;<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0wrote:</div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex"><div>On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, =
Matt Calabrese wrote:<br></div><span class=3D""><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><div class=3D"gmail_quote"><div>They are completely different=
problems that have different requirements and different solutions. Your in=
tuitions do not carry over, and that's unfortunate, but it is also real=
ity. I understand that you personally don't find that particular requir=
ement very obvious, but again, one's intuitions have no impact on what =
is actually true. Either yo represent those requirements, or you weaken the=
invariants of the type by introducing an invalid state, thereby complicati=
ng things further.</div></div></div></div></blockquote></span><div><br>So, =
having an invalid state that is only used by people who need it is more com=
plicated than having a type become immobile even though its contained types=
are mobile, just in an unusual way? That is less complicated?<br></div></b=
lockquote><div><br></div><div>By my suggestion (and boost), what are the po=
ssible states that variant<T...> can be in? Any one of T. What are th=
e preconditions of apply_visitor? No explicit preconditions. If I write a f=
unction that accepts a reference to a variant, do I know it is "valid?=
" Yes, because by the very nature of the type it is impossible to be i=
nvalid.</div><div><br></div><div>By introducing an invalid state, what are =
the possible states that variant<T...> can be in? Any one of T... or =
it could be invalid. What are the preconditions of apply_visitor? variant m=
ust not be in the invalid state. If I write a function that accepts a refer=
ence to a variant, do I know it is "valid?" Not unless I specify =
that as a precondition, and in practice I'd probably also assert that t=
he variant is valid in the body of the function.</div><div><br></div><div>S=
o yeah, it is less complicated to reason about and work with the type when =
it satisfies the never empty guarantee. Are the requirements for getting ce=
rtain operations non-obvious? Sure, but they are the necessary requirements=
to keep the invariants of the type strict and to make the contracts of fun=
ctions that deal with the type simple. You can still get all of the equival=
ent behavior of the "invalid" state, you just do so without weake=
ning the type's invariants.</div><div><br></div><div>On Tue, Sep 22, 20=
15 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">j=
mck...@gmail.com</a>></span>=C2=A0wrote:</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"><div>you =
arbitrarily decide that all other solutions are "unnecessarily complic=
ating all or most contracts" or whatever.<br></div></blockquote><div><=
br></div><div>I'm not "arbitrarily deciding it," the contract=
s are demonstrably more complicated. See the examples above.</div></div></d=
iv></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--001a1134e2125dc7a505206ffdce--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 23 Sep 2015 14:01:26 -0700
Raw View
--089e015370f6fa8f000520706ab5
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 23, 2015 at 8:00 AM, Tony V E <tvaneerd@gmail.com> wrote:
> Most functions with basic guarantees can be "upgraded" via assignment or
> non-throwing swap - ie assign back a copy of the old value. But for
> variant, assignment is the function in question, so there is no easy way to
> implement strong on top of basic.
>
This is true regardless of there being an invalid state or not. I'm not
implying that you are conflating them, I just want to make this clear so
that if people disagree with one point the issues remain orthogonal.
They've been conflated before.
Assuming you really do need to get back the old value, which isn't even
always required when handling an exception depending on your situation, you
can do this via indirection in at least a couple of ways. First, you can
store the offending fields that have move constructors that are not
noexcept by way of a unique_ptr (as explained, this doesn't even
necessarily imply dynamic memory allocation, though in practice this likely
isn't an issue anyway, since your type that has a move-constructor that can
throw likely is that way because it is itself doing some kind of dynamic
memory allocation). Alternatively, you do the equivalent of the double
storage option but at a higher level rather than the variant type
implicitly doing it whenever it would need to in order to make assignment
meet the strong guarantee (I.E. when one of the fields has a
move-constructor that is not noexcept).
Another way to phrase this last point is that while you can build the
equivalent of a variant type that uses the double storage option by way of
a thinner variant as a building block, if you instead start with a variant
that forces double storage, there is no way to get rid of that storage when
you do not need it. If you don't need it and the cost is also too much,
either because of overall memory usage or because arrays of such
types/things that contain such types are less cache friendly, then you'd
have to implement your own variant type more from scratch.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e015370f6fa8f000520706ab5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Sep 23, 2015 at 8:00 AM, Tony V E <span dir=3D"ltr"><<a href=3D"mail=
to:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gma=
il_extra"><div class=3D"gmail_quote"><div>Most functions with basic guarant=
ees can be "upgraded" via assignment or non-throwing swap - ie as=
sign back a copy of the old value.=C2=A0 But for variant, assignment is the=
function in question, so there is no easy way to implement strong on top o=
f basic.<br></div></div></div></div></blockquote><div><br></div><div>This i=
s true regardless of there being an invalid state or not. I'm not imply=
ing that you are conflating them, I just want to make this clear so that if=
people disagree with one point the issues remain orthogonal. They've b=
een conflated before.</div><div><br></div><div>Assuming you really do need =
to get back the old value, which isn't even always required when handli=
ng an exception depending on your situation, you can do this via indirectio=
n in at least a couple of ways. First, you can store the offending fields t=
hat have move constructors that are not noexcept by way of a unique_ptr (as=
explained, this doesn't even necessarily imply dynamic memory allocati=
on, though in practice this likely isn't an issue anyway, since your ty=
pe that has a move-constructor that can throw likely is that way because it=
is itself doing some kind of dynamic memory allocation). Alternatively, yo=
u do the equivalent of the double storage option but at a higher level rath=
er than the variant type implicitly doing it whenever it would need to in o=
rder to make assignment meet the strong guarantee (I.E. when one of the fie=
lds has a move-constructor that is not noexcept).</div><div><br></div><div>=
Another way to phrase this last point is that while you can build the equiv=
alent of a variant type that uses the double storage option by way of a thi=
nner variant as a building block, if you instead start with a variant that =
forces double storage, there is no way to get rid of that storage when you =
do not need it. If you don't need it and the cost is also too much, eit=
her because of overall memory usage or because arrays of such types/things =
that contain such types are less cache friendly, then you'd have to imp=
lement your own variant type more from scratch.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e015370f6fa8f000520706ab5--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 23 Sep 2015 14:55:07 -0700
Raw View
--001a11c2e462fa5f6b0520712ac7
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 23, 2015 at 2:01 PM, Matt Calabrese <calabrese@google.com>
wrote:
>
> Another way to phrase this last point is that while you can build the
> equivalent of a variant type that uses the double storage option by way of
> a thinner variant as a building block, if you instead start with a variant
> that forces double storage, there is no way to get rid of that storage when
> you do not need it. If you don't need it and the cost is also too much,
> either because of overall memory usage or because arrays of such
> types/things that contain such types are less cache friendly, then you'd
> have to implement your own variant type more from scratch.
>
I forgot one last point, but one that's not feasible in current C++, though
may be useful in understanding the problem and also in the future if/when
it become feasible.
If we ever get destructive moves in the language, as has been suggested by
various parties including myself, many of these issues that we have talked
about will go away in practice. The reason is because the rationale for why
a given move-constructor may throw often is because the source object of
the move needs to be left in a valid state that does not violate the
invariants of the type (you need to do this because the right hand operand
isn't destroyed... unless you weaken the type's invariants to include an
"invalid" state ;) ). The underlying problem is that sometimes, maintaining
the invariants would require performing dynamic memory allocation. Because
of this, types that currently have move constructors that can throw often
would not have destructive moves that would throw as there are no
invariants to maintain in source of the move as it is undergoing
destruction. Depending on if/how destructive moves progress, it's even been
suggested that destructive moves are strictly required to be noexcept, and
this is not generally unreasonable, even for types that currently have
throwing move constructors.
The implication of all of this is that if our field types are noexcept
destructive movable (regardless of whether or not they are noexcept
move-constructible), then even if the variant, itself, is not undergoing a
destructive move, we are able to implement the strong exception guarantee
for all of our move assignments without needing something like double
storage. Similarly, we can always then implement the strong exception
guarantee for our copy assignments. If we happen to also have a field that
is noexcept-default-constructible, we could even go so far as to make the
move-assignment operator have a nothrow guarantee (though I personally
think this wouldn't be necessary). Further, in the case that the operands
of the assignment are undergoing a destructive move from right-hand-side to
left-hand-side (again, assuming noexcept destructive move), then we very
directly get our overall operation to be noexcept.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2e462fa5f6b0520712ac7
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Sep 23, 2015 at 2:01 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> wrote:<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 clas=
s=3D"gmail_extra"><div class=3D"gmail_quote"><div>Another way to phrase thi=
s last point is that while you can build the equivalent of a variant type t=
hat uses the double storage option by way of a thinner variant as a buildin=
g block, if you instead start with a variant that forces double storage, th=
ere is no way to get rid of that storage when you do not need it. If you do=
n't need it and the cost is also too much, either because of overall me=
mory usage or because arrays of such types/things that contain such types a=
re less cache friendly, then you'd have to implement your own variant t=
ype more from scratch.</div></div></div></div>
</blockquote></div><br></div><div class=3D"gmail_extra">I forgot one last p=
oint, but one that's not feasible in current C++, though may be useful =
in understanding the problem and also in the future if/when it become feasi=
ble.</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">I=
f we ever get destructive moves in the language, as has been suggested by v=
arious parties including myself, many of these issues that we have talked a=
bout will go away in practice. The reason is because the rationale for why =
a given move-constructor may throw often is because the source object of th=
e move needs to be left in a valid state that does not violate the invarian=
ts of the type (you need to do this because the right hand operand isn'=
t destroyed... unless you weaken the type's invariants to include an &q=
uot;invalid" state ;) ). The underlying problem is that sometimes, mai=
ntaining the invariants would require performing dynamic memory allocation.=
Because of this, types that currently have move constructors that can thro=
w often would not have destructive moves that would throw as there are no i=
nvariants to maintain in source of the move as it is undergoing destruction=
.. Depending on if/how destructive moves progress, it's even been sugges=
ted that destructive moves are strictly required to be noexcept, and this i=
s not generally unreasonable, even for types that currently have throwing m=
ove constructors.</div><div class=3D"gmail_extra"><br></div><div class=3D"g=
mail_extra">The implication of all of this is that if our field types are n=
oexcept destructive movable (regardless of whether or not they are noexcept=
move-constructible), then even if the variant, itself, is not undergoing a=
destructive move, we are able to implement the strong exception guarantee =
for all of our move assignments without needing something like double stora=
ge. Similarly, we can always then implement the strong exception guarantee =
for our copy assignments. If we happen to also have a field that is noexcep=
t-default-constructible, we could even go so far as to make the move-assign=
ment operator have a nothrow guarantee (though I personally think this woul=
dn't be necessary). Further, in the case that the operands of the assig=
nment are undergoing a destructive move from right-hand-side to left-hand-s=
ide (again, assuming noexcept destructive move), then we very directly get =
our overall operation to be noexcept.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2e462fa5f6b0520712ac7--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Wed, 23 Sep 2015 23:06:46 +0100
Raw View
On 23/09/15 05:03, Nevin Liber wrote:
> Oh, and don't forget it is a pessimization to do
> construct-then-noexcept-move instead of just construct when the variant
> is changing types, so you are penalizing all users. Of course, double
> buffering is also a pessimization in terms of cache as well as memory usage.
>
> Tradeoffs are hard.
Yes, tradeoffs are hard.
I've done some work on my variant implementation on bitbucket
(https://bitbucket.org/anthonyw/variant) to add the strong guarantee.
It does this in a variety of ways, in order to minimize space.
1. If the type you are constructing has a nothrow constructor you are
trying to use, destroy old value then construct directly
2. If the type you are constructing has a nothrow move constructor, and
it is not double-buffered (see below) then construct locally and then
destroy old value, and move-construct into the variant.
3. If all the other types have a nothrow move constructor and this type
is not double-buffered (see below) then move-construct the old value
into a local buffer, construct the new value in place, then destroy the
local buffer. On exception, move the old value back.
4. If at least 2 types are not nothrow-move-constructible then we need a
double-buffer. The size of the buffer is set to big enough to cover all
the types that are not nothrow-move-constructible. However, all types
that fit are then counted as double-buffered. This avoids extra move
constructions where possible, without imposing a space penalty beyond
what is required.
I think this is a reasonable trade-off. YMMV.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 23 Sep 2015 17:54:47 -0700 (PDT)
Raw View
------=_Part_51_1567978941.1443056087489
Content-Type: multipart/alternative;
boundary="----=_Part_52_1174617514.1443056087490"
------=_Part_52_1174617514.1443056087490
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 23, 2015 at 4:30:49 PM UTC-4, Matt Calabrese wrote:
>
> On Wed, Sep 23, 2015 at 7:20 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese
>> wrote:
>>>
>>> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> That was the feature as you suggested it, and that's the only way to
>>>> turn it into a proper compiler error (rather than throwing an exception at
>>>> runtime if you try to copy a variant that happens to hold a non-noexcept
>>>> type). The `variant` becomes an immobile type if one of its members isn't
>>>> noexcept moveable.
>>>>
>>>
>>> No, only if one of its types has a move-constructor that is noexcept and
>>> there is also no field that has a noexcept default constructor.
>>>
>>
>> I missed that part.
>>
>> *However*, that doesn't change the fact that it's still unusable.
>> Earlier in the thread, I posed a hypothetical: a failure in a `variant`
>> copy that is caught and processing proceeds.
>>
>> How does later code determine if the `variant` is in the state it is in
>> because of a failure or because the user deliberately set it to that state?
>>
>
>> The answer is you can't. And that's *bad*. A user who needs to recover
>> from such failures* needs* to be able to tell the difference. It
>> introduces very subtle bugs if the user doesn't do the right thing.
>>
>
> I don't understand what point you think you are making. You handle this in
> exactly the same way that you always do for absolutely any operation that
> fails when the basic guarantee is specified.
>
But my types might offer a strong exception guarantee. If all the types I
put into a variant offer the strong guarantee, it is perfectly reasonable
for the `variant` of them to offer it also. Yet sticking it in your kind of
`variant` breaks that guarantee.
That's bad.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> And I don't even know what "make it optional" means; it can't mean to
>>>> wrap it in an `optional`, since that class probably forwards the throwing
>>>> behavior of the copy/move operations of T. Do you mean by making it a
>>>> pointer-to-T of some kind?
>>>>
>>>
>>> No, I really do simply mean optional<variant<T...>>, where one or more
>>> of T has a move-constructor that can throw.
>>>
>>
>> That changes nothing. If your T... list makes the `variant` type
>> immobile, then the `optional` container will be *similarly* immobile.
>>
>
> Please reread my post. This is simply not true. Such an operation is
> equivalent to an emplace operation. optional implementations such as
> boost::optional don't currently define such an overload, but there is no
> logical reason why they can't.
>
You mean, besides the fact that a wrapper type fabricating an operation
that is illegal on the contents makes no sense? You are basically saying
that, if T is not move assignable, `optional<T>`, which is a
value-type-wrapper for T, should *create* a move assignment operator where
possible.
That's *completely insane*.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>
> Even if `optional` worked exactly as you think it does, why should users
>> have to add the syntactic noise of `optional<variant<...>>`?
>>
>
> I don't "think" it works that way, it doesn't work *any* way because
> optional is not in the standard yet.
>
The committee begs to differ
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4480.html#optional>.
That may not be in C++17 as a language/library, but it's still a C++
standard.
I only explain that this is what it can (and IMHO should) do in this case,
> because it is both logically sensible and also comes up in practice. Users
> do not have to do optional<variant<T...>>. They only do
> optional<variant<T...>> when they want/need to represent the equivalent of
> what you are getting from an "invalid" state.
>
Which would be *any time* they are using throwing move types in a
`variant`, since they need to be able to distinguish between an error and a
deliberate setting.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>> There is no reason for a user to *assume* that a variant that only
>> contains throwing move types will be immobile.
>>
>
> They don't have to assume it or even understand it, it's simply what is
> implementable when maintaining strict invariants.
>
If it forces your interface to be incredibly unintuitive and difficult to
use, then maybe "maintaining strict invariants" isn't worth doing.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>
>> Copy-assignment of a sum type that has fields with move-constructors that
>>> can through is a very different operation from the copy-assignment of a
>>> struct.
>>>
>>
>> ... why? To me as a user, that seems like very esoteric C++ knowledge.
>>
>
> Call it esoteric or non-obvious, or whatever you want. It's still
> ultimately true and we shouldn't pretend that it is not true.
>
A sign of a good abstraction is that it insulates you from details you
don't need to know as much as it possibly can.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>
>> On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese
>> wrote:
>>
>>> They are completely different problems that have different requirements
>>> and different solutions. Your intuitions do not carry over, and that's
>>> unfortunate, but it is also reality. I understand that you personally don't
>>> find that particular requirement very obvious, but again, one's intuitions
>>> have no impact on what is actually true. Either yo represent those
>>> requirements, or you weaken the invariants of the type by introducing an
>>> invalid state, thereby complicating things further.
>>>
>>
>> So, having an invalid state that is only used by people who need it is
>> more complicated than having a type become immobile even though its
>> contained types are mobile, just in an unusual way? That is less
>> complicated?
>>
>
> By my suggestion (and boost), what are the possible states that
> variant<T...> can be in? Any one of T. What are the preconditions of
> apply_visitor? No explicit preconditions. If I write a function that
> accepts a reference to a variant, do I know it is "valid?" Yes, because by
> the very nature of the type it is impossible to be invalid.
>
> By introducing an invalid state, what are the possible states that
> variant<T...> can be in? Any one of T... or it could be invalid. What are
> the preconditions of apply_visitor? variant must not be in the invalid
> state. If I write a function that accepts a reference to a variant, do I
> know it is "valid?" Not unless I specify that as a precondition, and in
> practice I'd probably also assert that the variant is valid in the body of
> the function.
>
> So yeah, it is less complicated to reason about and work with the type
> when it satisfies the never empty guarantee. Are the requirements for
> getting certain operations non-obvious? Sure, but they are the necessary
> requirements to keep the invariants of the type strict and to make the
> contracts of functions that deal with the type simple. You can still get
> all of the equivalent behavior of the "invalid" state, you just do so
> without weakening the type's invariants.
>
This is the most important thing. Because, while I did in fact
misunderstand a number of elements of your idea, it turns out that you've
misunderstood a number of elements of N4542, as evidenced by these
paragraphs.
The thing you don't understand about N4542 is this: you are not being
forced to use the invalid state.
Under N4542, `variant` becomes invalid if, *and only if*, a copy/move
fails. Which means, if you use types where copy/move *cannot fail*... your
`variant`s will always be valid.
`variant<int, float>` will always be valid. As will `variant<std::string,
std::vector<T>>`. As will `variant`s of most C++ standard library types.
So in both your idea and N4542, users who don't use throwing move types in
`variant` will get the "never-empty guarantee". And in both ideas, users
who use throwing move types *have to* deal with validity. So your claim of
"greater complexity" is simply wrong. In either case, the complexity is
exactly the same: users without throwing move are never empty, and users
with throwing moves have to deal with validity.
Since both ideas apply the same general solution to the problem (never
empty, never have copy/move overhead, users with failing types have to
check validity), the question now is how to impose that structure. Users
with throwing move types *must* deal with validity. So how do you do that?
Your way forces them to suffer through using `optional<variant<T...>>`.
Think about what their code will have to look like.
Every time they want to access the stored value, they have to call `get`.
Every time they want to apply a visitor, they have to call `get`. Again and
again and again. Even if they *know for a fact* that the variant is safe,
they *have to* call `get`.
Normally, if some function returns an `optional<T>`, you can check to see
if it's really there, then move it into an actual variable. But not your
way; you have to store it as an `optional`, so you have to constantly use
it as an optional. The best they can do is store a reference, but you don't
want to have references be members of types.
Not only that, your method *requires* changes to `optional`, changes that
are, charitably, dubious. If those changes don't pass the committee (and I
wouldn't hold my breath), then `variant` cannot effectively be used with
throwing move types.
N4542's way recognizes that the problem exists. So instead of passing it
off to some other type, it simply provides `variant` with the interface to
solve it, but *only* in that specific, narrow case.
And suddenly, everyone is happy. You get the never-empty guarantee for
types which can get that guarantee without overhead, and they get a type
that takes care of itself without having to impose a lot of API burden.
Why should we pick the option that hurts throwing move users more? Isn't
using throwing move types *enough* of a punishment ;)
Would it help satisfy your sensibilities about "complexity" if the
interface for N4542's `variant` actually SFINAE-removed the `is_valid`
member, if the typelist doesn't contain throwing move types?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_52_1174617514.1443056087490
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, September 23, 2015 at 4:30:49 PM UTC-4, Matt Calabrese wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div cla=
ss=3D"gmail_quote">On Wed, Sep 23, 2015 at 7:20 AM, Nicol Bolas <span dir=
=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailt=
o=3D"MW-JextxBgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On Wedn=
esday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese wrote:<span>=
<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;p=
adding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>On T=
ue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=
=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:<br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex">That was the feature as you suggested it, and that's the=
only way to turn it into a proper compiler error (rather than throwing an =
exception at runtime if you try to copy a variant that happens to hold a no=
n-noexcept type). The `variant` becomes an immobile type if one of its memb=
ers isn't noexcept moveable.<br></blockquote><div><br></div><div>No, on=
ly if one of its types has a move-constructor that is noexcept and there is=
also no field that has a noexcept default constructor.</div></div></div></=
div></blockquote></span><div><br>I missed that part.<br><br><i>However</i>,=
that doesn't change the fact that it's still unusable. Earlier in =
the thread, I posed a hypothetical: a failure in a `variant` copy that is c=
aught and processing proceeds.<br><br>How does later code determine if the =
`variant` is in the state it is in because of a failure or because the user=
deliberately set it to that state?</div></blockquote><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=
><br>The answer is you can't. And that's <i>bad</i>. A user who nee=
ds to recover from such failures<i> needs</i> to be able to tell the differ=
ence. It introduces very subtle bugs if the user doesn't do the right t=
hing.<br></div></blockquote><div><br></div><div><div>I don't understand=
what point you think you are making. You handle this in exactly the same w=
ay that you always do for absolutely any operation that fails when the basi=
c guarantee is specified.</div></div></div></div></div></blockquote><div><b=
r>But my types might offer a strong exception guarantee. If all the types I=
put into a variant offer the strong guarantee, it is perfectly reasonable =
for the `variant` of them to offer it also. Yet sticking it in your kind of=
`variant` breaks that guarantee.<br><br>That's bad.<br><br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D=
"gmail_quote"><div></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"><span><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><div class=3D"gmail_quote"><div>On Tue, Sep 22, 2015 at 8:16 =
PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmai=
l.com</a>></span>=C2=A0<wbr>wrote:<br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> And I don&=
#39;t even know what "make it optional" means; it can't mean =
to wrap it in an `optional`, since that class probably forwards the throwin=
g behavior of the copy/move operations of T. Do you mean by making it a poi=
nter-to-T of some kind?<br></blockquote><div><br></div><div>No, I really do=
simply mean optional<variant<T...>>, where one or more of T ha=
s a move-constructor that can throw.</div></div></div></div></blockquote></=
span><div><br>That changes nothing. If your T... list makes the `variant` t=
ype immobile, then the `optional` container will be <i>similarly</i> immobi=
le.</div></blockquote><div><br></div><div>Please reread my post. This is si=
mply not true. Such an operation is equivalent to an emplace operation. opt=
ional implementations such as boost::optional don't currently define su=
ch an overload, but there is no logical reason why they can't.</div></d=
iv></div></div></blockquote><div><br>You mean, besides the fact that a wrap=
per type fabricating an operation that is illegal on the contents makes no =
sense? You are basically saying that, if T is not move assignable, `optiona=
l<T>`, which is a value-type-wrapper for T, should <i>create</i> a mo=
ve assignment operator where possible.<br><br>That's <i>completely insa=
ne</i>.<br></div><br><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"><div><div class=3D"gmail_quote"><div></div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On Tue=
, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D=
"nofollow">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:</blockquote><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex"><div>Even if `optional` worked exactly as you think it does,=
why should users have to add the syntactic noise of `optional<variant&l=
t;...>>`?</div></blockquote><div><br></div><div>I don't "thi=
nk" it works that way, it doesn't work *any* way because optional =
is not in the standard yet.</div></div></div></div></blockquote><div><br><a=
href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4480.html=
#optional">The committee begs to differ</a>. That may not be in C++17 as a =
language/library, but it's still a C++ standard.<br><br></div><blockquo=
te 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><div class=3D"gma=
il_quote"><div> I only explain that this is what it can (and IMHO should) d=
o in this case, because it is both logically sensible and also comes up in =
practice. Users do not have to do optional<variant<T...>>. They=
only do optional<variant<T...>> when they want/need to represe=
nt the equivalent of what you are getting from an "invalid" state=
..</div></div></div></div></blockquote><div><br>Which would be <i>any time</=
i> they are using throwing move types in a `variant`, since they need to be=
able to distinguish between an error and a deliberate setting.<br><br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"><div></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex">On Tue, Sep 22, 2015 at 8:=
16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@g=
mail.com</a>></span>=C2=A0<wbr>wrote:<div>There is no reason for a user =
to <i>assume</i> that a variant that only contains throwing move types will=
be immobile.</div></blockquote><div><br></div><div>They don't have to =
assume it or even understand it, it's simply what is implementable when=
maintaining strict invariants.</div></div></div></div></blockquote><div><b=
r>If it forces your interface to be incredibly unintuitive and difficult to=
use, then maybe "maintaining strict invariants" isn't worth =
doing.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>On Tue, Sep 22, 20=
15 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">j=
mck...@gmail.com</a>></span>=C2=A0<wbr>wrote:</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"><spa=
n><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid=
;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>Co=
py-assignment of a sum type that has fields with move-constructors that can=
through is a very different operation from the copy-assignment of a struct=
..</div></div></div></div></blockquote></span><div><br>... why? To me as a u=
ser, that seems like very esoteric C++ knowledge.</div></blockquote><div><b=
r></div><div>Call it esoteric or non-obvious, or whatever you want. It'=
s still ultimately true and we shouldn't pretend that it is not true.</=
div></div></div></div></blockquote><div><br>A sign of a good abstraction is=
that it insulates you from details you don't need to know as much as i=
t possibly can.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div></div><di=
v>=C2=A0On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"=
><<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:<=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div>On Wednesday, September 23, 2015 at 12:37:46 AM =
UTC-4, Matt Calabrese wrote:<br></div><span><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote"><div>They are completely different probl=
ems that have different requirements and different solutions. Your intuitio=
ns do not carry over, and that's unfortunate, but it is also reality. I=
understand that you personally don't find that particular requirement =
very obvious, but again, one's intuitions have no impact on what is act=
ually true. Either yo represent those requirements, or you weaken the invar=
iants of the type by introducing an invalid state, thereby complicating thi=
ngs further.</div></div></div></div></blockquote></span><div><br>So, having=
an invalid state that is only used by people who need it is more complicat=
ed than having a type become immobile even though its contained types are m=
obile, just in an unusual way? That is less complicated?<br></div></blockqu=
ote><div><br></div><div>By my suggestion (and boost), what are the possible=
states that variant<T...> can be in? Any one of T. What are the prec=
onditions of apply_visitor? No explicit preconditions. If I write a functio=
n that accepts a reference to a variant, do I know it is "valid?"=
Yes, because by the very nature of the type it is impossible to be invalid=
..</div><div><br></div><div>By introducing an invalid state, what are the po=
ssible states that variant<T...> can be in? Any one of T... or it cou=
ld be invalid. What are the preconditions of apply_visitor? variant must no=
t be in the invalid state. If I write a function that accepts a reference t=
o a variant, do I know it is "valid?" Not unless I specify that a=
s a precondition, and in practice I'd probably also assert that the var=
iant is valid in the body of the function.</div><div><br></div><div>So yeah=
, it is less complicated to reason about and work with the type when it sat=
isfies the never empty guarantee. Are the requirements for getting certain =
operations non-obvious? Sure, but they are the necessary requirements to ke=
ep the invariants of the type strict and to make the contracts of functions=
that deal with the type simple. You can still get all of the equivalent be=
havior of the "invalid" state, you just do so without weakening t=
he type's invariants.</div></div></div></div></blockquote><div><br>This=
is the most important thing. Because, while I did in fact misunderstand a =
number of elements of your idea, it turns out that you've misunderstood=
a number of elements of N4542, as evidenced by these paragraphs.<br><br>Th=
e thing you don't understand about N4542 is this: you are not being for=
ced to use the invalid state.<br><br>Under N4542, `variant` becomes invalid=
if, <b><i>and only if</i></b>, a copy/move fails. Which means, if you use =
types where copy/move <i>cannot fail</i>... your `variant`s will always be =
valid.<br><br>`variant<int,
float>` will always be valid. As will `variant<std::string,=20
std::vector<T>>`. As will `variant`s of most C++ standard=20
library types.<br><br>So in both your idea and N4542, users who don't=
=20
use throwing move types in `variant` will get the "never-empty guarant=
ee". And in both ideas, users who use throwing move types <i>have to</=
i> deal with validity. So your claim of "greater complexity" is s=
imply wrong. In either case, the complexity is exactly the same: users with=
out throwing move are never empty, and users with throwing moves have to de=
al with validity.<br><br>Since both ideas apply the same general solution t=
o the problem (never empty, never have copy/move overhead, users with faili=
ng types have to check validity), the question now is how to impose that st=
ructure. Users with throwing move types <i>must</i> deal with validity. So =
how do you do that?<br><br>Your way forces them to suffer through using `op=
tional<variant<T...>>`. Think about what their code will have t=
o look like.<br><br>Every time they want to access the stored value, they h=
ave to call `get`. Every time they=20
want to apply a visitor, they have to call `get`. Again and again and=20
again. Even if they <i>know for a fact</i> that the variant is safe, they <=
i>have to</i> call `get`.<br><br>Normally,
if some function returns an `optional<T>`, you can check to see=20
if it's really there, then move it into an actual variable. But not you=
r
way; you have to store it as an `optional`, so you have to constantly=20
use it as an optional. The best they can do is store a reference, but you d=
on't want to have references be members of types.<br><br>Not only that,=
your method <i>requires</i> changes to `optional`, changes that are, chari=
tably, dubious. If those changes don't pass the committee (and I wouldn=
't hold my breath), then `variant` cannot effectively be used with thro=
wing move types.<br><br>N4542's way recognizes that the problem exists.=
So instead of passing it off to some other type, it simply provides `varia=
nt` with the interface to solve it, but <i>only</i> in that specific, narro=
w case.<br><br>And suddenly, everyone is happy. You get the never-empty gua=
rantee for types which can get that guarantee without overhead, and they ge=
t a type that takes care of itself without having to impose a lot of API bu=
rden.<br><br>Why should we pick the option that hurts throwing move users m=
ore? Isn't using throwing move types <i>enough</i> of a punishment ;)<b=
r><br>Would
it help satisfy your sensibilities about "complexity" if the int=
erface for N4542's=20
`variant` actually SFINAE-removed the `is_valid` member, if the typelist
doesn't contain throwing move types?</div>
<p></p>
-- <br />
<br />
--- <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 />
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_52_1174617514.1443056087490--
------=_Part_51_1567978941.1443056087489--
.
Author: Larry Evans <cppljevans@suddenlink.net>
Date: Wed, 23 Sep 2015 22:22:03 -0500
Raw View
This is a multi-part message in MIME format.
--------------010202080702040407030807
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On 09/23/2015 08:43 AM, Anthony Williams wrote:
> On 23/09/15 14:04, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
>>> Check out my implementation on bitbucket
>>> (https://bitbucket.org/anthonyw/variant). It uses raw storage and is
>>> constexpr aware.
[snip]
>> But I also see things that confuse me, like the use of placement new in
>> a function template flagged constexpr, which AFAIK will never be a
>> constexpr function.
[snip]
> It's possible there's some spurious constexpr keywords on templated
> functions where I forgot to remove them as I changed the implementation
> around, and the compiler didn't complain as you can always declare a
> templated function constexpr, even if it violates the rules.
>=20
> Anthony
>=20
Compiling the 1st attachment produces output in 2nd attachment,
which supports Agustin's confusion about constexpr :(
Larry
--=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/.
--------------010202080702040407030807
Content-Type: text/x-c++src;
name="variant.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="variant.cpp"
#include "variant"
struct member
{
member(int a)
: my_a(a)
{}
int my_a;
};
int main()
{
constexpr std::experimental::__storage_wrapper<member> wrap_mem(9);
return 0;
}
--------------010202080702040407030807
Content-Type: text/plain; charset=UTF-8;
name="variant.compilation"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="variant.compilation"
LSotIG1vZGU6IGNvbXBpbGF0aW9uOyBkZWZhdWx0LWRpcmVjdG9yeTogIn4vcHJvZ19kZXYv
Yml0YnVja2V0L2FudGhvbnl3L3ZhcmlhbnQvIiAtKi0KQ29tcGlsYXRpb24gc3RhcnRlZCBh
dCBXZWQgU2VwIDIzIDIyOjE3OjMwCgptYWtlIC1mIGxqZS5tayBydW4KaW5zdGFsbCAtZCBg
ZGlybmFtZSAvdG1wL2J1aWxkL2NsYW5neHgzXzdfcGtnL2JpdGJ1Y2tldC9hbnRob255dy92
YXJpYW50L3ZhcmlhbnQub2AKL2hvbWUvZXZhbnNsL2R3bmxkcy9sbHZtLzMuNy9wcmVidWls
dC9jbGFuZytsbHZtLTMuNy4wLXg4Nl82NC1saW51eC1nbnUtdWJ1bnR1LTE0LjA0L2Jpbi9j
bGFuZysrIC1jIC1PMCAtc3RkbGliPWxpYmMrKyAgLXN0ZD1jKysxNCAtZnRlbXBsYXRlLWJh
Y2t0cmFjZS1saW1pdD0wICAgIC1JL2hvbWUvZXZhbnNsL3Byb2dfZGV2L2Jvb3N0L3NhbmRi
b3gvcncvc2FuZGJveC9sZGlvbm5lL2hhbmEvaW5jbHVkZSAtSS9ob21lL2V2YW5zbC9wcm9n
X2Rldi9ib29zdC9zYW5kYm94L3J3L25vbl92YXJpYWRpY190ZW1wbGF0ZXMgLUkvaG9tZS9l
dmFuc2wvcHJvZ19kZXYvY2xhbmcvbGliY3h4L3NhbmRib3gvbGlicy9jb21wb3NpdGVfc3Rv
cmFnZS9pbmNsdWRlIC1JL2hvbWUvZXZhbnNsL3Byb2dfZGV2L2Jvb3N0L3NhbmRib3gvcncv
c2FuZGJveC9samUgLUkvaG9tZS9ldmFuc2wvcHJvZ19kZXYvYm9vc3QvYm9vc3QtcmVsZWFz
ZXMvcm8vYm9vc3RfMV81OV8wICAgIC1mdGVtcGxhdGUtZGVwdGg9MTAwICB2YXJpYW50LmNw
cCAtTU1EIC1vIC90bXAvYnVpbGQvY2xhbmd4eDNfN19wa2cvYml0YnVja2V0L2FudGhvbnl3
L3ZhcmlhbnQvdmFyaWFudC5vIAp2YXJpYW50LmNwcDoxMTo1ODogZXJyb3I6IGNvbnN0ZXhw
ciB2YXJpYWJsZSAnd3JhcF9tZW0nIG11c3QgYmUgaW5pdGlhbGl6ZWQgYnkgYSBjb25zdGFu
dCBleHByZXNzaW9uCiAgY29uc3RleHByIHN0ZDo6ZXhwZXJpbWVudGFsOjpfX3N0b3JhZ2Vf
d3JhcHBlcjxtZW1iZXI+IHdyYXBfbWVtKDkpOwogICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBefn5+fn5+fn5+fgouL3ZhcmlhbnQ6
Mjk4OjE2OiBub3RlOiBzdWJleHByZXNzaW9uIG5vdCB2YWxpZCBpbiBhIGNvbnN0YW50IGV4
cHJlc3Npb24KICAgICAgICByZXR1cm4gbmV3IChfX3ApIF9UeXBlKHN0ZDo6Zm9yd2FyZDxf
QXJncz4oX19hcmdzKS4uLiksZW1wdHlfdCgpOwogICAgICAgICAgICAgICBeCi4vdmFyaWFu
dDozMDM6MjI6IG5vdGU6IGluIGNhbGwgdG8gJ19fY29uc3RydWN0KCZ3cmFwX21lbS5fX3N0
b3JhZ2UsIDkpJwogICAgICAgIF9fZHVtbXlfYmFzZShfX2NvbnN0cnVjdCgmX19zdG9yYWdl
LHN0ZDo6Zm9yd2FyZDxfQXJncz4oX19hcmdzKS4uLikpe30KICAgICAgICAgICAgICAgICAg
ICAgXgp2YXJpYW50LmNwcDoxMTo1ODogbm90ZTogaW4gY2FsbCB0byAnX19zdG9yYWdlX3dy
YXBwZXIoOSknCiAgY29uc3RleHByIHN0ZDo6ZXhwZXJpbWVudGFsOjpfX3N0b3JhZ2Vfd3Jh
cHBlcjxtZW1iZXI+IHdyYXBfbWVtKDkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBeCjEgZXJyb3IgZ2VuZXJhdGVkLgptYWtl
OiAqKiogWy90bXAvYnVpbGQvY2xhbmd4eDNfN19wa2cvYml0YnVja2V0L2FudGhvbnl3L3Zh
cmlhbnQvdmFyaWFudC5vXSBFcnJvciAxCgpDb21waWxhdGlvbiBleGl0ZWQgYWJub3JtYWxs
eSB3aXRoIGNvZGUgMiBhdCBXZWQgU2VwIDIzIDIyOjE3OjMwCg==
--------------010202080702040407030807--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Thu, 24 Sep 2015 07:10:14 +0100
Raw View
--047d7b6d8068a56c470520781581
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On 24 Sep 2015 4:22 am, "Larry Evans" <cppljevans@suddenlink.net> wrote:
>
> On 09/23/2015 08:43 AM, Anthony Williams wrote:
> > On 23/09/15 14:04, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:
> >>> Check out my implementation on bitbucket
> >>> (https://bitbucket.org/anthonyw/variant). It uses raw storage and is
> >>> constexpr aware.
> [snip]
> >> But I also see things that confuse me, like the use of placement new i=
n
> >> a function template flagged constexpr, which AFAIK will never be a
> >> constexpr function.
> [snip]
> > It's possible there's some spurious constexpr keywords on templated
> > functions where I forgot to remove them as I changed the implementation
> > around, and the compiler didn't complain as you can always declare a
> > templated function constexpr, even if it violates the rules.
> >
> > Anthony
> >
> Compiling the 1st attachment produces output in 2nd attachment,
> which supports Agustin's confusion about constexpr :(
>
Storage_wrapper is what gets used for non-literal types. It may have
spurious constexpr keywords. If used in a non-constexpr context that's ok.
constexpr variant<int> v(9);
works, as does
variant<int,string> v("hello");
Anthony
--=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/.
--047d7b6d8068a56c470520781581
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<p dir=3D"ltr"><br>
On 24 Sep 2015 4:22 am, "Larry Evans" <<a href=3D"mailto:cpplj=
evans@suddenlink.net">cppljevans@suddenlink.net</a>> wrote:<br>
><br>
> On 09/23/2015 08:43 AM, Anthony Williams wrote:<br>
> > On 23/09/15 14:04, Agust=C3=ADn K-ballo Berg=C3=A9 wrote:<br>
> >>> Check out my implementation on bitbucket<br>
> >>> (<a href=3D"https://bitbucket.org/anthonyw/variant">https=
://bitbucket.org/anthonyw/variant</a>). It uses raw storage and is<br>
> >>> constexpr aware.<br>
> [snip]<br>
> >> But I also see things that confuse me, like the use of placem=
ent new in<br>
> >> a function template flagged constexpr, which AFAIK will never=
be a<br>
> >> constexpr function.<br>
> [snip]<br>
> > It's possible there's some spurious constexpr keywords on=
templated<br>
> > functions where I forgot to remove them as I changed the implemen=
tation<br>
> > around, and the compiler didn't complain as you can always de=
clare a<br>
> > templated function constexpr, even if it violates the rules.<br>
> ><br>
> > Anthony<br>
> ><br>
> Compiling the 1st attachment produces output in 2nd attachment,<br>
> which supports Agustin's confusion about constexpr :(<br>
></p>
<p dir=3D"ltr">Storage_wrapper is what gets used for non-literal types. It =
may have spurious constexpr keywords. If used in a non-constexpr context th=
at's ok.</p>
<p dir=3D"ltr">constexpr variant<int> v(9);</p>
<p dir=3D"ltr">works, as does</p>
<p dir=3D"ltr">variant<int,string> v("hello");</p>
<p dir=3D"ltr">Anthony</p>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--047d7b6d8068a56c470520781581--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 23 Sep 2015 23:10:31 -0700
Raw View
--001a1137bdd0a6ef7b052078169c
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 23, 2015 at 5:54 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> But my types might offer a strong exception guarantee. If all the types I
> put into a variant offer the strong guarantee, it is perfectly reasonable
> for the `variant` of them to offer it also. Yet sticking it in your kind of
> `variant` breaks that guarantee.
>
What? That's never been true, even for the struct/pair case that you refer
to. The strong guarantee does not compose in that case, either. Only the
nothrow guarantee composes in that manner for such a type with orthogonal
fields, just as it does for a variant, here. Separate from variant
entirely, it gets even worse for more general class types that have
higher-level invariants predicated on members. In this case, not only does
the strong guarantee not compose to produce something that satisfies the
strong guarantee, but here the direct composition can (and often does)
leave you with an assignment operation that wouldn't even meet the basic
guarantee, let alone the strong guarantee. This has always been the nature
of the exception guarantees. Yeah, it's unfortunate, but it's nothing
unique to variant.
On Wed, Sep 23, 2015 at 5:54 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> You mean, besides the fact that a wrapper type fabricating an operation
> that is illegal on the contents makes no sense? You are basically saying
> that, if T is not move assignable, `optional<T>`, which is a
> value-type-wrapper for T, should *create* a move assignment operator
> where possible.
>
> That's *completely insane*.
>
No, it's really not, and I've explained in detail why it is not, why it
works, and how it is implementable. Yeah, it's non-obvious, but it is
correct. Simply saying it's "insane" doesn't advance this conversation. If
there is something specific in the explanation that you disagree with, then
refer precisely to it and why you think it is in error. Calling the overall
idea "insane" doesn't help. Explain why it logically does not make sense,
along with an example case. Until then it is impossible to even debate the
topic because you are not saying anything to refute. You're essentially
just stating that it is not logical because you do not find it intuitive.
That is not a sufficient answer.
On Wed, Sep 23, 2015 at 5:54 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> The committee begs to differ
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4480.html#optional>.
> That may not be in C++17 as a language/library, but it's still a C++
> standard.
>
I am aware of the state of optional.
On Wed, Sep 23, 2015 at 5:54 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> If it forces your interface to be incredibly unintuitive and difficult to
> use
>
How exactly is it unintuitive or difficult to use an
optional<variant<T...>>, where the variant has the never-empty guarantee?
It has exactly the same interface as an optional because that is precisely
what it is, and the interface of a never-empty variant specifies fewer
operations than a variant with an "invalid" state, and the operations that
it does specify have simpler contracts. People don't have to learn how to
check for the invalid state or how the invalid state is dealt with for
things like visit() or which() because the variant simply cannot ever be in
such a state. You check for an "invalid" state by seeing if your optional
is nullopt, just like you would with any other optional instance. Again,
there are fewer functions total in the interface of the type, in addition
to the types themselves having stricter invariants and the associated
functions having simpler contracts. There are fewer operations and what is
there has simpler contracts, yet there is also no loss in overall
functionality. The only thing that is non-obvious about this is precisely
the requirements of the assignment operator of the underlying variant and
also the observation of the ability to implement the assignment operator of
optional in slightly more cases than is currently done, but users don't
have to immediately understand the reason behind such requirements, they
only have to know that the requirements are there. If you always want the
equivalent of an invalid state for whatever reason, just put it in an
optional, which is exactly what you'd do with any other type. Not everyone
creates variants with fields that have move constructors that can throw, so
the type shouldn't always suffer that penalty. Further, without much effort
in the implementation, not only is there no loss in functionality and
simpler contracts, but an optional<variant<T...>> can even be as
space-efficient as a variant with an invalid state since the discriminator
storage can be shared.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
> A sign of a good abstraction is that it insulates you from details you
> don't need to know as much as it possibly can.
>
You don't need to know anything about the internals of variant to use this.
You only need to know the requirements of the associated functions.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>
>> On Wednesday, September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese
>>> wrote:
>>>
>>>> They are completely different problems that have different requirements
>>>> and different solutions. Your intuitions do not carry over, and that's
>>>> unfortunate, but it is also reality. I understand that you personally don't
>>>> find that particular requirement very obvious, but again, one's intuitions
>>>> have no impact on what is actually true. Either yo represent those
>>>> requirements, or you weaken the invariants of the type by introducing an
>>>> invalid state, thereby complicating things further.
>>>>
>>>
>>> So, having an invalid state that is only used by people who need it is
>>> more complicated than having a type become immobile even though its
>>> contained types are mobile, just in an unusual way? That is less
>>> complicated?
>>>
>>
>> By my suggestion (and boost), what are the possible states that
>> variant<T...> can be in? Any one of T. What are the preconditions of
>> apply_visitor? No explicit preconditions. If I write a function that
>> accepts a reference to a variant, do I know it is "valid?" Yes, because by
>> the very nature of the type it is impossible to be invalid.
>>
>> By introducing an invalid state, what are the possible states that
>> variant<T...> can be in? Any one of T... or it could be invalid. What are
>> the preconditions of apply_visitor? variant must not be in the invalid
>> state. If I write a function that accepts a reference to a variant, do I
>> know it is "valid?" Not unless I specify that as a precondition, and in
>> practice I'd probably also assert that the variant is valid in the body of
>> the function.
>>
>> So yeah, it is less complicated to reason about and work with the type
>> when it satisfies the never empty guarantee. Are the requirements for
>> getting certain operations non-obvious? Sure, but they are the necessary
>> requirements to keep the invariants of the type strict and to make the
>> contracts of functions that deal with the type simple. You can still get
>> all of the equivalent behavior of the "invalid" state, you just do so
>> without weakening the type's invariants.
>>
>
> This is the most important thing. Because, while I did in fact
> misunderstand a number of elements of your idea, it turns out that you've
> misunderstood a number of elements of N4542, as evidenced by these
> paragraphs.
>
??? No I haven't.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Under N4542, `variant` becomes invalid if, *and only if*, a copy/move
> fails. Which means, if you use types where copy/move *cannot fail*...
> your `variant`s will always be valid.
>
That is not true even in N4542 as you can also get there via failed
emplacement, even if you're not dealing with types that have move
constructors that can throw (perhaps less obvious, you can get to invalid
even if all of your fields have no constructors that are noexcept(false) by
way of emplace -- and on that note, the specification of emplace in the
document is technically incorrect regarding exceptions, since it doesn't
cover exceptions stemming from argument conversions during emplacement).
Apart from that, in generic code (I.E. you are dealing with a dependent
variant<T...>), it is nontrivial to determine whether your type can or
cannot easily be in the invalid state anyway, not that it would matter
because whether easy or not, it can always possibly get there, regardless
of the field types.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> `variant<int, float>` will always be valid. As will `variant<std::string,
> std::vector<T>>`. As will `variant`s of most C++ standard library types.
> So in both your idea and N4542, users who don't use throwing move types in
> `variant` will get the "never-empty guarantee".
As described above, none of your assertions here are actually true. Any of
those types can end up in the invalid state in a valid program. There is no
never-empty guarantee for any set of field types in this proposal.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> And in both ideas, users who use throwing move types *have to* deal with
> validity. So your claim of "greater complexity" is simply wrong.
>
No, in my suggestion they only have to deal with "validity" when the user
is referring to an *optional* of the variant, just as is the case in
general with other types. For any functions that do not change the field
type of the object, they'd simply take a reference or copy of the variant
as opposed to the optional, just as is the case for "visit" or "which." All
operations that do not change the field type have absolutely no reason to
deal with an optional. You only interface with optional when you need to
invoke move-assignment or emplacement functions that can throw exceptions
(if not immediately obvious, you get a non-noexcept emplacement operation
for free from optional's emplacement, which in turn operates via the
variant's emplacement constructor).
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> In either case, the complexity is exactly the same: users without throwing
> move are never empty, and users with throwing moves have to deal with
> validity.
>
Again, this is false.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Since both ideas apply the same general solution to the problem (never
> empty, never have copy/move overhead, users with failing types have to
> check validity), the question now is how to impose that structure. Users
> with throwing move types *must* deal with validity. So how do you do that?
>
> Your way forces them to suffer through using `optional<variant<T...>>`.
> Think about what their code will have to look like.
>
If by "suffer" you mean "use functionality of a higher-level abstraction
rather than baking that complexity into your own type," then yeah, I'd
gladly "suffer."
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Every time they want to access the stored value, they have to call `get`.
> Every time they want to apply a visitor, they have to call `get`. Again and
> again and again. Even if they *know for a fact* that the variant is safe,
> they *have to* call `get`.
>
That's not true, just like you don't have to check if the "possibly
invalid" variant is invalid at every step. The benefit here is that by way
of optional you get this via the type system. In other words, in the
optional approach, once you know the optional is valid, you can just
retrieve a reference to the underlying variant by dereferencing the
optional and work with that reference (or you avoid the explicit check
entirely and do the equivalent of a visit).
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Normally, if some function returns an `optional<T>`, you can check to see
> if it's really there, then move it into an actual variable. But not your
> way; you have to store it as an `optional`, so you have to constantly use
> it as an optional.
>
First off, you can still do this in all cases where your type is movable
(regardless of exception specification) assuming that you are constructing
the variant. The construction of a variant by moving out of a dereferenced
optional<variant<T...>> is perfectly fine, as copy/move construction has
always been fine. If you are talking about the equivalent of a
move-assignment rather than a move-construction, this is also fine unless
you have a move-constructor that can throw. The only time you wouldn't do
it is when you are doing an assignment as opposed to a construction and
your move-constructor can throw, in which case yeah, you'd use an optional.
If you think that this extra typing for such a case is too much effort for
you, over all of the other benefits, then I don't know what to tell you. I
value correctness and easy to reason about types and functions over
minimizing the amount of typing I might some day need to do for an obscure
case.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Not only that, your method *requires* changes to `optional`, changes that
> are, charitably, dubious. If those changes don't pass the committee (and I
> wouldn't hold my breath), then `variant` cannot effectively be used with
> throwing move types.
>
I cannot speak for the committee regarding the suggested optional changes,
but after speaking with certain people offline it is clear that others
understand and agree with my assessment even though some in this thread do
not (or at least did not, initially). It wouldn't surprise me if the
committee as a whole didn't "get" it, just as you don't get it, and I
cannot change that. It is a non-obvious addition, but it really is
logically sound, whether you realize it or not. All I can do is try to make
the case.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> N4542's way recognizes that the problem exists. So instead of passing it
> off to some other type, it simply provides `variant` with the interface to
> solve it, but *only* in that specific, narrow case.
>
"Passing it off" to some other type is not something you should be afraid
of, it's something that you should embrace. Use construction and
destruction to denote when you become "valid" and "invalid" with a
user-defined type. If when performing an operation you would otherwise be
left in an "invalid" state, then users should no longer see your type as
constructed at all. The benefit of this is that it implies that any
constructed instance of your type is by definition valid unless you did
something else that was ill-formed. This notion is precisely what the use
of optional here gets you -- if you would be left in a state where none of
your field types would be represented, instead of baking in an invalid
state into all variants, you just destroy the object. Variant's interface
remains simple and not in need of separate notion of "validity", all of
your contracts remain simple with "is valid" preconditions, and your
invariants remain strict.
> On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Why should we pick the option that hurts throwing move users more? Isn't
> using throwing move types *enough* of a punishment ;)
>
There should be no end of punishment for such users :)
Joking aside, I'm sympathetic to types that have move constructors that can
throw even though I do not personally implement such types, apart from
indirectly making them via composition of existing types that have move
constructors that can throw. Until and unless we ever get destructive move,
there are [unfortunately] compelling reasons for move constructors that can
throw exception to exist. I hate that and I wish I could deny it as it
would make a lot of things in the language much simpler, but I do
understand it.
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>
Would it help satisfy your sensibilities about "complexity" if the
> interface for N4542's `variant` actually SFINAE-removed the `is_valid`
> member, if the typelist doesn't contain throwing move types?
>
I don't think this is really an option because you can get to invalid even
if none of your types have any constructors that can throw. If you
*really *wanted
that out of this proposal, you'd have to also restrict emplacement to be
noexcept. Further, for the sake of writing generic code, it's useful for
the operation with that name to still be there in all cases, since even if
"is_valid" were somehow always logically true based on field types (it's
currently not), generic code that invokes the function is doing nothing
logically incorrect. It's just that the function would always return a
value that is known at compile-time.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1137bdd0a6ef7b052078169c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Sep 23, 2015 at 5:54 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> 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-st=
yle:solid;padding-left:1ex"><div>But my types might offer a strong exceptio=
n guarantee. If all the types I put into a variant offer the strong guarant=
ee, it is perfectly reasonable for the `variant` of them to offer it also. =
Yet sticking it in your kind of `variant` breaks that guarantee.<br></div><=
/blockquote><div><br></div><div>What? That's never been true, even for =
the struct/pair case that you refer to. The strong guarantee does not compo=
se in that case, either. Only the nothrow guarantee composes in that manner=
for such a type with orthogonal fields, just as it does for a variant, her=
e. Separate from variant entirely, it gets even worse for more general clas=
s types that have higher-level invariants predicated on members. In this ca=
se, not only does the strong guarantee not compose to produce something tha=
t satisfies the strong guarantee, but here the direct composition can (and =
often does) leave you with an assignment operation that wouldn't even m=
eet the basic guarantee, let alone the strong guarantee. This has always be=
en the nature of the exception guarantees. Yeah, it's unfortunate, but =
it's nothing unique to variant.</div><div><br></div><div>On Wed, Sep 23=
, 2015 at 5:54 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto=
:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=
=C2=A0wrote:</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"><div>You mean, besides the fact that a w=
rapper type fabricating an operation that is illegal on the contents makes =
no sense? You are basically saying that, if T is not move assignable, `opti=
onal<T>`, which is a value-type-wrapper for T, should <i>create</i> a=
move assignment operator where possible.<br><br>That's <i>completely i=
nsane</i>.<br></div></blockquote><div><br></div><div>No, it's really no=
t, and I've explained in detail why it is not, why it works, and how it=
is implementable. Yeah, it's non-obvious, but it is correct. Simply sa=
ying it's "insane" doesn't advance this conversation. If =
there is something specific in the explanation that you disagree with, then=
refer precisely to it and why you think it is in error. Calling the overal=
l idea "insane" doesn't help. Explain why it logically does n=
ot make sense, along with an example case. Until then it is impossible to e=
ven debate the topic because you are not saying anything to refute. You'=
;re essentially just stating that it is not logical because you do not find=
it intuitive. That is not a sufficient answer.<br></div><div><br></div><di=
v>On Wed, Sep 23, 2015 at 5:54 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<=
a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com=
</a>></span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,2=
04,204);border-left-style:solid;padding-left:1ex"><div><a href=3D"http://ww=
w.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4480.html#optional" target=
=3D"_blank">The committee begs to differ</a>. That may not be in C++17 as a=
language/library, but it's still a C++ standard.<br></div></blockquote=
><div><br></div><div>I am aware of the state of optional.</div><div><br></d=
iv><div>On Wed, Sep 23, 2015 at 5:54 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"=
><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gma=
il.com</a>></span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" st=
yle=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>If it forces y=
our interface to be incredibly unintuitive and difficult to use<br></div></=
blockquote><div><br></div><div>How exactly is it unintuitive or difficult t=
o use an optional<variant<T...>>, where the variant has the nev=
er-empty guarantee? It has exactly the same interface as an optional becaus=
e that is precisely what it is, and the interface of a never-empty variant =
specifies fewer operations than a variant with an "invalid" state=
, and the operations that it does specify have simpler contracts. People do=
n't have to learn how to check for the invalid state or how the invalid=
state is dealt with for things like visit() or which() because the variant=
simply cannot ever be in such a state. You check for an "invalid"=
; state by seeing if your optional is nullopt, just like you would with any=
other optional instance. Again, there are fewer functions total in the int=
erface of the type, in addition to the types themselves having stricter inv=
ariants and the associated functions having simpler contracts. There are fe=
wer operations and what is there has simpler contracts, yet there is also n=
o loss in overall functionality. The only thing that is non-obvious about t=
his is precisely the requirements of the assignment operator of the underly=
ing variant and also the observation of the ability to implement the assign=
ment operator of optional in slightly more cases than is currently done, bu=
t users don't have to immediately understand the reason behind such req=
uirements, they only have to know that the requirements are there. If you a=
lways want the equivalent of an invalid state for whatever reason, just put=
it in an optional, which is exactly what you'd do with any other type.=
Not everyone creates variants with fields that have move constructors that=
can throw, so the type shouldn't always suffer that penalty. Further, =
without much effort in the implementation, not only is there no loss in fun=
ctionality and simpler contracts, but an optional<variant<T...>>=
; can even be as space-efficient as a variant with an invalid state since t=
he discriminator storage can be shared.</div><div>=C2=A0<br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-widt=
h:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-le=
ft:1ex"><span class=3D""><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><div class=
=3D"gmail_quote"><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<sp=
an dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=
=A0wrote:</div></div></div></div></blockquote></span><div>A sign of a good =
abstraction is that it insulates you from details you don't need to kno=
w as much as it possibly can.<br></div></blockquote><div><br></div><div>You=
don't need to know anything about the internals of variant to use this=
.. You only need to know the requirements of the associated functions.</div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l=
eft-style:solid;padding-left:1ex"><div>=C2=A0On Tue, Sep 22, 2015 at 8:16 P=
M, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail=
..com</a>></span>=C2=A0wrote:</div><span class=3D""><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_quote"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rg=
b(204,204,204);border-left-style:solid;padding-left:1ex"><div>On Wednesday,=
September 23, 2015 at 12:37:46 AM UTC-4, Matt Calabrese wrote:<br></div><s=
pan><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:sol=
id;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>=
They are completely different problems that have different requirements and=
different solutions. Your intuitions do not carry over, and that's unf=
ortunate, but it is also reality. I understand that you personally don'=
t find that particular requirement very obvious, but again, one's intui=
tions have no impact on what is actually true. Either yo represent those re=
quirements, or you weaken the invariants of the type by introducing an inva=
lid state, thereby complicating things further.</div></div></div></div></bl=
ockquote></span><div><br>So, having an invalid state that is only used by p=
eople who need it is more complicated than having a type become immobile ev=
en though its contained types are mobile, just in an unusual way? That is l=
ess complicated?<br></div></blockquote><div><br></div><div>By my suggestion=
(and boost), what are the possible states that variant<T...> can be =
in? Any one of T. What are the preconditions of apply_visitor? No explicit =
preconditions. If I write a function that accepts a reference to a variant,=
do I know it is "valid?" Yes, because by the very nature of the =
type it is impossible to be invalid.</div><div><br></div><div>By introducin=
g an invalid state, what are the possible states that variant<T...> c=
an be in? Any one of T... or it could be invalid. What are the precondition=
s of apply_visitor? variant must not be in the invalid state. If I write a =
function that accepts a reference to a variant, do I know it is "valid=
?" Not unless I specify that as a precondition, and in practice I'=
d probably also assert that the variant is valid in the body of the functio=
n.</div><div><br></div><div>So yeah, it is less complicated to reason about=
and work with the type when it satisfies the never empty guarantee. Are th=
e requirements for getting certain operations non-obvious? Sure, but they a=
re the necessary requirements to keep the invariants of the type strict and=
to make the contracts of functions that deal with the type simple. You can=
still get all of the equivalent behavior of the "invalid" state,=
you just do so without weakening the type's invariants.</div></div></d=
iv></blockquote></span><div><br>This is the most important thing. Because, =
while I did in fact misunderstand a number of elements of your idea, it tur=
ns out that you've misunderstood a number of elements of N4542, as evid=
enced by these paragraphs.<br></div></blockquote><div><br></div><div>??? No=
I haven't.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=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">=C2=A0On Tue, Sep 22=
, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollo=
w">jmck...@gmail.com</a>></span>=C2=A0wrote:<div>Under N4542, `variant` =
becomes invalid if, <b><i>and only if</i></b>, a copy/move fails. Which mea=
ns, if you use types where copy/move <i>cannot fail</i>... your `variant`s =
will always be valid.<br></div></blockquote><div><br></div><div>That is not=
true even in N4542 as you can also get there via failed emplacement, even =
if you're not dealing with types that have move constructors that can t=
hrow (perhaps less obvious, you can get to invalid even if all of your fiel=
ds have no constructors that are noexcept(false) by way of emplace -- and o=
n that note, the specification of emplace in the document is technically in=
correct regarding exceptions, since it doesn't cover exceptions stemmin=
g from argument conversions during emplacement).</div><div><br></div><div>A=
part from that, in generic code (I.E. you are dealing with a dependent vari=
ant<T...>), it is nontrivial to determine whether your type can or ca=
nnot easily be in the invalid state anyway, not that it would matter becaus=
e whether easy or not, it can always possibly get there, regardless of the =
field types.</div><div><br></div><div>=C2=A0On Tue, Sep 22, 2015 at 8:16 PM=
, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.=
com</a>></span>=C2=A0wrote:<br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rg=
b(204,204,204);border-left-style:solid;padding-left:1ex"><div>`variant<i=
nt,
float>` will always be valid. As will `variant<std::string,=20
std::vector<T>>`. As will `variant`s of most C++ standard=20
library types.=C2=A0<br></div>So in both your idea and N4542, users who don=
't use throwing move types in `variant` will get the "never-empty =
guarantee".</blockquote><div>=C2=A0</div><div>As described above, none=
of your assertions here are actually true. Any of those types can end up i=
n the invalid state in a valid program. There is no never-empty guarantee f=
or any set of field types in this proposal.</div><div><br></div><div>=C2=A0=
On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a =
rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0wrote:</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-l=
eft:1ex"><div>And in both ideas, users who use throwing move types <i>have =
to</i> deal with validity. So your claim of "greater complexity" =
is simply wrong.</div></blockquote><div><br></div><div>No, in my suggestion=
they only have to deal with "validity" when the user is referrin=
g to an <i>optional</i> of the variant, just as is the case in general with=
other types. For any functions that do not change the field type of the ob=
ject, they'd simply take a reference or copy of the variant as opposed =
to the optional, just as is the case for "visit" or "which.&=
quot; All operations that do not change the field type have absolutely no r=
eason to deal with an optional. You only interface with optional when you n=
eed to invoke move-assignment or emplacement functions that can throw excep=
tions (if not immediately obvious, you get a non-noexcept emplacement opera=
tion for free from optional's emplacement, which in turn operates via t=
he variant's emplacement constructor).</div><div><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex">=C2=A0On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"l=
tr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0wrote:<di=
v>In either case, the complexity is exactly the same: users without throwin=
g move are never empty, and users with throwing moves have to deal with val=
idity.<br></div></blockquote><div><br></div><div>Again, this is false.</div=
><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-=
left-style:solid;padding-left:1ex"><div>On Tue, Sep 22, 2015 at 8:16 PM, Ni=
col Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com<=
/a>></span>=C2=A0wrote:<br></div><div>Since both ideas apply the same ge=
neral solution to the problem (never empty, never have copy/move overhead, =
users with failing types have to check validity), the question now is how t=
o impose that structure. Users with throwing move types <i>must</i> deal wi=
th validity. So how do you do that?<br><br>Your way forces them to suffer t=
hrough using `optional<variant<T...>>`. Think about what their =
code will have to look like.<br></div></blockquote><div><br></div><div>If b=
y "suffer" you mean "use functionality of a higher-level abs=
traction rather than baking that complexity into your own type," then =
yeah, I'd gladly "suffer."</div><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex">On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr">&l=
t;<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0wrote:<div>Ever=
y time they want to access the stored value, they have to call `get`. Every=
time they=20
want to apply a visitor, they have to call `get`. Again and again and=20
again. Even if they <i>know for a fact</i> that the variant is safe, they <=
i>have to</i> call `get`.<br></div></blockquote><div><br></div><div>That=
9;s not true, just like you don't have to check if the "possibly i=
nvalid" variant is invalid at every step. The benefit here is that by =
way of optional you get this via the type system. In other words, in the op=
tional approach, once you know the optional is valid, you can just retrieve=
a reference to the underlying variant by dereferencing the optional and wo=
rk with that reference (or you avoid the explicit check entirely and do the=
equivalent of a visit).</div><div>=C2=A0</div><div>On Tue, Sep 22, 2015 at=
8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck..=
..@gmail.com</a>></span>=C2=A0wrote:</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>Normally,
if some function returns an `optional<T>`, you can check to see=20
if it's really there, then move it into an actual variable. But not you=
r
way; you have to store it as an `optional`, so you have to constantly=20
use it as an optional.</div></blockquote><div><br></div><div>First off, you=
can still do this in all cases where your type is movable (regardless of e=
xception specification) assuming that you are constructing the variant. The=
construction of a variant by moving out of a dereferenced optional<vari=
ant<T...>> is perfectly fine, as copy/move construction has always=
been fine. If you are talking about the equivalent of a move-assignment ra=
ther than a move-construction, this is also fine unless you have a move-con=
structor that can throw. The only time you wouldn't do it is when you a=
re doing an assignment as opposed to a construction and your move-construct=
or can throw, in which case yeah, you'd use an optional. If you think t=
hat this extra typing for such a case is too much effort for you, over all =
of the other benefits, then I don't know what to tell you. I value corr=
ectness and easy to reason about types and functions over minimizing the am=
ount of typing I might some day need to do for an obscure case.</div><div>=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-le=
ft-style:solid;padding-left:1ex">On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bol=
as=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>>=
</span>=C2=A0wrote:<div>Not only that, your method <i>requires</i> changes =
to `optional`, changes that are, charitably, dubious. If those changes don&=
#39;t pass the committee (and I wouldn't hold my breath), then `variant=
` cannot effectively be used with throwing move types.<br></div></blockquot=
e><div><br></div><div>I cannot speak for the committee regarding the sugges=
ted optional changes, but after speaking with certain people offline it is =
clear that others understand and agree with my assessment even though some =
in this thread do not (or at least did not, initially). It wouldn't sur=
prise me if the committee as a whole didn't "get" it, just as=
you don't get it, and I cannot change that. It is a non-obvious additi=
on, but it really is logically sound, whether you realize it or not. All I =
can do is try to make the case.</div><div>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border=
-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On T=
ue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a rel=
=3D"nofollow">jmck...@gmail.com</a>></span>=C2=A0wrote:<div>N4542's =
way recognizes that the problem exists. So instead of passing it off to som=
e other type, it simply provides `variant` with the interface to solve it, =
but <i>only</i> in that specific, narrow case.<br></div></blockquote><div><=
br></div><div>"Passing it off" to some other type is not somethin=
g you should be afraid of, it's something that you should embrace. Use =
construction and destruction to denote when you become "valid" an=
d "invalid" with a user-defined type. If when performing an opera=
tion you would otherwise be left in an "invalid" state, then user=
s should no longer see your type as constructed at all. The benefit of this=
is that it implies that any constructed instance of your type is by defini=
tion valid unless you did something else that was ill-formed. This notion i=
s precisely what the use of optional here gets you -- if you would be left =
in a state where none of your field types would be represented, instead of =
baking in an invalid state into all variants, you just destroy the object. =
Variant's interface remains simple and not in need of separate notion o=
f "validity", all of your contracts remain simple with "is v=
alid" preconditions, and your invariants remain strict.=C2=A0</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"><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol =
Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>&=
gt;</span>=C2=A0wrote:<br>Why should we pick the option that hurts throwing=
move users more? Isn't using throwing move types <i>enough</i> of a pu=
nishment ;)<br></div></blockquote><div><br></div><div>There should be no en=
d of punishment for such users :)</div><div><br></div><div>Joking aside, I&=
#39;m sympathetic to types that have move constructors that can throw even =
though I do not personally implement such types, apart from indirectly maki=
ng them via composition of existing types that have move constructors that =
can throw. Until and unless we ever get destructive move, there are [unfort=
unately] compelling reasons for move constructors that can throw exception =
to exist. I hate that and I wish I could deny it as it would make a lot of =
things in the language much simpler, but I do understand it.</div><div><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div>On Tue, Sep 22, 2015 at 8:16 PM, Nicol Bolas=C2=
=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></spa=
n>=C2=A0wrote:=C2=A0</div></blockquote><blockquote class=3D"gmail_quote" st=
yle=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>Would
it help satisfy your sensibilities about "complexity" if the int=
erface for N4542's=20
`variant` actually SFINAE-removed the `is_valid` member, if the typelist
doesn't contain throwing move types?</div></blockquote><div><br></div>=
<div>I don't think this is really an option because you can get to inva=
lid even if none of your types have any constructors that can throw. If you=
<i>really=C2=A0</i>wanted that out of this proposal, you'd have to als=
o restrict emplacement to be noexcept. Further, for the sake of writing gen=
eric code, it's useful for the operation with that name to still be the=
re in all cases, since even if "is_valid" were somehow always log=
ically true based on field types (it's currently not), generic code tha=
t invokes the function is doing nothing logically incorrect. It's just =
that the function would always return a value that is known at compile-time=
..</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1137bdd0a6ef7b052078169c--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 24 Sep 2015 01:40:23 -0500
Raw View
--001a1141dba0d2e9480520788366
Content-Type: text/plain; charset=UTF-8
On 24 September 2015 at 01:10, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
>
> On Wed, Sep 23, 2015 at 5:54 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> If it forces your interface to be incredibly unintuitive and difficult to
>> use
>>
>
> How exactly is it unintuitive or difficult to use an
> optional<variant<T...>>, where the variant has the never-empty guarantee?
>
How does it work?
Suppose I have the following class:
struct NonAssignable
{
NonAssignable() = default;
NonAssignable(NonAssignable const&) = default;
NonAssignable& operator=(NonAssignable const&) = delete;
NonAssignable& operator=(NonAssignable&&) = delete;
NonAssignable(NonAssignable&&) = default;
~NonAssignable() = default;
};
optional<NonAssignable> currently has no assignment operator, because
NonAssignable has no assignment operator.
If your variant<T...> has no assignment operator, how exactly does
optional<variant<T...>> magically get one??
The only thing I can think of is that optional synthesizes an assignment
operator by "if (engaged) { if (!selfAssign) destroy; construct; }" instead
of the current "if (engaged) assign; else construct;" (or do you only want
to do that for types that are not assignable?), but I would find an
optional which did that quite surprising.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1141dba0d2e9480520788366
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 24 September 2015 at 01:10, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></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 class=3D=
"gmail_quote"><span class=3D""><div><br></div><div>On Wed, Sep 23, 2015 at =
5:54 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson=
@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote=
:<br></div></span><span class=3D""><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div>If it forces your=
interface to be incredibly unintuitive and difficult to use<br></div></blo=
ckquote><div><br></div></span><div>How exactly is it unintuitive or difficu=
lt to use an optional<variant<T...>>, where the variant has the=
never-empty guarantee? </div></div></div></div></blockquote><div><br></div=
><div>How does it work?</div><div><br></div><div>Suppose I have the followi=
ng class:</div><div><br></div><div>struct NonAssignable</div><div>{</div><d=
iv>=C2=A0 =C2=A0 NonAssignable() =3D default;</div><div><br></div><div>=C2=
=A0 =C2=A0 NonAssignable(NonAssignable const&) =3D default;</div><div>=
=C2=A0 =C2=A0 NonAssignable& operator=3D(NonAssignable const&) =3D =
delete;</div><div>=C2=A0 =C2=A0 NonAssignable& operator=3D(NonAssignabl=
e&&) =3D delete;</div><div>=C2=A0 =C2=A0 NonAssignable(NonAssignabl=
e&&) =3D default;</div><div>=C2=A0 =C2=A0 ~NonAssignable() =3D defa=
ult;</div><div>};<br></div><div><br></div><div>optional<NonAssignable>=
; currently has no assignment operator, because NonAssignable has no assign=
ment operator.</div><div><br></div><div>If your variant<T...> has no =
assignment operator, how exactly does optional<variant<T...>> m=
agically get one??</div><div><br></div><div>The only thing I can think of i=
s that optional synthesizes an assignment operator by "if (engaged) { =
if (!selfAssign) destroy; construct; }" instead of the current "i=
f (engaged) assign; else construct;" (or do you only want to do that f=
or types that are not assignable?), but I would find an optional which did =
that quite surprising.</div></div>-- <br><div class=3D"gmail_signature">=C2=
=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@evi=
loverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847)=
691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1141dba0d2e9480520788366--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 24 Sep 2015 01:49:44 -0500
Raw View
--001a114363ac3fc4cb052078a546
Content-Type: text/plain; charset=UTF-8
On 23 September 2015 at 17:06, Anthony Williams <anthony.ajw@gmail.com>
wrote:
> I've done some work on my variant implementation on bitbucket
> (https://bitbucket.org/anthonyw/variant) to add the strong guarantee.
>
> It does this in a variety of ways, in order to minimize space.
>
> 1. If the type you are constructing has a nothrow constructor you are
> trying to use, destroy old value then construct directly
>
> 2. If the type you are constructing has a nothrow move constructor, and
> it is not double-buffered (see below) then construct locally and then
> destroy old value, and move-construct into the variant.
>
> 3. If all the other types have a nothrow move constructor and this type
> is not double-buffered (see below) then move-construct the old value
> into a local buffer, construct the new value in place, then destroy the
> local buffer. On exception, move the old value back.
>
> 4. If at least 2 types are not nothrow-move-constructible then we need a
> double-buffer. The size of the buffer is set to big enough to cover all
> the types that are not nothrow-move-constructible. However, all types
> that fit are then counted as double-buffered. This avoids extra move
> constructions where possible, without imposing a space penalty beyond
> what is required.
>
> I think this is a reasonable trade-off. YMMV.
>
While I haven't read through the latest iteration of your code yet, the
above description is quite reasonable, and at first glance, I like it
better than N4542. Nice job!
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a114363ac3fc4cb052078a546
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 23 September 2015 at 17:06, Anthony Williams <span dir=
=3D"ltr"><<a href=3D"mailto:anthony.ajw@gmail.com" target=3D"_blank">ant=
hony.ajw@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div=
class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 =
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I've done some wo=
rk on my variant implementation on bitbucket<br>
(<a href=3D"https://bitbucket.org/anthonyw/variant" rel=3D"noreferrer" targ=
et=3D"_blank">https://bitbucket.org/anthonyw/variant</a>) to add the strong=
guarantee.<br>
<br>
It does this in a variety of ways, in order to minimize space.<br>
<br>
1. If the type you are constructing has a nothrow constructor you are<br>
trying to use, destroy old value then construct directly<br>
<br>
2. If the type you are constructing has a nothrow move constructor, and<br>
it is not double-buffered (see below) then construct locally and then<br>
destroy old value, and move-construct into the variant.<br>
<br>
3. If all the other types have a nothrow move constructor and this type<br>
is not double-buffered (see below) then move-construct the old value<br>
into a local buffer, construct the new value in place, then destroy the<br>
local buffer. On exception, move the old value back.<br>
<br>
4. If at least 2 types are not nothrow-move-constructible then we need a<br=
>
double-buffer. The size of the buffer is set to big enough to cover all<br>
the types that are not nothrow-move-constructible. However, all types<br>
that fit are then counted as double-buffered. This avoids extra move<br>
constructions where possible, without imposing a space penalty beyond<br>
what is required.<br>
<br>
I think this is a reasonable trade-off. YMMV.<br></blockquote><div><br></di=
v><div>While I haven't read through the latest iteration of your code y=
et, the above description is quite reasonable, and at first glance, I like =
it better than N4542.=C2=A0 Nice job!</div></div>-- <br><div class=3D"gmail=
_signature">=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a114363ac3fc4cb052078a546--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 00:17:33 -0700
Raw View
--94eb2c0961c45e94ce05207906bd
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 23, 2015 at 11:40 PM, Nevin Liber <nevin@eviloverlord.com>
wrote:
>
> If your variant<T...> has no assignment operator, how exactly does
> optional<variant<T...>> magically get one??
>
> The only thing I can think of is that optional synthesizes an assignment
> operator by "if (engaged) { if (!selfAssign) destroy; construct; }" instead
> of the current "if (engaged) assign; else construct;" (or do you only want
> to do that for types that are not assignable?), but I would find an
> optional which did that quite surprising.
>
Precisely this (well, slightly more complicated if you address
self-assignment). You would *only *do it in this way if the type is
move-constructible and yet not move-assignable, which is an exceedingly
rare class of types that a non-empty-guarantee variant type with a field
that has a move-constructor that can throw would happen to be one of. To
explain why this is logical, understand that optional already effectively
implies some higher level equivalence between the result of a
move-construction and a move-assignment (or copy-assign vs copy-construct
for that matter). This can be shown by examining what happens in the
following -- here I use copies but the same is true for moves:
//////////
optional<T> foo = nullopt;
optional<T> empty_opt = nullopt;
optional<T> nonempty_opt = T();
// This looks like assignment (it is), but internally it's copy-constructing
// because foo begin as nullopt.
foo = nonempty_opt;
// This looks like assignment (it is), and internally it really is
copy-assigning
// because foo is currently engaged.
foo = nonempty_opt;
//////////
If you acknowledge the above, then you can already see that assignment can
already operate by doing construction internally (I.E. we don't always use
assignment operators to implement assignment operators, depending at
runtime on whether or not the instance is initially nullopt). In other
words, you assign internally when it is possible to assign, and you
construct when you can't assign because there is no existing instance
(notably, alternatively, if using assign to implement assign were really
important, and the type were default constructible, then people should be
arguing that it would be more "correct" to default construct and assign
here, but we do not make that case because we understand the higher level
functional equivalence between the operations).
So what happens if the type T is, for instance, move-constructible but not
move-assignable? Here, the part of the implementation that handles the case
when the left-hand operand is nullopt remains unchanged. We *always* used
construction here as opposed to assignment. But what about the alternative
case, where the left hand operand is *not* nullopt. In this case, we can no
longer directly call the assignment operator because one does not exist.
However, we do have a corresponding constructor, and since we are already
okay with relying on the functional equivalence of the result of a
copy-assignment and a copy-construction with respect to the internals of
optional in the case that the left-hand operand were nullopt, the why would
you assert anything different regarding destruction of the internal T of
the left-hand operand followed by construction (in other words, the
equivalent of what emplacement would do here)? Because we are in an
optional, in the event that the construction fails by way of an exception,
we restore our invariants by now leaving the optional in the nullopt state
as the exception propagates back to the caller. Again, this is precisely
what emplacement also does in this case.
So the conclusion, which is certainly not immediately obvious without
really thinking about the situation, is that if you have a type T that is
copy-constructible/move-constructible yet not
copy-assignable/move-assignable, you can put it into an optional and the
resultant type is one that is perfectly capable of being assignable! The
behavior with respect to falling back to nullopt in the event that an
exception being thrown is also not very surprising, as if you think of
optional as a special case of a variant, this is equivalent to what Boost
does in the event that an exception is thrown in the middle of a
reconstruction like this -- it falls back to a
noexcept-default-constructible field type. In the case here, the optional
can be thought of as equivalent in functionality and concept (though not
exact interface) to a variant<nullopt_t. T>. nullopt_t happens to be that
sufficient fallback that we use to maintain our invariants as we propagate
the exception back to the caller, and we do so without some additional
invalid state.
This is all beneficial to us because a variant with the
never-empty-guarantee and the avoidance of things like dynamic memory
allocation or permanent double storage (or Anthony's partial double storage
technique), which are other solutions that would avoid sacrificing the
never-empty guarantee, we would be left either with users specifying a
field type that acts as a fallback (sadly voted down, IMO), or a variant
whose operator= requirements are just no longer met and so the operation is
deleted. As unfortunate as that is, if you understand/agree with the above
assessment of optional's assignment operator, which I honestly do think is
difficult to refute if you really think about it even though it is not
immediately obvious, then you can get the equivalent of the functionality
of the "invalid" state, without losing the never-empty-guarantee and while
having a type that is assignable/emplaceable, even if a field's
move-constructor can throw or emplacement can throw. In that case, type
type is simply called optional<variant<T...>>. This is not a trick or a
hack, it just naturally emerges from the generalization of operations.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--94eb2c0961c45e94ce05207906bd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Sep 23, 2015 at 11:40 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"=
mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>=
></span> 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"><div class=3D"gmail_ext=
ra"><div class=3D"gmail_quote"><div>If your variant<T...> has no assi=
gnment operator, how exactly does optional<variant<T...>> magic=
ally get one??</div><div><br></div><div>The only thing I can think of is th=
at optional synthesizes an assignment operator by "if (engaged) { if (=
!selfAssign) destroy; construct; }" instead of the current "if (e=
ngaged) assign; else construct;" (or do you only want to do that for t=
ypes that are not assignable?), but I would find an optional which did that=
quite surprising.</div></div></div></div></blockquote></div><br></div><div=
class=3D"gmail_extra">Precisely this (well, slightly more complicated if y=
ou address self-assignment). You would <i>only=C2=A0</i>do it in this way i=
f the type is move-constructible and yet not move-assignable, which is an e=
xceedingly rare class of types that a non-empty-guarantee variant type with=
a field that has a move-constructor that can throw would happen to be one =
of. To explain why this is logical, understand that optional already effect=
ively implies some higher level equivalence between the result of a move-co=
nstruction and a move-assignment (or copy-assign vs copy-construct for that=
matter). This can be shown by examining what happens in the following -- h=
ere I use copies but the same is true for moves:</div><div class=3D"gmail_e=
xtra"><br></div><div class=3D"gmail_extra">//////////</div><div class=3D"gm=
ail_extra">optional<T> foo =3D nullopt;</div><div class=3D"gmail_extr=
a">optional<T> empty_opt =3D nullopt;</div><div class=3D"gmail_extra"=
>optional<T> nonempty_opt =3D T();</div><div class=3D"gmail_extra"><b=
r></div><div class=3D"gmail_extra">// This looks like assignment (it is), b=
ut internally it's copy-constructing<br></div><div class=3D"gmail_extra=
">// because foo begin as nullopt.</div><div class=3D"gmail_extra">foo =3D =
nonempty_opt;</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail=
_extra">// This looks like assignment (it is), and internally it really is =
copy-assigning</div><div class=3D"gmail_extra">// because foo is currently =
engaged.</div><div class=3D"gmail_extra">foo =3D nonempty_opt;</div><div cl=
ass=3D"gmail_extra">//////////</div><div class=3D"gmail_extra"><br></div><d=
iv class=3D"gmail_extra">If you acknowledge the above, then you can already=
see that assignment can already operate by doing construction internally (=
I.E. we don't always use assignment operators to implement assignment o=
perators, depending at runtime on whether or not the instance is initially =
nullopt). In other words, you assign internally when it is possible to assi=
gn, and you construct when you can't assign because there is no existin=
g instance (notably, alternatively, if using assign to implement assign wer=
e really important, and the type were default constructible, then people sh=
ould be arguing that it would be more "correct" to default constr=
uct and assign here, but we do not make that case because we understand the=
higher level functional equivalence between the operations).</div><div cla=
ss=3D"gmail_extra"><br></div><div class=3D"gmail_extra">So what happens if =
the type T is, for instance, move-constructible but not move-assignable? He=
re, the part of the implementation that handles the case when the left-hand=
operand is nullopt remains unchanged. We <i>always</i>=C2=A0used construct=
ion here as opposed to assignment. But what about the alternative case, whe=
re the left hand operand is <i>not</i>=C2=A0nullopt. In this case, we can n=
o longer directly call the assignment operator because one does not exist. =
However, we do have a corresponding constructor, and since we are already o=
kay with relying on the functional equivalence of the result of a copy-assi=
gnment and a copy-construction with respect to the internals of optional in=
the case that the left-hand operand were nullopt, the why would you assert=
anything different regarding destruction of the internal T of the left-han=
d operand followed by construction (in other words, the equivalent of what =
emplacement would do here)? Because we are in an optional, in the event tha=
t the construction fails by way of an exception, we restore our invariants =
by now leaving the optional in the nullopt state as the exception propagate=
s back to the caller. Again, this is precisely what emplacement also does i=
n this case.</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_=
extra">So the conclusion, which is certainly not immediately obvious withou=
t really thinking about the situation, is that if you have a type T that is=
copy-constructible/move-constructible yet not copy-assignable/move-assigna=
ble, you can put it into an optional and the resultant type is one that is =
perfectly capable of being assignable! The behavior with respect to falling=
back to nullopt in the event that an exception being thrown is also not ve=
ry surprising, as if you think of optional as a special case of a variant, =
this is equivalent to what Boost does in the event that an exception is thr=
own in the middle of a reconstruction like this -- it falls back to a noexc=
ept-default-constructible field type. In the case here, the optional can be=
thought of as equivalent in functionality and concept (though not exact in=
terface) to a variant<nullopt_t. T>. nullopt_t happens to be that suf=
ficient fallback that we use to maintain our invariants as we propagate the=
exception back to the caller, and we do so without some additional invalid=
state.</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra=
">This is all beneficial to us because a variant with the never-empty-guara=
ntee and the avoidance of things like dynamic memory allocation or permanen=
t double storage (or Anthony's partial double storage technique), which=
are other solutions that would avoid sacrificing the never-empty guarantee=
, we would be left either with users specifying a field type that acts as a=
fallback (sadly voted down, IMO), or a variant whose operator=3D requireme=
nts are just no longer met and so the operation is deleted. As unfortunate =
as that is, if you understand/agree with the above assessment of optional&#=
39;s assignment operator, which I honestly do think is difficult to refute =
if you really think about it even though it is not immediately obvious, the=
n you can get the equivalent of the functionality of the "invalid"=
; state, without losing the never-empty-guarantee and while having a type t=
hat is assignable/emplaceable, even if a field's move-constructor can t=
hrow or emplacement can throw. In that case, type type is simply called opt=
ional<variant<T...>>. This is not a trick or a hack, it just na=
turally emerges from the generalization of operations.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--94eb2c0961c45e94ce05207906bd--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 00:44:11 -0700
Raw View
--001a11c30caaa800660520796570
Content-Type: text/plain; charset=UTF-8
On Thu, Sep 24, 2015 at 12:17 AM, Matt Calabrese <calabrese@google.com>
wrote:
>
> This is all beneficial to us because a variant with the
> never-empty-guarantee and the avoidance of things like dynamic memory
> allocation or permanent double storage (or Anthony's partial double storage
> technique), which are other solutions that would avoid sacrificing the
> never-empty guarantee, we would be left either with users specifying a
> field type that acts as a fallback (sadly voted down, IMO), or a variant
> whose operator= requirements are just no longer met and so the operation is
> deleted. As unfortunate as that is, if you understand/agree with the above
> assessment of optional's assignment operator, which I honestly do think is
> difficult to refute if you really think about it even though it is not
> immediately obvious, then you can get the equivalent of the functionality
> of the "invalid" state, without losing the never-empty-guarantee and while
> having a type that is assignable/emplaceable, even if a field's
> move-constructor can throw or emplacement can throw. In that case, type
> type is simply called optional<variant<T...>>. This is not a trick or a
> hack, it just naturally emerges from the generalization of operations.
>
I know I've said this before, but I will reiterate. This does not mean that
variant<T...> would never have an assignment operator. All it means is that
the assignment operator's concept requirements are that the field types
have move constructors that are noexcept. Very often, people are dealing
with types that do not have move constructors that can throw, so for them
none of this affects them. They simply get a variant type that has the
never empty guarantee and it is fully assignable, etc. I reiterate this
because this implies that a lot of user code never has to care about this
because the variants that they make would "just work" and be fully
assignable without optional or an invalid state, or anything like that.
It's just like working with Boost's optional. This only affects people with
field types that have move constructors that can throw, or people who want
to use an emplacement mutator that can throw (variant emplacement
constructors are always okay, and so is noexcept emplacement). In that
special kind of case, variant is still instantiable and still satisfies the
never-empty guarantee, it only lacks assignment. An optional of that
variant, though, would now be fully assignable, and you get the functional
equivalent of the "invalid" state though it is now represented by the
optional being nullopt. You get a mutating emplacement that can throw by
way of optional's emplacement function, and you can even retrieve a
reference to the underlying, non-empty variant by simply dereferencing the
optional, giving you a way to communicate a never-empty variant to other
functions.
Because the underlying variant itself would be back to being never-empty,
we would no longer need to even have discussions about what to do if you
visit or invoke which() on an "invalid" variant, because such an "invalid"
variant exist anymore. Similarly, user-land functions that deal with the
variant and that aren't changing its underlying field type in a way that
could imply calling a move-constructor that could throw (I.E. they don't
assign to it, or they only ever use a noexpect emplacement function), then
they too can just deal with a reference or copy of the underlying variant
and never care about an optional that can potentially be nullopt. Their
contracts are all back to being simple without "is valid" preconditions.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c30caaa800660520796570
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, Sep 24, 2015 at 12:17 AM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> wrote:<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 clas=
s=3D"gmail_extra">This is all beneficial to us because a variant with the n=
ever-empty-guarantee and the avoidance of things like dynamic memory alloca=
tion or permanent double storage (or Anthony's partial double storage t=
echnique), which are other solutions that would avoid sacrificing the never=
-empty guarantee, we would be left either with users specifying a field typ=
e that acts as a fallback (sadly voted down, IMO), or a variant whose opera=
tor=3D requirements are just no longer met and so the operation is deleted.=
As unfortunate as that is, if you understand/agree with the above assessme=
nt of optional's assignment operator, which I honestly do think is diff=
icult to refute if you really think about it even though it is not immediat=
ely obvious, then you can get the equivalent of the functionality of the &q=
uot;invalid" state, without losing the never-empty-guarantee and while=
having a type that is assignable/emplaceable, even if a field's move-c=
onstructor can throw or emplacement can throw. In that case, type type is s=
imply called optional<variant<T...>>. This is not a trick or a =
hack, it just naturally emerges from the generalization of operations.</div=
></div></blockquote><div><br></div><div>I know I've said this before, b=
ut I will reiterate. This does not mean that variant<T...> would neve=
r have an assignment operator. All it means is that the assignment operator=
's concept requirements are that the field types have move constructors=
that are noexcept. Very often, people are dealing with types that do not h=
ave move constructors that can throw, so for them none of this affects them=
.. They simply get a variant type that has the never empty guarantee and it =
is fully assignable, etc. I reiterate this because this implies that a lot =
of user code never has to care about this because the variants that they ma=
ke would "just work" and be fully assignable without optional or =
an invalid state, or anything like that. It's just like working with Bo=
ost's optional. This only affects people with field types that have mov=
e constructors that can throw, or people who want to use an emplacement mut=
ator that can throw (variant emplacement constructors are always okay, and =
so is noexcept emplacement). In that special kind of case, variant is still=
instantiable and still satisfies the never-empty guarantee, it only lacks =
assignment. An optional of that variant, though, would now be fully assigna=
ble, and you get the functional equivalent of the "invalid" state=
though it is now represented by the optional being nullopt. You get a muta=
ting emplacement that can throw by way of optional's emplacement functi=
on, and you can even retrieve a reference to the underlying, non-empty vari=
ant by simply dereferencing the optional, giving you a way to communicate a=
never-empty variant to other functions.</div><div><br></div><div>Because t=
he underlying variant itself would be back to being never-empty, we would n=
o longer need to even have discussions about what to do if you visit or inv=
oke which() on an "invalid" variant, because such an "invali=
d" variant exist anymore. Similarly, user-land functions that deal wit=
h the variant and that aren't changing its underlying field type in a w=
ay that could imply calling a move-constructor that could throw (I.E. they =
don't assign to it, or they only ever use a noexpect emplacement functi=
on), then they too can just deal with a reference or copy of the underlying=
variant and never care about an optional that can potentially be nullopt. =
Their contracts are all back to being simple without "is valid" p=
reconditions.</div></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c30caaa800660520796570--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Thu, 24 Sep 2015 03:12:16 -0700 (PDT)
Raw View
------=_Part_449_1796007222.1443089536884
Content-Type: multipart/alternative;
boundary="----=_Part_450_1211018558.1443089536885"
------=_Part_450_1211018558.1443089536885
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 23, 2015 at 11:06:50 PM UTC+1, Anthony Williams
wrote:
>
> On 23/09/15 05:03, Nevin Liber wrote:
> > Oh, and don't forget it is a pessimization to do
> > construct-then-noexcept-move instead of just construct when the variant
> > is changing types, so you are penalizing all users. Of course, double
> > buffering is also a pessimization in terms of cache as well as memory
> usage.
> >
> > Tradeoffs are hard.
>
> Yes, tradeoffs are hard.
>
> I've done some work on my variant implementation on bitbucket
> (https://bitbucket.org/anthonyw/variant) to add the strong guarantee.
>
> It does this in a variety of ways, in order to minimize space.
>
> 1. If the type you are constructing has a nothrow constructor you are
> trying to use, destroy old value then construct directly
>
> 2. If the type you are constructing has a nothrow move constructor, and
> it is not double-buffered (see below) then construct locally and then
> destroy old value, and move-construct into the variant.
>
> 3. If all the other types have a nothrow move constructor and this type
> is not double-buffered (see below) then move-construct the old value
> into a local buffer, construct the new value in place, then destroy the
> local buffer. On exception, move the old value back.
>
> 4. If at least 2 types are not nothrow-move-constructible then we need a
> double-buffer. The size of the buffer is set to big enough to cover all
> the types that are not nothrow-move-constructible. However, all types
> that fit are then counted as double-buffered. This avoids extra move
> constructions where possible, without imposing a space penalty beyond
> what is required.
>
> I think this is a reasonable trade-off. YMMV.
>
>
I see, if only one type is non nothrow move constructible the trick that
there is no scenario where it needs to replace itself. Cool.
Also heap allocation should left as an implementation option instead of
double buffering. No need for explicit allocation support though, if
necessary variant could rely on the scoped_allocator_traits to get an
allocator from the object being copied. Also standard libraries
implementations that are ok allocating on a container move (which is pretty
much the reason for throwing moves to exist) should have no issues in
allocating on a variant assignment either, while other implementations
won't be penalized with having to support a variant with a broken
invariant.
std::variant should be either exception-safe variant (my preference) or
have an explicit empty state. The special failed state is IMHO an
abomination.
Possibly the variant-with-empty-state case could be spelled as
std::optional<std::variant<....> > (which I believe was suggested else
thread) and guarantee minimal space occupancy and freedom from allocation.
In fact it would be nice if optional<variant< > > was guaranteed to be
optimal (i.e. share the variant discriminant and optional flag) in all
cases.
--
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_450_1211018558.1443089536885
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, September 23, 2015 at 11:06:50 PM UTC+1, Anthony Williams wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;">On 23/09/15 05:03, Nevin Li=
ber wrote:
<br>> Oh, and don't forget it is a pessimization to do
<br>> construct-then-noexcept-move instead of just construct when the va=
riant
<br>> is changing types, so you are penalizing all users. =C2=A0Of cours=
e, double
<br>> buffering is also a pessimization in terms of cache as well as mem=
ory usage.
<br>>=20
<br>> Tradeoffs are hard.
<br>
<br>Yes, tradeoffs are hard.
<br>
<br>I've done some work on my variant implementation on bitbucket
<br>(<a href=3D"https://bitbucket.org/anthonyw/variant" target=3D"_blank" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url?=
q\75https%3A%2F%2Fbitbucket.org%2Fanthonyw%2Fvariant\46sa\75D\46sntz\0751\4=
6usg\75AFQjCNE8yBmc8elrYR3VAntb1yyKrbEdeA';return true;" onclick=3D"thi=
s.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fbitbucket.org%2F=
anthonyw%2Fvariant\46sa\75D\46sntz\0751\46usg\75AFQjCNE8yBmc8elrYR3VAntb1yy=
KrbEdeA';return true;">https://bitbucket.org/<wbr>anthonyw/variant</a>)=
to add the strong guarantee.
<br>
<br>It does this in a variety of ways, in order to minimize space.
<br>
<br>1. If the type you are constructing has a nothrow constructor you are
<br>trying to use, destroy old value then construct directly
<br>
<br>2. If the type you are constructing has a nothrow move constructor, and
<br>it is not double-buffered (see below) then construct locally and then
<br>destroy old value, and move-construct into the variant.
<br>
<br>3. If all the other types have a nothrow move constructor and this type
<br>is not double-buffered (see below) then move-construct the old value
<br>into a local buffer, construct the new value in place, then destroy the
<br>local buffer. On exception, move the old value back.
<br>
<br>4. If at least 2 types are not nothrow-move-constructible then we need =
a
<br>double-buffer. The size of the buffer is set to big enough to cover all
<br>the types that are not nothrow-move-constructible. However, all types
<br>that fit are then counted as double-buffered. This avoids extra move
<br>constructions where possible, without imposing a space penalty beyond
<br>what is required.
<br>
<br>I think this is a reasonable trade-off. YMMV.
<br>
<br></blockquote><div><br>I see, if only one type is non nothrow move const=
ructible the trick that there is no scenario where it needs to replace itse=
lf. Cool. <br><br>Also heap allocation should left as an implementation opt=
ion instead of double buffering. No need for explicit allocation support th=
ough, if necessary variant could rely on the scoped_allocator_traits to get=
an allocator from the object being copied. Also standard libraries impleme=
ntations that are ok allocating on a container move (which is pretty much t=
he reason for throwing moves to exist) should have no issues in allocating =
on a variant assignment either, while other implementations won't be pe=
nalized=C2=A0 with having to support a variant with a broken invariant.<br>=
<br>std::variant should be either exception-safe variant (my preference) or=
have an explicit empty state. The special failed state is IMHO an abominat=
ion.<br><br>Possibly the variant-with-empty-state case could be spelled as =
std::optional<std::variant<....> > (which I believe was suggest=
ed else thread) and guarantee minimal space occupancy and freedom from allo=
cation. In fact it would be nice if optional<variant< > > was g=
uaranteed to be optimal (i.e. share the variant discriminant and optional f=
lag) in all cases.<br><br>-- <br>=C2=A0</div>
<p></p>
-- <br />
<br />
--- <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 />
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_450_1211018558.1443089536885--
------=_Part_449_1796007222.1443089536884--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 24 Sep 2015 10:06:12 -0700 (PDT)
Raw View
------=_Part_910_599143968.1443114372183
Content-Type: multipart/alternative;
boundary="----=_Part_911_1285788121.1443114372183"
------=_Part_911_1285788121.1443114372183
Content-Type: text/plain; charset=UTF-8
On 23 September 2015 at 17:06, Anthony Williams <antho...@gmail.com
<javascript:>> wrote:
> I've done some work on my variant implementation on bitbucket
>> (https://bitbucket.org/anthonyw/variant) to add the strong guarantee.
>>
>> It does this in a variety of ways, in order to minimize space.
>>
>> 1. If the type you are constructing has a nothrow constructor you are
>> trying to use, destroy old value then construct directly
>>
>> 2. If the type you are constructing has a nothrow move constructor, and
>> it is not double-buffered (see below) then construct locally and then
>> destroy old value, and move-construct into the variant.
>>
>> 3. If all the other types have a nothrow move constructor and this type
>> is not double-buffered (see below) then move-construct the old value
>> into a local buffer, construct the new value in place, then destroy the
>> local buffer. On exception, move the old value back.
>>
>> 4. If at least 2 types are not nothrow-move-constructible then we need a
>> double-buffer. The size of the buffer is set to big enough to cover all
>> the types that are not nothrow-move-constructible. However, all types
>> that fit are then counted as double-buffered. This avoids extra move
>> constructions where possible, without imposing a space penalty beyond
>> what is required.
>>
>> I think this is a reasonable trade-off. YMMV.
>
>
I like the general thrust of where you're going with this. I am a bit leery
of all of the extra move operations, since they assume that movement is
quick (which admittedly, it usually is, but not always). The most common
case of assignment into a live variant will be construction of a type via a
non-nothrow constructor against a type that is nothrow moveable. So most
people will get the construct/destruct/move variation.
Another downside is that construction happens before destruction.
Especially considering that construction happening before destruction is
not consistent. Admittedly, that's a limitation I'm perfectly willing to
accept. But it might lead to some subtle and surprising behavior, if users
are using RAII-scoping for things.
I find your description of #2 and #3 confusing. I understand what you're
getting at with them, but your description doesn't quite make sense.
Item #4 states that a particular type is double-buffered if all of these
are true:
A) The type does not have a nothrow move constructor.
B) The typelist contains at least 2 types total (including this one) that
do not have nothrow move constructors.
Given A and B, #2 and #3's prohibition against being a double-buffered type
seems unnecessary. #2 only applies in the event of a nothrow move
constructor. And #3 only applies if the type is the only type in the
typelist without a nothrow move constructor.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_911_1285788121.1443114372183
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 23 September 2015 at 17:06, Anthony Williams <span dir=
=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailt=
o=3D"PVlWYd-fBAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">antho...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex">I've done some work on my variant implementa=
tion on bitbucket<br>
(<a href=3D"https://bitbucket.org/anthonyw/variant" rel=3D"nofollow" target=
=3D"_blank" onmousedown=3D"this.href=3D'https://www.google.com/url?q\75=
https%3A%2F%2Fbitbucket.org%2Fanthonyw%2Fvariant\46sa\75D\46sntz\0751\46usg=
\75AFQjCNE8yBmc8elrYR3VAntb1yyKrbEdeA';return true;" onclick=3D"this.hr=
ef=3D'https://www.google.com/url?q\75https%3A%2F%2Fbitbucket.org%2Fanth=
onyw%2Fvariant\46sa\75D\46sntz\0751\46usg\75AFQjCNE8yBmc8elrYR3VAntb1yyKrbE=
deA';return true;">https://bitbucket.org/<wbr>anthonyw/variant</a>) to =
add the strong guarantee.<br>
<br>
It does this in a variety of ways, in order to minimize space.<br>
<br>
1. If the type you are constructing has a nothrow constructor you are<br>
trying to use, destroy old value then construct directly<br>
<br>
2. If the type you are constructing has a nothrow move constructor, and<br>
it is not double-buffered (see below) then construct locally and then<br>
destroy old value, and move-construct into the variant.<br>
<br>
3. If all the other types have a nothrow move constructor and this type<br>
is not double-buffered (see below) then move-construct the old value<br>
into a local buffer, construct the new value in place, then destroy the<br>
local buffer. On exception, move the old value back.<br>
<br>
4. If at least 2 types are not nothrow-move-constructible then we need a<br=
>
double-buffer. The size of the buffer is set to big enough to cover all<br>
the types that are not nothrow-move-constructible. However, all types<br>
that fit are then counted as double-buffered. This avoids extra move<br>
constructions where possible, without imposing a space penalty beyond<br>
what is required.<br>
<br>
I think this is a reasonable trade-off. YMMV.</blockquote></div></div></div=
></blockquote><div><br>I like the general thrust of where you're going =
with this. I am a bit leery of all of the extra move operations, since they=
assume that movement is quick (which admittedly, it usually is, but not al=
ways). The most common case of assignment into a live variant will be const=
ruction of a type via a non-nothrow constructor against a type that is noth=
row moveable. So most people will get the construct/destruct/move variation=
..<br><br>Another downside is that construction happens before destruction. =
Especially considering that construction happening before destruction is no=
t consistent. Admittedly, that's a limitation I'm perfectly willing=
to accept. But it might lead to some subtle and surprising behavior, if us=
ers are using RAII-scoping for things.<br><br>I find your description of #2=
and #3 confusing. I understand what you're getting at with them, but y=
our description doesn't quite make sense.<br><br>Item #4 states that a =
particular type is double-buffered if all of these are true:<br><br>A) The =
type does not have a nothrow move constructor.<br><br>B) The typelist conta=
ins at least 2 types total (including this one) that do not have nothrow mo=
ve constructors.<br><br>Given A and B, #2 and #3's prohibition against =
being a double-buffered type seems unnecessary. #2 only applies in the even=
t of a nothrow move constructor. And #3 only applies if the type is the onl=
y type in the typelist without a nothrow move constructor.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_911_1285788121.1443114372183--
------=_Part_910_599143968.1443114372183--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Thu, 24 Sep 2015 18:33:40 +0100
Raw View
On 24/09/15 18:06, Nicol Bolas wrote:
> On 23 September 2015 at 17:06, Anthony Williams <antho...@gmail.com
> <javascript:>> wrote:
>
> I've done some work on my variant implementation on bitbucket
> (https://bitbucket.org/anthonyw/variant
> <https://bitbucket.org/anthonyw/variant>) to add the strong
> guarantee.
>
> It does this in a variety of ways, in order to minimize space.
>
> 1. If the type you are constructing has a nothrow constructor
> you are
> trying to use, destroy old value then construct directly
>
> 2. If the type you are constructing has a nothrow move
> constructor, and
> it is not double-buffered (see below) then construct locally and
> then
> destroy old value, and move-construct into the variant.
>
> 3. If all the other types have a nothrow move constructor and
> this type
> is not double-buffered (see below) then move-construct the old value
> into a local buffer, construct the new value in place, then
> destroy the
> local buffer. On exception, move the old value back.
>
> 4. If at least 2 types are not nothrow-move-constructible then
> we need a
> double-buffer. The size of the buffer is set to big enough to
> cover all
> the types that are not nothrow-move-constructible. However, all
> types
> that fit are then counted as double-buffered. This avoids extra move
> constructions where possible, without imposing a space penalty
> beyond
> what is required.
>
> I think this is a reasonable trade-off. YMMV.
>
>
> I like the general thrust of where you're going with this. I am a bit
> leery of all of the extra move operations, since they assume that
> movement is quick (which admittedly, it usually is, but not always). The
> most common case of assignment into a live variant will be construction
> of a type via a non-nothrow constructor against a type that is nothrow
> moveable. So most people will get the construct/destruct/move variation.
The assumption is that nothrow-move is quick. If move is slow then it is
often really a copy, and often may throw.
I imagine that the most common case is actually people using variant
with built-ins and things like string and vector which have their own
nothrow move operations.
> Another downside is that construction happens before destruction.
> Especially considering that construction happening before destruction is
> not consistent. Admittedly, that's a limitation I'm perfectly willing to
> accept. But it might lead to some subtle and surprising behavior, if
> users are using RAII-scoping for things.
The strong guarantee requires construction of new before destruction of
old if construction can throw.
The surprising bit is that sometimes this doesn't happen.
> I find your description of #2 and #3 confusing. I understand what you're
> getting at with them, but your description doesn't quite make sense.
I'll elaborate a bit more then.
Double-buffering is enabled if there are at least 2 types without a
nothrow move constructor.
The buffer is then set big enough to cover the largest of those types
that are not nothrow move constructible.
The buffer is then used for any type that would fit in the buffer if you
are not using a nothrow constructor for it.
This avoids the extra moves if you've got the space, but doesn't double
the space if your largest objects have nothrow moves.
So, points 2 and 3 only apply if either double-buffering is disabled
because all or all-but-one types are nothrow-move-constructible, or the
type being constructed is too big to fit in the buffer.
e.g. variant<int, string, LargeWithNoThrowMove, MediumWithThrowingMove,
SmallWithThrowingMove> v(42);
sizeof(string)=8;
sizeof(int)=4;
sizeof(MediumWithThrowingMove)=16;
sizeof(SmallWithThrowingMove)=4;
sizeof(LargeWithNoThrowMove)=32;
MediumWithThrowingMove and SmallWithThrowingMove have a throwing move,
so we have double-buffering. The buffer will be big enough for
MediumWithThrowingMove, and thus big enough for all the other types
except LargeWithNoThrowMove.
Now we do:
v="hello";
std::string is small, but has a throwing constructor, so we use the buffer.
On the other hand, if we do:
LargeWithNoThrowMove x;
v=x;
Then we construct locally, and move in, as it won't fit in the buffer,
as per #2.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 24 Sep 2015 11:27:22 -0700 (PDT)
Raw View
------=_Part_744_141327053.1443119242613
Content-Type: multipart/alternative;
boundary="----=_Part_745_1918062448.1443119242614"
------=_Part_745_1918062448.1443119242614
Content-Type: text/plain; charset=UTF-8
On Thursday, September 24, 2015 at 1:33:45 PM UTC-4, Anthony Williams wrote:
>
> On 24/09/15 18:06, Nicol Bolas wrote:
> > On 23 September 2015 at 17:06, Anthony Williams <antho...@gmail.com
> > <javascript:>> wrote:
> >
> > I've done some work on my variant implementation on bitbucket
> > (https://bitbucket.org/anthonyw/variant
> > <https://bitbucket.org/anthonyw/variant>) to add the strong
> > guarantee.
> >
> > It does this in a variety of ways, in order to minimize space.
> >
> > 1. If the type you are constructing has a nothrow constructor
> > you are
> > trying to use, destroy old value then construct directly
> >
> > 2. If the type you are constructing has a nothrow move
> > constructor, and
> > it is not double-buffered (see below) then construct locally and
> > then
> > destroy old value, and move-construct into the variant.
> >
> > 3. If all the other types have a nothrow move constructor and
> > this type
> > is not double-buffered (see below) then move-construct the old
> value
> > into a local buffer, construct the new value in place, then
> > destroy the
> > local buffer. On exception, move the old value back.
> >
> > 4. If at least 2 types are not nothrow-move-constructible then
> > we need a
> > double-buffer. The size of the buffer is set to big enough to
> > cover all
> > the types that are not nothrow-move-constructible. However, all
> > types
> > that fit are then counted as double-buffered. This avoids extra
> move
> > constructions where possible, without imposing a space penalty
> > beyond
> > what is required.
> >
> > I think this is a reasonable trade-off. YMMV.
> >
> >
> > I like the general thrust of where you're going with this. I am a bit
> > leery of all of the extra move operations, since they assume that
> > movement is quick (which admittedly, it usually is, but not always). The
> > most common case of assignment into a live variant will be construction
> > of a type via a non-nothrow constructor against a type that is nothrow
> > moveable. So most people will get the construct/destruct/move variation.
>
> The assumption is that nothrow-move is quick. If move is slow then it is
> often really a copy, and often may throw.
>
Well, fast and slow are relative. Think about unqiue_ptr. It's move
operation is conceptually fast. But it is also *two* operations: a memcpy
followed by setting the previous value to nullptr. The latter is necessary
because you also have to call the destructor. So the cost of the move is
quite high, relatively speaking.
Basically, my point is that without destructive move (or whatever we're
calling it these days), each extra move can be a lot more costly than it
would be with that feature.
That's not to say that your idea is bad or wrong. Only that this will be
one of the sources of push-back against it. N4542 has the advantage that it
is always as fast as it is possible to be.
> The strong guarantee requires construction of new before destruction of
> old if construction can throw.
>
> The surprising bit is that sometimes this doesn't happen.
Well, you could take out case #1 and thus make it always happen. Sure,
you'll lose performance for emplacement operations that use non-throwing
constructors. But is that an occurrence that is common enough to justify
this behavioral variance?
> I find your description of #2 and #3 confusing. I understand what you're
> > getting at with them, but your description doesn't quite make sense.
>
> I'll elaborate a bit more then.
>
> Double-buffering is enabled if there are at least 2 types without a
> nothrow move constructor.
>
> The buffer is then set big enough to cover the largest of those types
> that are not nothrow move constructible.
>
> The buffer is then used for any type that would fit in the buffer if you
> are not using a nothrow constructor for it.
>
> This avoids the extra moves if you've got the space, but doesn't double
> the space if your largest objects have nothrow moves.
>
> So, points 2 and 3 only apply if either double-buffering is disabled
> because all or all-but-one types are nothrow-move-constructible, or the
> type being constructed is too big to fit in the buffer.
>
> e.g. variant<int, string, LargeWithNoThrowMove, MediumWithThrowingMove,
> SmallWithThrowingMove> v(42);
>
> sizeof(string)=8;
> sizeof(int)=4;
> sizeof(MediumWithThrowingMove)=16;
> sizeof(SmallWithThrowingMove)=4;
> sizeof(LargeWithNoThrowMove)=32;
>
> MediumWithThrowingMove and SmallWithThrowingMove have a throwing move,
> so we have double-buffering. The buffer will be big enough for
> MediumWithThrowingMove, and thus big enough for all the other types
> except LargeWithNoThrowMove.
>
So as I understand it, sizeof(variant<...>) will therefore be (ignoring
alignment) 48 plus the index. That's 32 for the main storage (enough to
store `LargeWithNoThrowMove`), and 16 for the double-buffer.
Now we do:
>
> v="hello";
>
> std::string is small, but has a throwing constructor, so we use the buffer.
>
When you say "use the buffer", do you mean that you construct the
`std::string` into the extra 16 bytes of space, destroy the original value,
and then move it over (and call the destructor on the buffer space)?
That all sounds doable. You're effectively defining the minimal overhead
implementations can achieve for the following behaviors:
1) No empty or invalid state.
2) Strong exception guarantee.
3) No gimping of functionality (ie: not taking away operations just because
they're nothrow).
The biggest opposition will be from those who *really* care about the
"minimal overhead" cost: size and performance.
I don't know how standardizable what I'm about to suggest would be. But one
way to help alleviate those concerns would be to add a constexpr static
member that will be true if the variant has no double buffer. That way, if
a user wants to avoid accidentally doing something that causes more variant
overhead, they can static_assert on it.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_745_1918062448.1443119242614
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, September 24, 2015 at 1:33:45 PM UTC-4, Anthony Williams wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">On 24/09/15 18:06, Nicol Bola=
s wrote:
<br>> On 23 September 2015 at 17:06, Anthony Williams <<a>antho...@gm=
ail.com</a>
<br>> <javascript:>> wrote:
<br>>=20
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 I've done some work on my variant =
implementation on bitbucket
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 (<a href=3D"https://bitbucket.org/anth=
onyw/variant" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'https://www.google.com/url?q\75https%3A%2F%2Fbitbucket.org%2Fanthon=
yw%2Fvariant\46sa\75D\46sntz\0751\46usg\75AFQjCNE8yBmc8elrYR3VAntb1yyKrbEde=
A';return true;" onclick=3D"this.href=3D'https://www.google.com/url=
?q\75https%3A%2F%2Fbitbucket.org%2Fanthonyw%2Fvariant\46sa\75D\46sntz\0751\=
46usg\75AFQjCNE8yBmc8elrYR3VAntb1yyKrbEdeA';return true;">https://bitbu=
cket.org/<wbr>anthonyw/variant</a>
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 <<a href=3D"https://bitbucket.org/a=
nthonyw/variant" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'https://www.google.com/url?q\75https%3A%2F%2Fbitbucket.org%2Fantho=
nyw%2Fvariant\46sa\75D\46sntz\0751\46usg\75AFQjCNE8yBmc8elrYR3VAntb1yyKrbEd=
eA';return true;" onclick=3D"this.href=3D'https://www.google.com/ur=
l?q\75https%3A%2F%2Fbitbucket.org%2Fanthonyw%2Fvariant\46sa\75D\46sntz\0751=
\46usg\75AFQjCNE8yBmc8elrYR3VAntb1yyKrbEdeA';return true;">https://bitb=
ucket.org/<wbr>anthonyw/variant</a>>) to add the strong
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 guarantee.
<br>>=20
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 It does this in a variety of ways, in =
order to minimize space.
<br>>=20
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 1. If the type you are constructing ha=
s a nothrow constructor
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 you are
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 trying to use, destroy old value then =
construct directly
<br>>=20
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 2. If the type you are constructing ha=
s a nothrow move
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 constructor, and
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 it is not double-buffered (see below) =
then construct locally and
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 then
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 destroy old value, and move-construct =
into the variant.
<br>>=20
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 3. If all the other types have a nothr=
ow move constructor and
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 this type
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 is not double-buffered (see below) the=
n move-construct the old value
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 into a local buffer, construct the new=
value in place, then
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 destroy the
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 local buffer. On exception, move the o=
ld value back.
<br>>=20
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 4. If at least 2 types are not nothrow=
-move-constructible then
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 we need a
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 double-buffer. The size of the buffer =
is set to big enough to
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 cover all
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 the types that are not nothrow-move-co=
nstructible. However, all
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 types
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 that fit are then counted as double-bu=
ffered. This avoids extra move
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 constructions where possible, without =
imposing a space penalty
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 beyond
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 what is required.
<br>>=20
<br>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 I think this is a reasonable trade-off=
.. YMMV.
<br>>=20
<br>>=20
<br>> I like the general thrust of where you're going with this. I a=
m a bit
<br>> leery of all of the extra move operations, since they assume that
<br>> movement is quick (which admittedly, it usually is, but not always=
). The
<br>> most common case of assignment into a live variant will be constru=
ction
<br>> of a type via a non-nothrow constructor against a type that is not=
hrow
<br>> moveable. So most people will get the construct/destruct/move vari=
ation.
<br>
<br>The assumption is that nothrow-move is quick. If move is slow then it i=
s
<br>often really a copy, and often may throw.
<br></blockquote><div><br>Well, fast and slow are relative. Think about unq=
iue_ptr. It's move operation is conceptually fast. But it is also <i>tw=
o</i> operations: a memcpy followed by setting the previous value to nullpt=
r. The latter is necessary because you also have to call the destructor. So=
the cost of the move is quite high, relatively speaking.<br><br>Basically,=
my point is that without destructive move (or whatever we're calling i=
t these days), each extra move can be a lot more costly than it would be wi=
th that feature.<br><br>That's not to say that your idea is bad or wron=
g. Only that this will be one of the sources of push-back against it. N4542=
has the advantage that it is always as fast as it is possible to be.<br>=
=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1p=
x solid rgb(204, 204, 204); padding-left: 1ex;" class=3D"gmail_quote">The s=
trong guarantee requires construction of new before destruction of
<br>old if construction can throw.
<br>
<br>The surprising bit is that sometimes this doesn't happen.
</blockquote><div><br>Well, you could take out case #1 and thus make it alw=
ays happen. Sure, you'll lose performance for emplacement operations th=
at use non-throwing constructors. But is that an occurrence that is common =
enough to justify this behavioral variance?<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">
> I find your description of #2 and #3 confusing. I understand what you&=
#39;re
<br>> getting at with them, but your description doesn't quite make =
sense.
<br>
<br>I'll elaborate a bit more then.
<br>
<br>Double-buffering is enabled if there are at least 2 types without a
<br>nothrow move constructor.
<br>
<br>The buffer is then set big enough to cover the largest of those types
<br>that are not nothrow move constructible.
<br>
<br>The buffer is then used for any type that would fit in the buffer if yo=
u
<br>are not using a nothrow constructor for it.
<br>
<br>This avoids the extra moves if you've got the space, but doesn'=
t double
<br>the space if your largest objects have nothrow moves.
<br>
<br>So, points 2 and 3 only apply if either double-buffering is disabled
<br>because all or all-but-one types are nothrow-move-constructible, or the
<br>type being constructed is too big to fit in the buffer.
<br>
<br>e.g. variant<int, string, LargeWithNoThrowMove, MediumWithThrowingMo=
ve,
<br>SmallWithThrowingMove> v(42);
<br>
<br>sizeof(string)=3D8;
<br>sizeof(int)=3D4;
<br>sizeof(MediumWithThrowingMove)<wbr>=3D16;
<br>sizeof(SmallWithThrowingMove)=3D<wbr>4;
<br>sizeof(LargeWithNoThrowMove)=3D<wbr>32;
<br>
<br>MediumWithThrowingMove and SmallWithThrowingMove have a throwing move,
<br>so we have double-buffering. The buffer will be big enough for
<br>MediumWithThrowingMove, and thus big enough for all the other types
<br>except LargeWithNoThrowMove.<br></blockquote><div><br>So as I understan=
d it, sizeof(variant<...>) will therefore be (ignoring alignment) 48 =
plus the index. That's 32 for the main storage (enough to store `LargeW=
ithNoThrowMove`), and 16 for the double-buffer.<br><br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;">
Now we do:
<br>
<br>v=3D"hello";
<br>
<br>std::string is small, but has a throwing constructor, so we use the buf=
fer.<br></blockquote><div><br>When you say "use the buffer", do y=
ou mean that you construct the `std::string` into the extra 16 bytes of spa=
ce, destroy the original value, and then move it over (and call the destruc=
tor on the buffer space)?</div><br>That all sounds doable. You're effec=
tively defining the minimal overhead implementations can achieve for the fo=
llowing behaviors:<br><br>1) No empty or invalid state.<br><br>2) Strong ex=
ception guarantee.<br><br>3) No gimping of functionality (ie: not taking aw=
ay operations just because they're nothrow).<br><br>The biggest opposit=
ion will be from those who <i>really</i> care about the "minimal overh=
ead" cost: size and performance.<br><br>I don't know how standardi=
zable what I'm about to suggest would be. But one way to help alleviate=
those concerns would be to add a constexpr static member that will be true=
if the variant has no double buffer. That way, if a user wants to avoid ac=
cidentally doing something that causes more variant overhead, they can stat=
ic_assert on it.<br>
<p></p>
-- <br />
<br />
--- <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 />
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_745_1918062448.1443119242614--
------=_Part_744_141327053.1443119242613--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 24 Sep 2015 14:16:12 -0500
Raw View
--001a11415d1cd6eaaa0520831251
Content-Type: text/plain; charset=UTF-8
On 24 September 2015 at 13:27, Nicol Bolas <jmckesson@gmail.com> wrote:
> That's not to say that your idea is bad or wrong. Only that this will be
> one of the sources of push-back against it. N4542 has the advantage that it
> is always as fast as it is possible to be.
>
Not true. Specifically:
"Specific care was taken in the copy-assignment operator and copy
constructor to reduce the likelihood of the variant ending up in an invalid
state: whenever possible, they will first create a temporary, and only
destruct the contained type if this temporary construction did not throw.
The variant will thus only end up in an invalid state if the move
constructor throws (which is far less likely even if they are
noexcept(false)), or if the alternative cannot be move constructed."
In some sense, N4542 is worse. N4542 does construct-then-move to reduce
the likelihood (but not eliminate) of entering the invalid state; the
Williams variant only does the extra move if that eliminates the need for
double buffering.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11415d1cd6eaaa0520831251
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra">On 24 September 2015 at 13:27, =
Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" ta=
rget=3D"_blank">jmckesson@gmail.com</a>></span> wrote:<br><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>That's not to say that your idea is =
bad or wrong. Only that this will be one of the sources of push-back agains=
t it. N4542 has the advantage that it is always as fast as it is possible t=
o be.<br></div></blockquote></div><br>Not true.=C2=A0 Specifically:</div><d=
iv class=3D"gmail_extra">
=09
=09
=09
<div class=3D"" title=3D"Page 16">
<div class=3D"">
<div class=3D"">
<p><span style=3D"font-size:10pt;font-family:LMRoman10">"Specific=
care was taken in the copy-assignment operator and copy constructor
to reduce the likelihood of the variant ending up in an invalid state: when=
ever
possible, they will first create a temporary, and only destruct the contain=
ed type
if this temporary construction did not throw. The variant will thus only en=
d up
in an invalid state if the move constructor throws (which is far less likel=
y even if
they are </span><span style=3D"font-size:10pt;font-family:LMMono10">noexcep=
t(false)</span><span style=3D"font-size:10pt;font-family:LMRoman10">), or i=
f the alternative cannot be move constructed."=C2=A0</span></p>
</div>
</div>
</div><div class=3D"gmail_extra">In some sense, N4542 is worse.=C2=A0 N45=
42 does construct-then-move to reduce the likelihood (but not eliminate) of=
entering the invalid state; the Williams variant only does the extra move =
if that eliminates the need for double buffering.</div><div class=3D"gmail_=
extra"><div class=3D"" title=3D"Page 16"><div class=3D""><div class=3D""></=
div></div></div></div><div><br></div>-- <br><div class=3D"gmail_signature">=
=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@=
eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (8=
47) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11415d1cd6eaaa0520831251--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 24 Sep 2015 14:22:56 -0500
Raw View
--001a1142f7ece1e8580520832a9b
Content-Type: text/plain; charset=UTF-8
>
> On 23 September 2015 at 17:06, Anthony Williams <anthony.ajw@gmail.com>
> wrote:
>
>> I've done some work on my variant implementation on bitbucket
>> (https://bitbucket.org/anthonyw/variant) to add the strong guarantee.
>>
>> 1. If the type you are constructing has a nothrow constructor you are
>> trying to use, destroy old value then construct directly
>>
>> 2. If the type you are constructing has a nothrow move constructor, and
>> it is not double-buffered (see below) then construct locally and then
>> destroy old value, and move-construct into the variant.
>>
>> 3. If all the other types have a nothrow move constructor and this type
>> is not double-buffered (see below) then move-construct the old value
>> into a local buffer, construct the new value in place, then destroy the
>> local buffer. On exception, move the old value back.
>>
>> 4. If at least 2 types are not nothrow-move-constructible then we need a
>> double-buffer. The size of the buffer is set to big enough to cover all
>> the types that are not nothrow-move-constructible. However, all types
>> that fit are then counted as double-buffered. This avoids extra move
>> constructions where possible, without imposing a space penalty beyond
>> what is required.
>
>
Have you thought about using a nothrow default constructible type (if and
only if at least one is in the type list) instead of double buffering?
Pro: it makes an easy way to guarantee there is no double buffering.
Con: it makes it harder to specify what *type* the variant is holding when
an exception is thrown. Note: we still cannot specify what *value* the
variant is holding if an exception is thrown, because you may get a
different outcome whether the assignment is changing the engaged type or
not.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1142f7ece1e8580520832a9b
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"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On 23 Septembe=
r 2015 at 17:06, Anthony Williams <span dir=3D"ltr"><<a href=3D"mailto:a=
nthony.ajw@gmail.com" target=3D"_blank">anthony.ajw@gmail.com</a>></span=
> wrote:<br></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><s=
pan class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex">I've done some work on my=
variant implementation on bitbucket<br>
(<a href=3D"https://bitbucket.org/anthonyw/variant" rel=3D"noreferrer" targ=
et=3D"_blank">https://bitbucket.org/anthonyw/variant</a>) to add the strong=
guarantee.<br>
<br>1. If the type you are constructing has a nothrow constructor you are<b=
r>
trying to use, destroy old value then construct directly<br>
<br>
2. If the type you are constructing has a nothrow move constructor, and<br>
it is not double-buffered (see below) then construct locally and then<br>
destroy old value, and move-construct into the variant.<br>
<br>
3. If all the other types have a nothrow move constructor and this type<br>
is not double-buffered (see below) then move-construct the old value<br>
into a local buffer, construct the new value in place, then destroy the<br>
local buffer. On exception, move the old value back.<br>
<br>
4. If at least 2 types are not nothrow-move-constructible then we need a<br=
>
double-buffer. The size of the buffer is set to big enough to cover all<br>
the types that are not nothrow-move-constructible. However, all types<br>
that fit are then counted as double-buffered. This avoids extra move<br>
constructions where possible, without imposing a space penalty beyond<br>
what is required.</blockquote></span></div></div></div></blockquote><div><b=
r></div><div>Have you thought about using a nothrow default constructible t=
ype (if and only if at least one is in the type list) instead of double buf=
fering?</div><div><br></div><div>Pro: =C2=A0it makes an easy way to guarant=
ee there is no double buffering.</div><div>=C2=A0<br></div><div>Con: it mak=
es it harder to specify what <i>type</i> the variant is holding when an exc=
eption is thrown.=C2=A0 Note: =C2=A0we still cannot specify what <i>value</=
i> the variant is holding if an exception is thrown, because you may get a =
different outcome whether the assignment is changing the engaged type or no=
t.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin ":-)&q=
uot; Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" targe=
t=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1142f7ece1e8580520832a9b--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Thu, 24 Sep 2015 20:39:58 +0100
Raw View
--001a1138098e7c4aff05208365d1
Content-Type: text/plain; charset=UTF-8
On 24 Sep 2015 8:23 pm, "Nevin Liber" <nevin@eviloverlord.com> wrote:
>
>
> Have you thought about using a nothrow default constructible type (if and
only if at least one is in the type list) instead of double buffering?
Yes, and I don't like that option.
> Pro: it makes an easy way to guarantee there is no double buffering.
>
> Con: it makes it harder to specify what type the variant is holding when
an exception is thrown. Note: we still cannot specify what value the
variant is holding if an exception is thrown, because you may get a
different outcome whether the assignment is changing the engaged type or
not.
Specifically, if you have a variant<A,B,C> holding a B, and you assign a
C, you might end up with an A. That's a bizarre case of the basic guarantee.
I find that unacceptable, except for the specific case that A is a special
empty_variant/error_state marker type.
Anthony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1138098e7c4aff05208365d1
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<p dir=3D"ltr"><br>
On 24 Sep 2015 8:23 pm, "Nevin Liber" <<a href=3D"mailto:nevin=
@eviloverlord.com">nevin@eviloverlord.com</a>> wrote:</p>
<p dir=3D"ltr">><br>
><br>
> Have you thought about using a nothrow default constructible type (if =
and only if at least one is in the type list) instead of double buffering?<=
/p>
<p dir=3D"ltr">Yes, and I don't like that option.</p>
<p dir=3D"ltr">> Pro: =C2=A0it makes an easy way to guarantee there is n=
o double buffering.<br>
> =C2=A0<br>
> Con: it makes it harder to specify what type the variant is holding wh=
en an exception is thrown.=C2=A0 Note: =C2=A0we still cannot specify what v=
alue the variant is holding if an exception is thrown, because you may get =
a different outcome whether the assignment is changing the engaged type or =
not.</p>
<p dir=3D"ltr">Specifically,=C2=A0 if you have a variant<A,B,C> holdi=
ng a B, and you assign a C, you might end up with an A. That's a bizarr=
e case of the basic guarantee.</p>
<p dir=3D"ltr">I find that unacceptable, except for the specific case that =
A is a special empty_variant/error_state marker type.</p>
<p dir=3D"ltr">Anthony</p>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--001a1138098e7c4aff05208365d1--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 24 Sep 2015 14:48:00 -0500
Raw View
--001a113d9f7a888d73052083847d
Content-Type: text/plain; charset=UTF-8
On 23 September 2015 at 19:54, Nicol Bolas <jmckesson@gmail.com> wrote:
> You mean, besides the fact that a wrapper type fabricating an operation
> that is illegal on the contents makes no sense? You are basically saying
> that, if T is not move assignable, `optional<T>`, which is a
> value-type-wrapper for T, should *create* a move assignment operator
> where possible.
>
> That's *completely insane*.
>
It's also a maintenance nightmare, because it relies on a non-obvious class
property.
Many people (including myself) believe in the Rule Of Zero; ie, don't
declare copy/move constructor/assignment or destructor unless you
absolutely must.
Let's take the following set of user classes, none of which have any of the
Big Five user declared:
class A
{
B b;
C c;
D d;
public:
/* ... */
};
class D
{
E e;
F f;
calabrese::variant<G, H, I> ghi;
public:
/* ... */
};
class H
{
J j;
K k;
L l;
public:
/* ... */
};
class L
{
M m;
N n;
vector<O> vo;
public:
/* ... */
};
And in the code I've got this kind of thing all over the place:
void Foo(A& a1, A const& a2)
{
/* ... */
a1 = a2;
/* ... */
}
Assume all compiles today.
Now, for other reasons L has to change to:
class L
{
M m;
N n;
deque<O> vo;
public:
/* ... */
};
And all of a sudden Foo no longer compiles. What's the fix?
The easiest fix I can think of is to use boost::variant. Everything else
involves either lying (have L declare its move constructor noexcept(true))
or lots of painful code changes.
If those are the fixes I'd have to recommend, then I'd have to vote
strongly against calabrese::variant.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113d9f7a888d73052083847d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On 23 September 2015 at 19:54, Nicol Bolas <span dir=3D"ltr"><<a href=3D=
"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>><=
/span> wrote:<br><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-l=
eft-style:solid;padding-left:1ex"><div>You mean, besides the fact that a wr=
apper type fabricating an operation that is illegal on the contents makes n=
o sense? You are basically saying that, if T is not move assignable, `optio=
nal<T>`, which is a value-type-wrapper for T, should <i>create</i> a =
move assignment operator where possible.<br><br>That's <i>completely <s=
pan class=3D"">insane</span></i>.<br></div><span class=3D""></span></blockq=
uote></div><br>It's also a maintenance nightmare, because it relies on =
a non-obvious class property.</div><div class=3D"gmail_extra"><br></div><di=
v class=3D"gmail_extra">Many people (including myself) believe in the Rule =
Of Zero; ie, don't declare copy/move constructor/assignment or destruct=
or unless you absolutely must.</div><div class=3D"gmail_extra"><br></div><d=
iv class=3D"gmail_extra">Let's take the following set of user classes, =
none of which have any of the Big Five user declared:</div><div class=3D"gm=
ail_extra"><br></div><div class=3D"gmail_extra"><div class=3D"gmail_extra">=
class A</div><div class=3D"gmail_extra">{</div><div class=3D"gmail_extra">=
=C2=A0 =C2=A0 B b;</div><div class=3D"gmail_extra">=C2=A0 =C2=A0 C c;</div>=
<div class=3D"gmail_extra">=C2=A0 =C2=A0 D d;</div><div class=3D"gmail_extr=
a">public:</div><div class=3D"gmail_extra">=C2=A0 =C2=A0 /* ... */</div><di=
v class=3D"gmail_extra">};</div><div class=3D"gmail_extra"><br><div class=
=3D"gmail_extra">class D</div><div class=3D"gmail_extra">{</div><div class=
=3D"gmail_extra">=C2=A0 =C2=A0 E e;</div><div class=3D"gmail_extra">=C2=A0 =
=C2=A0 F f;</div><div class=3D"gmail_extra">=C2=A0 =C2=A0 calabrese::varian=
t<G, H, I> ghi;</div><div class=3D"gmail_extra">public:<br></div><div=
class=3D"gmail_extra">=C2=A0 =C2=A0 /* ... */</div><div class=3D"gmail_ext=
ra">};</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra"=
>class H</div><div class=3D"gmail_extra">{</div><div class=3D"gmail_extra">=
=C2=A0 =C2=A0 J j;</div><div class=3D"gmail_extra">=C2=A0 =C2=A0 K k;</div>=
<div class=3D"gmail_extra">=C2=A0 =C2=A0 L l;</div><div class=3D"gmail_extr=
a">public:<br></div><div class=3D"gmail_extra">=C2=A0 =C2=A0 /* ... */</div=
><div class=3D"gmail_extra">};</div><div class=3D"gmail_extra"><br></div><d=
iv class=3D"gmail_extra">class L</div><div class=3D"gmail_extra">{</div><di=
v class=3D"gmail_extra">=C2=A0 =C2=A0 M m;</div><div class=3D"gmail_extra">=
=C2=A0 =C2=A0 N n;</div><div class=3D"gmail_extra">=C2=A0 =C2=A0 vector<=
O> vo;</div><div class=3D"gmail_extra">public:<br></div><div class=3D"gm=
ail_extra">=C2=A0 =C2=A0 /* ... */</div><div class=3D"gmail_extra">};</div>=
<div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">And in the =
code I've got this kind of thing all over the place:</div><div class=3D=
"gmail_extra"><br></div><div class=3D"gmail_extra">void Foo(A& a1, A co=
nst& a2)</div><div class=3D"gmail_extra">{</div><div class=3D"gmail_ext=
ra"><div class=3D"gmail_extra">=C2=A0 =C2=A0 /* ... */</div></div><div clas=
s=3D"gmail_extra">=C2=A0 =C2=A0 a1 =3D a2;</div><div class=3D"gmail_extra">=
=C2=A0 =C2=A0 /* ... */</div><div class=3D"gmail_extra">}</div><div class=
=3D"gmail_extra"><br></div><div class=3D"gmail_extra">Assume all compiles t=
oday.</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">=
<br></div><div class=3D"gmail_extra">Now, for other reasons L has to change=
to:</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra"><=
div class=3D"gmail_extra">class L</div><div class=3D"gmail_extra">{</div><d=
iv class=3D"gmail_extra">=C2=A0 =C2=A0 M m;</div><div class=3D"gmail_extra"=
>=C2=A0 =C2=A0 N n;</div><div class=3D"gmail_extra">=C2=A0 =C2=A0 deque<=
O> vo;</div><div class=3D"gmail_extra">public:<br></div><div class=3D"gm=
ail_extra">=C2=A0 =C2=A0 /* ... */</div><div class=3D"gmail_extra">};</div>=
<div><br></div></div><div class=3D"gmail_extra">And all of a sudden Foo no =
longer compiles.=C2=A0 What's the fix?</div><div class=3D"gmail_extra">=
<br></div><div class=3D"gmail_extra">The easiest fix I can think of is to u=
se boost::variant.=C2=A0 Everything else involves either lying (have L decl=
are its move constructor noexcept(true)) or lots of painful code changes.</=
div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">If thos=
e are the fixes I'd have to recommend, then I'd have to vote strong=
ly against calabrese::variant.</div><div class=3D"gmail_extra">--=C2=A0<br>=
</div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_signature"=
>=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin=
@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (=
847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113d9f7a888d73052083847d--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 24 Sep 2015 15:24:16 -0500
Raw View
--001a114363ac3c1e55052084061b
Content-Type: text/plain; charset=UTF-8
On 24 September 2015 at 02:17, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Wed, Sep 23, 2015 at 11:40 PM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
>>
>> If your variant<T...> has no assignment operator, how exactly does
>> optional<variant<T...>> magically get one??
>>
>> The only thing I can think of is that optional synthesizes an assignment
>> operator by "if (engaged) { if (!selfAssign) destroy; construct; }" instead
>> of the current "if (engaged) assign; else construct;" (or do you only want
>> to do that for types that are not assignable?), but I would find an
>> optional which did that quite surprising.
>>
>
> Precisely this (well, slightly more complicated if you address
> self-assignment). You would *only *do it in this way if the type is
> move-constructible and yet not move-assignable, which is an exceedingly
> rare class of types
>
Should all wrappers (pair, tuple, etc.) do this as well? Part of what the
committee does is try and make sure that everything fits together with some
sort of uniformity/regularity.
(Note: these are orthogonal questions to what conditions variant should or
should not have an assignment operator.)
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a114363ac3c1e55052084061b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 24 September 2015 at 02:17, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><div clas=
s=3D"gmail_extra"><div class=3D"gmail_quote">On Wed, Sep 23, 2015 at 11:40 =
PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"mailto:nevin@eviloverlord.=
com" target=3D"_blank">nevin@eviloverlord.com</a>></span> wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_qu=
ote"><div>If your variant<T...> has no assignment operator, how exact=
ly does optional<variant<T...>> magically get one??</div><div><=
br></div><div>The only thing I can think of is that optional synthesizes an=
assignment operator by "if (engaged) { if (!selfAssign) destroy; cons=
truct; }" instead of the current "if (engaged) assign; else const=
ruct;" (or do you only want to do that for types that are not assignab=
le?), but I would find an optional which did that quite surprising.</div></=
div></div></div></blockquote></div><br></div></span><div class=3D"gmail_ext=
ra">Precisely this (well, slightly more complicated if you address self-ass=
ignment). You would <i>only=C2=A0</i>do it in this way if the type is move-=
constructible and yet not move-assignable, which is an exceedingly rare cla=
ss of types</div></div></blockquote><div><br></div><div>Should all wrappers=
(pair, tuple, etc.) do this as well?=C2=A0 Part of what the committee does=
is try and make sure that everything fits together with some sort of unifo=
rmity/regularity.</div><div><br></div><div>(Note: these are orthogonal ques=
tions to what conditions variant should or should not have an assignment op=
erator.)</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin "=
;:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com"=
target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div=
>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a114363ac3c1e55052084061b--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Thu, 24 Sep 2015 13:45:27 -0700 (PDT)
Raw View
------=_Part_952_439415156.1443127528038
Content-Type: multipart/alternative;
boundary="----=_Part_953_212709212.1443127528038"
------=_Part_953_212709212.1443127528038
Content-Type: text/plain; charset=UTF-8
On Thursday, September 24, 2015 at 9:24:58 PM UTC+1, Nevin ":-)" Liber
wrote:
>
> On 24 September 2015 at 02:17, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-pr...@isocpp.org <javascript:>> wrote:
>
>> On Wed, Sep 23, 2015 at 11:40 PM, Nevin Liber <ne...@eviloverlord.com
>> <javascript:>> wrote:
>>>
>>> If your variant<T...> has no assignment operator, how exactly does
>>> optional<variant<T...>> magically get one??
>>>
>>> The only thing I can think of is that optional synthesizes an assignment
>>> operator by "if (engaged) { if (!selfAssign) destroy; construct; }" instead
>>> of the current "if (engaged) assign; else construct;" (or do you only want
>>> to do that for types that are not assignable?), but I would find an
>>> optional which did that quite surprising.
>>>
>>
>> Precisely this (well, slightly more complicated if you address
>> self-assignment). You would *only *do it in this way if the type is
>> move-constructible and yet not move-assignable, which is an exceedingly
>> rare class of types
>>
>
> Should all wrappers (pair, tuple, etc.) do this as well? Part of what the
> committee does is try and make sure that everything fits together with some
> sort of uniformity/regularity.
>
>
FWIW, in the past I've used boost::optional as a RegularType wrapper for
copy-constructible but not assignable types (one example is Boost.Lambda;
more generally any type which contains reference members), so I've found
the additional default constructor plus destroy+construct assignment
operator quite useful.
-- gpd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_953_212709212.1443127528038
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, September 24, 2015 at 9:24:58 PM UTC+1, Nevin ":-)" =
Liber wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">O=
n 24 September 2015 at 02:17, 'Matt Calabrese' via ISO C++ Standard=
- Future Proposals <span dir=3D"ltr"><<a href=3D"javascript:" target=3D=
"_blank" gdf-obfuscated-mailto=3D"yZaVEo6ICAAJ" rel=3D"nofollow" onmousedow=
n=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=
=3D'javascript:';return true;">std-pr...@isocpp.org</a>></span> =
wrote:<br><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><span><div><div class=3D"gmail_quote">On Wed, Sep 23, 2015 a=
t 11:40 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"javascript:" targe=
t=3D"_blank" gdf-obfuscated-mailto=3D"yZaVEo6ICAAJ" rel=3D"nofollow" onmous=
edown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hr=
ef=3D'javascript:';return true;">ne...@eviloverlord.com</a>></sp=
an> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"=
><div>If your variant<T...> has no assignment operator, how exactly d=
oes optional<variant<T...>> magically get one??</div><div><br><=
/div><div>The only thing I can think of is that optional synthesizes an ass=
ignment operator by "if (engaged) { if (!selfAssign) destroy; construc=
t; }" instead of the current "if (engaged) assign; else construct=
;" (or do you only want to do that for types that are not assignable?)=
, but I would find an optional which did that quite surprising.</div></div>=
</div></div></blockquote></div><br></div></span><div>Precisely this (well, =
slightly more complicated if you address self-assignment). You would <i>onl=
y=C2=A0</i>do it in this way if the type is move-constructible and yet not =
move-assignable, which is an exceedingly rare class of types</div></div></b=
lockquote><div><br></div><div>Should all wrappers (pair, tuple, etc.) do th=
is as well?=C2=A0 Part of what the committee does is try and make sure that=
everything fits together with some sort of uniformity/regularity.</div><di=
v><br></div></div></div></div></blockquote><div><br>FWIW, in the past I'=
;ve used boost::optional as a RegularType wrapper for copy-constructible bu=
t not assignable types (one example is Boost.Lambda; more generally any typ=
e which contains reference members), so I've found the additional defau=
lt constructor plus destroy+construct assignment operator quite useful. <br=
><br>-- gpd<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_953_212709212.1443127528038--
------=_Part_952_439415156.1443127528038--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 14:39:41 -0700
Raw View
--94eb2c0961c4a3bd55052085117a
Content-Type: text/plain; charset=UTF-8
On Thu, Sep 24, 2015 at 12:48 PM, Nevin Liber <nevin@eviloverlord.com>
wrote:
>
> And in the code I've got this kind of thing all over the place:
>
> void Foo(A& a1, A const& a2)
> {
> /* ... */
> a1 = a2;
> /* ... */
> }
>
> Assume all compiles today.
>
>
> Now, for other reasons L has to change to:
>
> class L
> {
> M m;
> N n;
> deque<O> vo;
> public:
> /* ... */
> };
>
> And all of a sudden Foo no longer compiles. What's the fix?
>
IIUC, other than that you'd probably need to update higher-level code, as
you've introduced a new path for failure by way of exception (which is much
more subtle to fix as there frequently are no compile errors), you'd just
make ghi optional and update the internal direct uses. If you find that
totally unpalatable, and I think you're overestimating the effort,
subtlety, and frequency of this happening, Michael Park's paper mentions an
option for a separate nullable_variant template. In my personal view, which
differs from his suggestion in the details, if such a template existed at
all it would just be a convenience wrapper around optional<variant<T...>>,
providing a more flattened interface (I.E. a little more similar to a
variant with an intrinsic invalid state, only even though the interface is
more flat, you'd still have access to the underlying never-empty
abstraction, which you could pass around/deal with locally when you do not
deal with "invalid"). I don't personally advocate this as I think such an
approach is unnecessary, and the flattened nature reintroduces more
complicated contracts, but it certainly seems to be a better solution than
always forcing someone to deal with a variant that can be invalid. I don't
want users to be adding preconditions to all of their functions dealing
with variants and asserting whenever receiving one that a given variant is
"valid," as people similarly need to do with reference types in certain
other mainstream languages whenever writing a function that doesn't deal
with null. Working with user-defined objects and references in C++ is
generally easier to reason about and do correctly because you often know by
the very nature of referring to a constructed instance of the type that it
is "valid." Whenever you can keep such states separate, which you genuinely
can here, it's beneficial to do so. Use the type system to properly handle
it. Of all of the design aspects of a variant type, I feel the never-empty
guarantee is perhaps the most important, since introducing "invalid"
implies complications in user-land contracts. By having "invalid", we are
forcing users to complicate their function specifications whenever they
deal with instances of that 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--94eb2c0961c4a3bd55052085117a
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, Sep 24, 2015 at 12:48 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"=
mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>=
></span> 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"><div class=3D"gmail_ext=
ra"><div class=3D"gmail_extra"><div class=3D"gmail_extra">And in the code I=
've got this kind of thing all over the place:</div><div class=3D"gmail=
_extra"><br></div><div class=3D"gmail_extra">void Foo(A& a1, A const&am=
p; a2)</div><div class=3D"gmail_extra">{</div><div class=3D"gmail_extra"><d=
iv class=3D"gmail_extra">=C2=A0 =C2=A0 /* ... */</div></div><div class=3D"g=
mail_extra">=C2=A0 =C2=A0 a1 =3D a2;</div><div class=3D"gmail_extra">=C2=A0=
=C2=A0 /* ... */</div><div class=3D"gmail_extra">}</div><div class=3D"gmai=
l_extra"><br></div><div class=3D"gmail_extra">Assume all compiles today.</d=
iv><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra"><br></di=
v><div class=3D"gmail_extra">Now, for other reasons L has to change to:</di=
v><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra"><div clas=
s=3D"gmail_extra">class L</div><div class=3D"gmail_extra">{</div><div class=
=3D"gmail_extra">=C2=A0 =C2=A0 M m;</div><div class=3D"gmail_extra">=C2=A0 =
=C2=A0 N n;</div><div class=3D"gmail_extra">=C2=A0 =C2=A0 deque<O> vo=
;</div><div class=3D"gmail_extra">public:<br></div><div class=3D"gmail_extr=
a">=C2=A0 =C2=A0 /* ... */</div><div class=3D"gmail_extra">};</div><div><br=
></div></div><div class=3D"gmail_extra">And all of a sudden Foo no longer c=
ompiles.=C2=A0 What's the fix?</div></div></div></div></blockquote><div=
><br></div><div>IIUC, other than that you'd probably need to update hig=
her-level code, as you've introduced a new path for failure by way of e=
xception (which is much more subtle to fix as there frequently are no compi=
le errors), you'd just make ghi optional and update the internal direct=
uses. If you find that totally unpalatable, and I think you're overest=
imating the effort, subtlety, and frequency of this happening, Michael Park=
's paper mentions an option for a separate nullable_variant template. I=
n my personal view, which differs from his suggestion in the details, if su=
ch a template existed at all it would just be a convenience wrapper around =
optional<variant<T...>>, providing a more flattened interface (=
I.E. a little more similar to a variant with an intrinsic invalid state, on=
ly even though the interface is more flat, you'd still have access to t=
he underlying never-empty abstraction, which you could pass around/deal wit=
h locally when you do not deal with "invalid"). I don't perso=
nally advocate this as I think such an approach is unnecessary, and the fla=
ttened nature reintroduces more complicated contracts, but it certainly see=
ms to be a better solution than always forcing someone to deal with a varia=
nt that can be invalid. I don't want users to be adding preconditions t=
o all of their functions dealing with variants and asserting whenever recei=
ving one that a given variant is "valid," as people similarly nee=
d to do with reference types in certain other mainstream languages whenever=
writing a function that doesn't deal with null. Working with user-defi=
ned objects and references in C++ is generally easier to reason about and d=
o correctly because you often know by the very nature of referring to a con=
structed instance of the type that it is "valid." Whenever you ca=
n keep such states separate, which you genuinely can here, it's benefic=
ial to do so. Use the type system to properly handle it. Of all of the desi=
gn aspects of a variant type, I feel the never-empty guarantee is perhaps t=
he most important, since introducing "invalid" implies complicati=
ons in user-land contracts. By having "invalid", we are forcing u=
sers to complicate their function specifications whenever they deal with in=
stances of that type.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--94eb2c0961c4a3bd55052085117a--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 24 Sep 2015 17:01:17 -0500
Raw View
--001a11415d1c35409d05208561b2
Content-Type: text/plain; charset=UTF-8
On 24 September 2015 at 16:39, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> IIUC, other than that you'd probably need to update higher-level code, as
> you've introduced a new path for failure by way of exception (which is much
> more subtle to fix as there frequently are no compile errors), you'd just
> make ghi optional and update the internal direct uses. If you find that
> totally unpalatable, and I think you're overestimating the effort,
> subtlety, and frequency of this happening,
>
Uh huh. Only because you've already decided that the Calabrese variant is
the One True Variant and all the others are bad.
If I use Boost.Variant, I don't have this problem.
If I use N4542.Variant, I don't have this problem.
If I use Williams.Variant, I don't have this problem.
If I use Eggs.Variant, I don't have this problem.
But Calabrese.Variant is somehow magically superior by being harder to use.
Do you have any experience using the Calabrese.Variant and
Calabrese.Optional in real code bases? I've used Boost.Variant as well as
a home grown one with an invalid state. As for optional, I've used
Boost.Optional, std::experimental::optional and a home grown one.
Oh, and the above problem can happen *just by switching standard library
implementations*. Like I said, a maintenance nightmare.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11415d1c35409d05208561b2
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 24 September 2015 at 16:39, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div>IIUC, other than that you'd probably n=
eed to update higher-level code, as you've introduced a new path for fa=
ilure by way of exception (which is much more subtle to fix as there freque=
ntly are no compile errors), you'd just make ghi optional and update th=
e internal direct uses. If you find that totally unpalatable, and I think y=
ou're overestimating the effort, subtlety, and frequency of this happen=
ing, </div></div></div></div></blockquote><div><br></div><div>Uh huh.=C2=A0=
Only because you've already decided that the Calabrese variant is the =
One True Variant and all the others are bad.</div><div><br></div><div>If I =
use Boost.Variant, I don't have this problem.</div><div><br></div><div>=
If I use N4542.Variant, I don't have this problem.</div><div><br></div>=
<div>If I use Williams.Variant, I don't have this problem.</div><div><b=
r></div><div>If I use Eggs.Variant, I don't have this problem.</div><di=
v><br></div><div>But Calabrese.Variant is somehow magically superior by bei=
ng harder to use.</div><div><br></div><div>Do you have any experience using=
the Calabrese.Variant and Calabrese.Optional in real code bases?=C2=A0 I&#=
39;ve used Boost.Variant as well as a home grown one with an invalid state.=
=C2=A0 As for optional, I've used Boost.Optional, std::experimental::op=
tional and a home grown one.</div><div><br></div><div>Oh, and the above pro=
blem can happen <i>just by switching standard library implementations</i>.=
=C2=A0 Like I said, a maintenance nightmare.</div></div>-- <br><div class=
=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a =
href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord=
..com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11415d1c35409d05208561b2--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Fri, 25 Sep 2015 00:35:59 +0200
Raw View
--001a11c2b90cf3b32b052085da5c
Content-Type: text/plain; charset=UTF-8
A variant with a normal empty value is very easy to reason about. It
default constructs to empty. It is queryable as empty. It is assignable
to empty. If something goes wrong when changing types it is left empty.
To change the type it destroys the old one and constructs the new one. The
code to implement such a variant is short and simple. Everyone will
understand how it works.
The complexity entailed from these desperate attempts to try and hide the
empty value are not worth it. You are just creating an overengineered
mess: If the types have these properties than the variant does this,
otherwise it does that unless the first type has property P, in that case
it double buffers to the heap and performs a triple
construct-move-copy-swap, blah, blah, blah.
The end result of such complexity is that it will be misused through
misunderstanding, and we'll end up with lots of hard-to-debug problems.
Keep it simple. Embrace the empty value.
On Wed, Sep 23, 2015 at 1:39 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, September 22, 2015 at 6:37:34 PM UTC-4, Andrew Tomazos wrote:
>>
>>
>>
>> On Tue, Sep 22, 2015 at 11:48 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>>
>>>
>>> On Tuesday, September 22, 2015 at 3:34:34 PM UTC-4, Andrew Tomazos wrote:
>>>>
>>>> On Tue, Sep 22, 2015 at 8:58 PM, Nevin Liber <ne...@eviloverlord.com>
>>>> wrote:
>>>>
>>>>> On 22 September 2015 at 13:46, Andrew Tomazos <andrew...@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> I just read the minutes. It was 10 people in the room and the first
>>>>>> vote on that issue was split down the middle.
>>>>>>
>>>>>
>>>>> And there were discussions after that.
>>>>>
>>>>> While we did reach consensus, it was not unanimous (IIRC there was
>>>>> still one dissenter in the room).
>>>>>
>>>>>
>>>>>> I think there were a lot of people not present that hold the position
>>>>>> that if there is to be a reachable empty state then it should behave like
>>>>>> every other type that has such an empty state. I expect the
>>>>>> default-construct-to-empty to be reopened at Kona.
>>>>>>
>>>>>
>>>>> Oh, I expect *every* design decision on variant (and possibly
>>>>> optional, since it is a related type, as well as requiring move
>>>>> constructors to never throw, either in the standard library or in the
>>>>> language) to be reopened in Kona.
>>>>>
>>>>> And there is a very real possibility that we won't have variant in the
>>>>> standard at all, if committee members cannot come to consensus on what they
>>>>> are willing to live with.
>>>>>
>>>>
>>>> If it drags on I think people will soften their stances. It was just a
>>>> little early at Lenexa and the group was too small. I think the 1000+
>>>> messages are a sign that people really want std::variant, so that will
>>>> motivate consensus in the long run. (I hope! :) )
>>>>
>>>
>>> Why does "consensus" mean "variants can be empty?" It seems to me that
>>> they were able to get a good 90% consensus on N4542. It's only been
>>> commentary since then that has reopened the issue.
>>>
>>> Here's the thing I've never understood about the whole emptiness thing.
>>>
>>> If I have need of a variant, and my use case is of the sort where that
>>> variant may be empty, N4542 lets me do that by explicitly providing an
>>> "empty" state, via the `monostate` type. If I want default constructing the
>>> variant to create an empty one, I just make it the first argument in the
>>> typelist.
>>>
>>> I can even create a specific typedef for it:
>>>
>>> template<typename ...Args>
>>> using empty_variant = variant<monostate, Args...>;
>>>
>>> However, if my use case for variant is such that it won't be empty... I
>>> still have to cover the empty case. Even though I know that it *cannot*
>>> be empty. If I use visitation, I have to handle the empty state. A state
>>> that no variant will ever be in.
>>>
>>> It seems to me that N4542 is the option that offers the most *freedom
>>> of choice* to the user. Users who want empty variants have them, and
>>> users who don't want empty variants don't have to have them.
>>>
>>> Why do people want to dictate how I code?
>>>
>>> My statement is (and it is a position shared by a lot of people) that
>> *if* variant has a reachable empty value (whether you call it an invalid
>> state, an error state, whatever) *then* it should behave as all the other
>> C++ types do that have such an empty value. It should default construct to
>> it, it should be queryable via the usual interface and should be mutatable
>> into it.
>>
>
> There are two problems with this.
>
> The first problem is really simple. Let's say I have a variant, and I need
> to put types into it that can throw on move. And I catch an exception,
> resolve something, and move on. I inspect the variant, and I find that it
> is empty.
>
> Now answer me this: is that variant empty because it was set to the empty
> state or because an exception was thrown?
>
> The answer, of course, is that you don't know.
>
> With N4542, you *do* know. Because there is a fundamental distinction
> between the variant being invalid (due to copy/move failure), and the
> variant containing the `monostate` type (the way you set it to being
> "empty").
>
> So I would say that your notion that "invalid" and "empty" are the same
> thing is just wrong.
>
> The second problem is this:
>
> I would have prefered a never-empty variant, provided it could have been
>> as performant as a union+tag and supported all types. Unfortunately it
>> turns out such a thing is impossible, so having an empty-value is the
>> least-worst alternative (in my opinion).
>>
>
> But it isn't impossible; it's impractical. The only two alternatives are
> to either forbid copy/move if one of the types is not noexcept, or to make
> copy/move expensive for types that are noexcept.
>
> Also, you don't seem to realize that N4542 gives you never-empty variants.
> It *guarantees* never-empty variants... so long as you follow the rules.
> If all the types you provide are no-except-moveable, then it is exactly
> equivalent to a "never empty" variant.
>
> It's really the best of all possible worlds. Users of throwing move
> objects still get to use variant, and do so with no loss of performance on
> copy/move. They have a way to test to see if the variant is valid, so that
> they can tell the difference between "empty due to failure" and "empty
> because I wanted it empty".
>
> And if you don't use throwing move objects... it's a never-empty variant,
> just like Boost.Variant.
>
> What more could you possibly ask for?
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2b90cf3b32b052085da5c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">A variant with a normal empty value is very easy to reason=
about.=C2=A0 It default constructs to empty.=C2=A0 It is queryable as empt=
y.=C2=A0 It is assignable to empty.=C2=A0 If something goes wrong when chan=
ging types it is left empty.=C2=A0 To change the type it destroys the old o=
ne and constructs the new one.=C2=A0 The code to implement such a variant i=
s short and simple.=C2=A0 Everyone will understand how it works.<div><br></=
div><div>The complexity entailed from these desperate attempts to try and h=
ide the empty value are not worth it.=C2=A0 You are just creating an overen=
gineered mess: =C2=A0If the types have these properties than the variant do=
es this, otherwise it does that unless the first type has property P, in th=
at case it double buffers to the heap and performs a triple construct-move-=
copy-swap, blah, blah, blah.</div><div><br></div><div>The end result of suc=
h complexity is that it will be misused through misunderstanding, and we=
9;ll end up with lots of hard-to-debug problems.</div><div><div class=3D"gm=
ail_extra"><br></div><div class=3D"gmail_extra">Keep it simple.=C2=A0 Embra=
ce the empty value.</div><div class=3D"gmail_extra"><br><div class=3D"gmail=
_quote">On Wed, Sep 23, 2015 at 1:39 AM, Nicol Bolas <span dir=3D"ltr"><=
<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.co=
m</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Tuesday, Septe=
mber 22, 2015 at 6:37:34 PM UTC-4, Andrew Tomazos wrote:<span class=3D""><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"><br><div><br><div cl=
ass=3D"gmail_quote">On Tue, Sep 22, 2015 at 11:48 PM, Nicol Bolas <span dir=
=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<br=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><br><br>On Tuesday, September 22, 2015 at 3=
:34:34 PM UTC-4, Andrew Tomazos wrote:<blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Tue, Sep 22, 2015 at=
8:58 PM, Nevin Liber <span dir=3D"ltr"><<a rel=3D"nofollow">ne...@evilo=
verlord.com</a>></span> wrote:<span><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"><div><span>On 22 September 2015 at 13:46, Andrew Tomazos <s=
pan dir=3D"ltr"><<a rel=3D"nofollow">andrew...@gmail.com</a>></span> =
wrote:<br></span><div class=3D"gmail_quote"><span><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div>I just read the minutes.=C2=A0 It was 10 people in the room and =
the first vote on that issue was split down the middle.=C2=A0</div></blockq=
uote><div><br></div></span><div>And there were discussions after that.</div=
><div><br></div><div>While we did reach consensus, it was not unanimous (II=
RC there was still one dissenter in the room).</div><span><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div> I think there were a lot of people not=
present that hold the position that if there is to be a reachable empty st=
ate then it should behave like every other type that has such an empty stat=
e.=C2=A0 I expect the default-construct-to-empty to be reopened at Kona.</d=
iv></blockquote><div><br></div></span><div>Oh, I expect <i>every</i>=C2=A0d=
esign decision on variant (and possibly optional, since it is a related typ=
e, as well as requiring move constructors to never throw, either in the sta=
ndard library or in the language) to be reopened in Kona.</div><div><br></d=
iv><div>And there is a very real possibility that we won't have variant=
in the standard at all, if committee members cannot come to consensus on w=
hat they are willing to live with.</div></div></div></div></blockquote><div=
>=C2=A0</div><div>If it drags on I think people will soften their stances.=
=C2=A0 It was just a little early at Lenexa and the group was too small.=C2=
=A0 I think the 1000+ messages are a sign that people really want std::vari=
ant, so that will motivate consensus in the long run. =C2=A0(I hope! :) )</=
div></span></div></div></div></blockquote><div><br>Why does "consensus=
" mean "variants can be empty?" It seems to me that they wer=
e able to get a good 90% consensus on N4542. It's only been commentary =
since then that has reopened the issue.<br><br>Here's the thing I'v=
e never understood about the whole emptiness thing.<br><br>If I have need o=
f a variant, and my use case is of the sort where that variant may be empty=
, N4542 lets me do that by explicitly providing an "empty" state,=
via the `monostate` type. If I want default constructing the variant to cr=
eate an empty one, I just make it the first argument in the typelist.<br><b=
r>I can even create a specific typedef for it:<br><br><div style=3D"backgro=
und-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid=
;border-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#00=
8">template</span><span style=3D"color:#660"><</span><span style=3D"colo=
r:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">...</span><span style=3D"color:#606">Args</span><span style=3D"co=
lor:#660">></span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#008">using</span><span style=3D"color:#000"> empty_variant </span><sp=
an style=3D"color:#660">=3D</span><span style=3D"color:#000"> variant</span=
><span style=3D"color:#660"><</span><span style=3D"color:#000">monostate=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#606">Args</span><span style=3D"color:#660">...>;=
</span></div></code></div><br>However, if my use case for variant is such t=
hat it won't be empty... I still have to cover the empty case. Even tho=
ugh I know that it <i>cannot</i> be empty. If I use visitation, I have to h=
andle the empty state. A state that no variant will ever be in.<br><br>It s=
eems to me that N4542 is the option that offers the most <i>freedom of choi=
ce</i> to the user. Users who want empty variants have them, and users who =
don't want empty variants don't have to have them.<br><br>Why do pe=
ople want to dictate how I code?<br></div><div><div>
<p></p></div></div></blockquote></div>My statement is (and it is a position=
shared by a lot of people) that *if* variant has a reachable empty value (=
whether you call it an invalid state, an error state, whatever) *then* it s=
hould behave as all the other C++ types do that have such an empty value.=
=C2=A0 It should default construct to it, it should be queryable via the us=
ual interface and should be mutatable into it.</div></div></blockquote></sp=
an><div><br>There are two problems with this. <br><br>The first problem is =
really simple. Let's say I have a variant, and I need to put types into=
it that can throw on move. And I catch an exception, resolve something, an=
d move on. I inspect the variant, and I find that it is empty.<br><br>Now a=
nswer me this: is that variant empty because it was set to the empty state =
or because an exception was thrown?<br><br>The answer, of course, is that y=
ou don't know.<br><br>With N4542, you <i>do</i> know. Because there is =
a fundamental distinction between the variant being invalid (due to copy/mo=
ve failure), and the variant containing the `monostate` type (the way you s=
et it to being "empty").<br><br>So I would say that your notion t=
hat "invalid" and "empty" are the same thing is just wr=
ong.<br><br>The second problem is this:<br><br></div><span class=3D""><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>I would have prefe=
red a never-empty variant, provided it could have been as performant as a u=
nion+tag and supported all types.=C2=A0 Unfortunately it turns out such a t=
hing is impossible, so having an empty-value is the least-worst alternative=
(in my opinion).</div></div></blockquote></span><div><br>But it isn't =
impossible; it's impractical. The only two alternatives are to either f=
orbid copy/move if one of the types is not noexcept, or to make copy/move e=
xpensive for types that are noexcept.<br><br>Also, you don't seem to re=
alize that N4542 gives you never-empty variants. It <i>guarantees</i> never=
-empty variants... so long as you follow the rules. If all the types you pr=
ovide are=20
no-except-moveable, then it is exactly equivalent to a "never empty&qu=
ot;=20
variant.<br><br>It's really the best of all possible worlds. Users of t=
hrowing move objects still get to use variant, and do so with no loss of pe=
rformance on copy/move. They have a way to test to see if the variant is va=
lid, so that they can tell the difference between "empty due to failur=
e" and "empty because I wanted it empty".<br><br>And if you =
don't use throwing move objects... it's a never-empty variant, just=
like Boost.Variant.<br><br>What more could you possibly ask for?<br> </di=
v><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2b90cf3b32b052085da5c--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 15:48:27 -0700
Raw View
--001a11c30caa8e2fcd052086076e
Content-Type: text/plain; charset=UTF-8
On Thu, Sep 24, 2015 at 3:01 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 24 September 2015 at 16:39, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> IIUC, other than that you'd probably need to update higher-level code, as
>> you've introduced a new path for failure by way of exception (which is much
>> more subtle to fix as there frequently are no compile errors), you'd just
>> make ghi optional and update the internal direct uses. If you find that
>> totally unpalatable, and I think you're overestimating the effort,
>> subtlety, and frequency of this happening,
>>
>
> Uh huh. Only because you've already decided that the Calabrese variant is
> the One True Variant and all the others are bad.
>
Nevin, if I didn't know you better I'd be more insulted, but that's really
not appropriate. I'm not saying anything of the sort. Obviously I believe
that this the best route forward, which is why I'm pushing for it, but I'm
not airing personal insults.
On Thu, Sep 24, 2015 at 3:01 PM, Nevin Liber <nevin@eviloverlord.com>
wrote:
> If I use Boost.Variant, I don't have this problem.
>
Boost.Variant is never-empty. Even if it were to use double storage (which
it doesn't), I would consider it a better option to something with an
invalid state, because it is harder for programmers to misuse and
simplifies their contracts.
On Thu, Sep 24, 2015 at 3:01 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> But Calabrese.Variant is somehow magically superior by being harder to use.
>
It's not superior, it's equivalent -- it just separates out the
abstractions rather than having it flattened into one type. The intent is
that while compile-time requirements of the underlying (non-optional)
construct are strict, it's easier to use *correctly* because the notion of
"invalid" is fully separate from the type itself. If you actually have an
instance, it's fully valid. An invalid instance is simply one that is not
constructed. If you always wanted a variant with a null state for some
reason (I wouldn't recommend it, but there's nothing stopping you), then
you could just always use an optional<variant<T...>>. Again, I personally
wouldn't recommend it because there are only certain classes of field types
for which you might want this, but this is a very direct equivalent to a
variant with a possible invalid state. Even if you were to do this, you
still have the benefit of the ability to retrieve a reference to the
never-empty variant, making it suitable to forward along to other functions
without complicating their contracts, which is something that you cannot do
when you combine together the two abstractions.
Think about it like a pointer and a reference. Let's say that you start
with a pointer, which can potentially be null. Other functions need to deal
with a reference to the target object type. You have a couple of options,
here:
1) Pass the object by pointer and have the function that needs to refer to
the object have an additional precondition regarding the pointer being
non-null, which is asserted in the function body
2) Dereference the pointer and pass by reference. The function no longer
needs a precondition and no longer needs to assert.
Perhaps controversial, but I would much sooner advocate option 2) rather
than option 1). Do you agree or disagree?
The above case is analogous to what is represented when you have a
variant<T...> and optional<variant<T...>>. By having the notions separate
and maintaining the never-empty guarantee in the underlying facility, you
allow users to write simpler code. The fact that we would use optional here
is particularly useful with respect to library specification, since it
means that we don't even have to decide on or further standardize what
"visit" or "which" would do on an invalid variant, because such a notion
simply does not exist.
On Thu, Sep 24, 2015 at 3:01 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> Do you have any experience using the Calabrese.Variant and
> Calabrese.Optional in real code bases? I've used Boost.Variant as well as
> a home grown one with an invalid state. As for optional, I've used
> Boost.Optional, std::experimental::optional and a home grown one.
>
We have very similar experiences. I've used variant in almost every project
since it was introduced into Boost. In my personal projects, I use a
home-grown variant which is also never-empty like the variant of Boost,
however it has the concept requirements that I've specified for assignment
(it is also constexpr-aware and guarantees triviality of special member
functions when applicable). I have an optional type that is a trivial
wrapper over that. The only thing I have not gone so far as to do is the
suggested optional-alteration regarding assignment, which is actually an
alteration that applies more generally to variant itself. I've never had
the need to do this because in practice I've rarely encountered
move-contstructors that can throw with respect to my variant fields
(incidental). The only time that I can recall where I *did* encounter that,
I just dealt with the field in that case via indirection, leaving the field
with a noexcept move constructor.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c30caa8e2fcd052086076e
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, Sep 24, 2015 at 3:01 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On =
24 September 2015 at 16:39, 'Matt Calabrese' via ISO C++ Standard -=
Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@iso=
cpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<b=
r></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>IIUC, other than that you'd probably need to up=
date higher-level code, as you've introduced a new path for failure by =
way of exception (which is much more subtle to fix as there frequently are =
no compile errors), you'd just make ghi optional and update the interna=
l direct uses. If you find that totally unpalatable, and I think you're=
overestimating the effort, subtlety, and frequency of this happening, </di=
v></div></div></div></blockquote><div><br></div></span><div>Uh huh.=C2=A0 O=
nly because you've already decided that the Calabrese variant is the On=
e True Variant and all the others are bad.</div></div></div></div></blockqu=
ote><div><br></div><div>Nevin, if I didn't know you better I'd be m=
ore insulted, but that's really not appropriate. I'm not saying any=
thing of the sort. Obviously I believe that this the best route forward, wh=
ich is why I'm pushing for it, but I'm not airing personal insults.=
</div><div><br></div><div>=C2=A0On Thu, Sep 24, 2015 at 3:01 PM, Nevin Libe=
r=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:nevin@eviloverlord.com" targ=
et=3D"_blank">nevin@eviloverlord.com</a>></span>=C2=A0wrote:</div><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w=
idth: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 class=3D"gmail_=
quote"><div>If I use Boost.Variant, I don't have this problem.<br></div=
></div></div></div></blockquote><div><br></div><div>Boost.Variant is never-=
empty. Even if it were to use double storage (which it doesn't), I woul=
d consider it a better option to something with an invalid state, because i=
t is harder for programmers to misuse and simplifies their contracts.</div>=
<div><br></div><div>On Thu, Sep 24, 2015 at 3:01 PM, Nevin Liber=C2=A0<span=
dir=3D"ltr"><<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank=
">nevin@eviloverlord.com</a>></span>=C2=A0wrote:</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>But Calabrese.Variant is somehow magically superior by being harder to use=
..</div></div></div></div></blockquote><div><br></div><div>It's not supe=
rior, it's equivalent -- it just separates out the abstractions rather =
than having it flattened into one type. The intent is that while compile-ti=
me requirements of the underlying (non-optional) construct are strict, it&#=
39;s easier to use *correctly* because the notion of "invalid" is=
fully separate from the type itself. If you actually have an instance, it&=
#39;s fully valid. An invalid instance is simply one that is not constructe=
d. If you always wanted a variant with a null state for some reason (I woul=
dn't recommend it, but there's nothing stopping you), then you coul=
d just always use an optional<variant<T...>>. Again, I personal=
ly wouldn't recommend it because there are only certain classes of fiel=
d types for which you might want this, but this is a very direct equivalent=
to a variant with a possible invalid state. Even if you were to do this, y=
ou still have the benefit of the ability to retrieve a reference to the nev=
er-empty variant, making it suitable to forward along to other functions wi=
thout complicating their contracts, which is something that you cannot do w=
hen you combine together the two abstractions.</div><div><br></div><div>Thi=
nk about it like a pointer and a reference. Let's say that you start wi=
th a pointer, which can potentially be null. Other functions need to deal w=
ith a reference to the target object type. You have a couple of options, he=
re:</div><div><br></div><div>1) Pass the object by pointer and have the fun=
ction that needs to refer to the object have an additional precondition reg=
arding the pointer being non-null, which is asserted in the function body</=
div><div>2) Dereference the pointer and pass by reference. The function no =
longer needs a precondition and no longer needs to assert.</div><div><br></=
div><div>Perhaps controversial, but I would much sooner advocate option 2) =
rather than option 1). Do you agree or disagree?</div><div><br></div><div>T=
he above case is analogous to what is represented when you have a variant&l=
t;T...> and optional<variant<T...>>. By having the notions s=
eparate and maintaining the never-empty guarantee in the underlying facilit=
y, you allow users to write simpler code. The fact that we would use option=
al here is particularly useful with respect to library specification, since=
it means that we don't even have to decide on or further standardize w=
hat "visit" or "which" would do on an invalid variant, =
because such a notion simply does not exist.</div><div><br></div><div>On Th=
u, Sep 24, 2015 at 3:01 PM, Nevin Liber=C2=A0<span dir=3D"ltr"><<a href=
=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com=
</a>></span>=C2=A0wrote:<br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div=
class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Do you have any expe=
rience using the Calabrese.Variant and Calabrese.Optional in real code base=
s?=C2=A0 I've used Boost.Variant as well as a home grown one with an in=
valid state.=C2=A0 As for optional, I've used Boost.Optional, std::expe=
rimental::optional and a home grown one.</div></div></div></div></blockquot=
e><div><br></div><div>We have very similar experiences. I've used varia=
nt in almost every project since it was introduced into Boost. In my person=
al projects, I use a home-grown variant which is also never-empty like the =
variant of Boost, however it has the concept requirements that I've spe=
cified for assignment (it is also constexpr-aware and guarantees triviality=
of special member functions when applicable). I have an optional type that=
is a trivial wrapper over that. The only thing I have not gone so far as t=
o do is the suggested optional-alteration regarding assignment, which is ac=
tually an alteration that applies more generally to variant itself. I'v=
e never had the need to do this because in practice I've rarely encount=
ered move-contstructors that can throw with respect to my variant fields (i=
ncidental). The only time that I can recall where I <i>did</i>=C2=A0encount=
er that, I just dealt with the field in that case via indirection, leaving =
the field with a noexcept move constructor.=C2=A0</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c30caa8e2fcd052086076e--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 16:06:06 -0700
Raw View
--047d7b33d318a4fce10520864641
Content-Type: text/plain; charset=UTF-8
On Thu, Sep 24, 2015 at 3:48 PM, Matt Calabrese <calabrese@google.com>
wrote:
>
> The only time that I can recall where I *did* encounter that, I just
> dealt with the field in that case via indirection, leaving the field with a
> noexcept move constructor.
>
I take that back, I've encountered fields with move-constructors that could
throw it in other places as well, but because I use
noexcept-default-constructible as a fallback, assignment was always still
fine. For detail, the only time where it actually showed up was because the
variant represented the states of a state machine, and the states were not
default constructible.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b33d318a4fce10520864641
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, Sep 24, 2015 at 3:48 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> wrote:<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 clas=
s=3D"gmail_extra"><div class=3D"gmail_quote"><div>The only time that I can =
recall where I <i>did</i>=C2=A0encounter that, I just dealt with the field =
in that case via indirection, leaving the field with a noexcept move constr=
uctor.=C2=A0</div></div></div></div>
</blockquote></div><br></div><div class=3D"gmail_extra">I take that back, I=
've encountered fields with move-constructors that could throw it in ot=
her places as well, but because I use noexcept-default-constructible as a f=
allback, assignment was always still fine. For detail, the only time where =
it actually showed up=C2=A0was because the variant represented the states o=
f a state machine, and the states were not default constructible.</div></di=
v>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--047d7b33d318a4fce10520864641--
.
Author: Michael Park <mcypark@gmail.com>
Date: Thu, 24 Sep 2015 16:10:53 -0700 (PDT)
Raw View
------=_Part_665_708370300.1443136253849
Content-Type: multipart/alternative;
boundary="----=_Part_666_1988932842.1443136253857"
------=_Part_666_1988932842.1443136253857
Content-Type: text/plain; charset=UTF-8
I'd like to float my proposal for a slight variation of N4542 around the
valid, unspecified state and *valid()*.
If we corner the valid, unspecified state to arise only to the exceptional
cases, the intent of the valid() function would be to observe the state of
the variant within the *catch* clause. That is, variants don't need to be
checked for validity all over the place. But we can't enforce the use of
*valid()* to be within *catch* clauses.
My proposal is to introduce a *bad_variant_assign* exception type which is
a *nested_exception* which stores the original exception that arose from
the move construction into the variant. This way we don't need to have a
*valid()* function which in and of itself doesn't communicate to the user
that it is intended to be only used within a *catch* clause.
The following code snippet with *valid()*:
*variant<T, U> v{T{}};*
*U u;*
*try {*
* v = u;*
*} catch (const std::exception& ex) {*
* if (!v.valid()) {*
* // v is valid, unspecified.*
* } else {*
* // old v is still there.*
* }*
*}*
would translate to:
*variant<T, U> v{T{}};*
*U u;*
*try {*
* v = u;*
*} catch (const std::bad_variant_assign& ex) {*
* // v is valid, unspecified.*
* // **ex.nested_ptr **stores the original exception.*
*} catch (const std::exception& ex) {*
* // old v is still there.*
*}*
On Thursday, September 24, 2015 at 4:06:08 PM UTC-7, Matt Calabrese wrote:
>
> On Thu, Sep 24, 2015 at 3:48 PM, Matt Calabrese <cala...@google.com
> <javascript:>> wrote:
>>
>> The only time that I can recall where I *did* encounter that, I just
>> dealt with the field in that case via indirection, leaving the field with a
>> noexcept move constructor.
>>
>
> I take that back, I've encountered fields with move-constructors that
> could throw it in other places as well, but because I use
> noexcept-default-constructible as a fallback, assignment was always still
> fine. For detail, the only time where it actually showed up was because the
> variant represented the states of a state machine, and the states were not
> default constructible.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_666_1988932842.1443136253857
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I'd like to float my proposal for a slight variation o=
f N4542 around the valid, unspecified state and=C2=A0<font face=3D"courier =
new, monospace"><b>valid()</b></font>.<div><br></div><div>If we corner the =
valid, unspecified state to arise only to the exceptional cases, the intent=
of the=C2=A0<font face=3D"courier new, monospace" style=3D"font-weight: bo=
ld;">valid()</font><font face=3D"arial, sans-serif">=C2=A0function would be=
to observe the state of the variant within the=C2=A0</font><font face=3D"c=
ourier new, monospace"><b>catch</b></font><font face=3D"arial, sans-serif">=
=C2=A0clause. That is, variants don't need to be checked for validity a=
ll over the place. But we can't enforce the use of=C2=A0</font><b style=
=3D"font-family: 'courier new', monospace;">valid()</b><font face=
=3D"arial, sans-serif">=C2=A0to be within=C2=A0</font><font face=3D"courier=
new, monospace"><b>catch</b></font><font face=3D"arial, sans-serif">=C2=A0=
clauses.</font></div><div><font face=3D"arial, sans-serif"><br></font></div=
><div><font face=3D"arial, sans-serif">My proposal is to introduce a=C2=A0<=
/font><b style=3D"font-family: 'courier new', monospace;">bad_varia=
nt_assign</b><font face=3D"arial, sans-serif">=C2=A0exception type which is=
a=C2=A0</font><b><font face=3D"courier new, monospace">nested_exception</f=
ont></b><font face=3D"arial, sans-serif">=C2=A0which stores=C2=A0the origin=
al exception that arose from the move construction into the variant. This w=
ay we don't need to have a=C2=A0</font><font face=3D"courier new, monos=
pace"><b>valid()</b></font><font face=3D"arial, sans-serif">=C2=A0function =
which in and of itself doesn't communicate to the user that it is inten=
ded to be only used within a=C2=A0</font><font face=3D"courier new, monospa=
ce"><b>catch</b></font><font face=3D"arial, sans-serif">=C2=A0clause.</font=
></div><div><font face=3D"arial, sans-serif"><br></font></div><div><font fa=
ce=3D"arial, sans-serif">The following code snippet with=C2=A0</font><b sty=
le=3D"font-family: 'courier new', monospace;">valid()</b><font face=
=3D"arial, sans-serif">:</font></div><blockquote style=3D"margin: 0px 0px 0=
px 40px; border: none; padding: 0px;"><div><font face=3D"courier new, monos=
pace"><b><br></b></font></div><div><font face=3D"courier new, monospace"><b=
>variant<T, U> v{T{}};</b></font></div><div><font face=3D"courier new=
, monospace"><b>U u;</b></font></div><div><font face=3D"courier new, monosp=
ace"><b>try {</b></font></div><div><font face=3D"courier new, monospace"><b=
>=C2=A0 v =3D u;</b></font></div><div><font face=3D"courier new, monospace"=
><b>} catch (const std::exception& ex) {</b></font></div><div><font fac=
e=3D"courier new, monospace"><b>=C2=A0 if (!v.valid()) {</b></font></div><d=
iv><b style=3D"font-family: 'courier new', monospace;">=C2=A0 =C2=
=A0 // v is valid, unspecified.</b></div><div><font face=3D"courier new, mo=
nospace"><b>=C2=A0 } else {</b></font></div><div><b style=3D"font-family: &=
#39;courier new', monospace;">=C2=A0 =C2=A0 // old v is still there.</b=
></div><div><font face=3D"courier new, monospace"><b>=C2=A0 }</b></font></d=
iv><div><font face=3D"courier new, monospace"><b>}</b></font></div></blockq=
uote><div><br></div><div>would translate to:</div><div><br></div><blockquot=
e style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><font face=
=3D"courier new, monospace"><b>variant<T, U> v{T{}};</b></font></div>=
<div><font face=3D"courier new, monospace"><b>U u;</b></font></div><div><fo=
nt face=3D"courier new, monospace"><b>try {</b></font></div><div><font face=
=3D"courier new, monospace"><b>=C2=A0 v =3D u;</b></font></div><div><font f=
ace=3D"courier new, monospace"><b>} catch (const std::bad_variant_assign&am=
p; ex) {</b></font></div><div><b style=3D"font-family: 'courier new'=
;, monospace;">=C2=A0 // v is valid, unspecified.</b></div><div><b style=3D=
"font-family: 'courier new', monospace;">=C2=A0 //=C2=A0</b><b styl=
e=3D"font-family: 'courier new', monospace;">ex.nested_ptr=C2=A0</b=
><b style=3D"font-family: 'courier new', monospace;">stores the ori=
ginal exception.</b></div><div><font face=3D"courier new, monospace"><b>} c=
atch (const std::exception& ex) {</b></font></div><div><b style=3D"font=
-family: 'courier new', monospace;">=C2=A0 // old v is still there.=
</b></div><div><font face=3D"courier new, monospace"><b>}</b></font></div><=
/blockquote><br>On Thursday, September 24, 2015 at 4:06:08 PM UTC-7, Matt C=
alabrese 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=
"><div><div class=3D"gmail_quote">On Thu, Sep 24, 2015 at 3:48 PM, Matt Cal=
abrese <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"u_rvYVmRCAAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">cala...@google.com</a>></span> wrote:<blockquote=
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>T=
he only time that I can recall where I <i>did</i>=C2=A0encounter that, I ju=
st dealt with the field in that case via indirection, leaving the field wit=
h a noexcept move constructor.=C2=A0</div></div></div></div>
</blockquote></div><br></div><div>I take that back, I've encountered fi=
elds with move-constructors that could throw it in other places as well, bu=
t because I use noexcept-default-constructible as a fallback, assignment wa=
s always still fine. For detail, the only time where it actually showed up=
=C2=A0was because the variant represented the states of a state machine, an=
d the states were not default constructible.</div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_666_1988932842.1443136253857--
------=_Part_665_708370300.1443136253849--
.
Author: Michael Park <mcypark@gmail.com>
Date: Thu, 24 Sep 2015 16:17:27 -0700 (PDT)
Raw View
------=_Part_1699_322913931.1443136647539
Content-Type: multipart/alternative;
boundary="----=_Part_1700_898126639.1443136647539"
------=_Part_1700_898126639.1443136647539
Content-Type: text/plain; charset=UTF-8
On an unrelated thought: *get* is a non-member function because we don't
want to write code like this (contrived):
*template <typename T, typename... Ts>*
*void F(const variant<Ts...>& v) {*
* v.template get<T>();*
*}*
Perhaps *emplace* should be considered to be made non-member in order to
avoid the same scenario (another contrived example)?
*template <typename T, typename... Ts, typename U>*
*void F(variant<Ts...>& v, const U& u) {*
* v.template emplace<T>(u);*
*}*
On Thursday, September 24, 2015 at 4:10:54 PM UTC-7, Michael Park wrote:
>
> I'd like to float my proposal for a slight variation of N4542 around the
> valid, unspecified state and *valid()*.
>
> If we corner the valid, unspecified state to arise only to the exceptional
> cases, the intent of the valid() function would be to observe the state
> of the variant within the *catch* clause. That is, variants don't need to
> be checked for validity all over the place. But we can't enforce the use of
> *valid()* to be within *catch* clauses.
>
> My proposal is to introduce a *bad_variant_assign* exception type which
> is a *nested_exception* which stores the original exception that arose
> from the move construction into the variant. This way we don't need to have
> a *valid()* function which in and of itself doesn't communicate to the
> user that it is intended to be only used within a *catch* clause.
>
> The following code snippet with *valid()*:
>
>
> *variant<T, U> v{T{}};*
> *U u;*
> *try {*
> * v = u;*
> *} catch (const std::exception& ex) {*
> * if (!v.valid()) {*
> * // v is valid, unspecified.*
> * } else {*
> * // old v is still there.*
> * }*
> *}*
>
>
> would translate to:
>
> *variant<T, U> v{T{}};*
> *U u;*
> *try {*
> * v = u;*
> *} catch (const std::bad_variant_assign& ex) {*
> * // v is valid, unspecified.*
> * // **ex.nested_ptr **stores the original exception.*
> *} catch (const std::exception& ex) {*
> * // old v is still there.*
> *}*
>
>
> On Thursday, September 24, 2015 at 4:06:08 PM UTC-7, Matt Calabrese wrote:
>>
>> On Thu, Sep 24, 2015 at 3:48 PM, Matt Calabrese <cala...@google.com>
>> wrote:
>>>
>>> The only time that I can recall where I *did* encounter that, I just
>>> dealt with the field in that case via indirection, leaving the field with a
>>> noexcept move constructor.
>>>
>>
>> I take that back, I've encountered fields with move-constructors that
>> could throw it in other places as well, but because I use
>> noexcept-default-constructible as a fallback, assignment was always still
>> fine. For detail, the only time where it actually showed up was because the
>> variant represented the states of a state machine, and the states were not
>> default constructible.
>>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1700_898126639.1443136647539
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On an unrelated thought: <b style=3D"font-family: 'cou=
rier new', monospace;">get</b><font face=3D"arial, sans-serif">=C2=A0is=
a non-member function because we don't want to write code like this (c=
ontrived):</font><div><font face=3D"arial, sans-serif"><br></font></div><bl=
ockquote style=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><fo=
nt face=3D"courier new, monospace"><b>template <typename T,=C2=A0typenam=
e... Ts></b></font></div><div><font face=3D"courier new, monospace"><b>v=
oid F(const variant<Ts...>& v) {</b></font></div><div><font face=
=3D"courier new, monospace"><b>=C2=A0 v.template get<T>();</b></font>=
</div><div><font face=3D"courier new, monospace"><b>}</b></font></div></blo=
ckquote><div><br></div><div><font face=3D"arial, sans-serif">Perhaps </font=
><b style=3D"font-family: 'courier new', monospace;">emplace</b>=C2=
=A0should be considered to be made non-member in order to avoid the same sc=
enario (another contrived example)?</div><div><br></div><blockquote style=
=3D"margin: 0 0 0 40px; border: none; padding: 0px;"><div><font face=3D"cou=
rier new, monospace"><b>template <typename T, typename... Ts, typename U=
></b></font></div><div><font face=3D"courier new, monospace"><b>void F(v=
ariant<Ts...>& v, const U& u) {</b></font></div><div><font fa=
ce=3D"courier new, monospace"><b>=C2=A0 v.template emplace<T>(u);</b>=
</font></div><div><font face=3D"courier new, monospace"><b>}</b></font></di=
v></blockquote><div><br>On Thursday, September 24, 2015 at 4:10:54 PM UTC-7=
, Michael Park 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">I'd like to float my proposal for a slight variation of N4542 =
around the valid, unspecified state and=C2=A0<font face=3D"courier new, mon=
ospace"><b>valid()</b></font>.<div><br></div><div>If we corner the valid, u=
nspecified state to arise only to the exceptional cases, the intent of the=
=C2=A0<font face=3D"courier new, monospace" style=3D"font-weight:bold">vali=
d()</font><font face=3D"arial, sans-serif">=C2=A0function would be to obser=
ve the state of the variant within the=C2=A0</font><font face=3D"courier ne=
w, monospace"><b>catch</b></font><font face=3D"arial, sans-serif">=C2=A0cla=
use. That is, variants don't need to be checked for validity all over t=
he place. But we can't enforce the use of=C2=A0</font><b style=3D"font-=
family:'courier new',monospace">valid()</b><font face=3D"arial, san=
s-serif">=C2=A0to be within=C2=A0</font><font face=3D"courier new, monospac=
e"><b>catch</b></font><font face=3D"arial, sans-serif">=C2=A0clauses.</font=
></div><div><font face=3D"arial, sans-serif"><br></font></div><div><font fa=
ce=3D"arial, sans-serif">My proposal is to introduce a=C2=A0</font><b style=
=3D"font-family:'courier new',monospace">bad_variant_assign</b><fon=
t face=3D"arial, sans-serif">=C2=A0exception type which is a=C2=A0</font><b=
><font face=3D"courier new, monospace">nested_exception</font></b><font fac=
e=3D"arial, sans-serif">=C2=A0which stores=C2=A0the original exception that=
arose from the move construction into the variant. This way we don't n=
eed to have a=C2=A0</font><font face=3D"courier new, monospace"><b>valid()<=
/b></font><font face=3D"arial, sans-serif">=C2=A0function which in and of i=
tself doesn't communicate to the user that it is intended to be only us=
ed within a=C2=A0</font><font face=3D"courier new, monospace"><b>catch</b><=
/font><font face=3D"arial, sans-serif">=C2=A0clause.</font></div><div><font=
face=3D"arial, sans-serif"><br></font></div><div><font face=3D"arial, sans=
-serif">The following code snippet with=C2=A0</font><b style=3D"font-family=
:'courier new',monospace">valid()</b><font face=3D"arial, sans-seri=
f">:</font></div><blockquote style=3D"margin:0px 0px 0px 40px;border:none;p=
adding:0px"><div><font face=3D"courier new, monospace"><b><br></b></font></=
div><div><font face=3D"courier new, monospace"><b>variant<T, U> v{T{}=
};</b></font></div><div><font face=3D"courier new, monospace"><b>U u;</b></=
font></div><div><font face=3D"courier new, monospace"><b>try {</b></font></=
div><div><font face=3D"courier new, monospace"><b>=C2=A0 v =3D u;</b></font=
></div><div><font face=3D"courier new, monospace"><b>} catch (const std::ex=
ception& ex) {</b></font></div><div><font face=3D"courier new, monospac=
e"><b>=C2=A0 if (!v.valid()) {</b></font></div><div><b style=3D"font-family=
:'courier new',monospace">=C2=A0 =C2=A0 // v is valid, unspecified.=
</b></div><div><font face=3D"courier new, monospace"><b>=C2=A0 } else {</b>=
</font></div><div><b style=3D"font-family:'courier new',monospace">=
=C2=A0 =C2=A0 // old v is still there.</b></div><div><font face=3D"courier =
new, monospace"><b>=C2=A0 }</b></font></div><div><font face=3D"courier new,=
monospace"><b>}</b></font></div></blockquote><div><br></div><div>would tra=
nslate to:</div><div><br></div><blockquote style=3D"margin:0 0 0 40px;borde=
r:none;padding:0px"><div><font face=3D"courier new, monospace"><b>variant&l=
t;T, U> v{T{}};</b></font></div><div><font face=3D"courier new, monospac=
e"><b>U u;</b></font></div><div><font face=3D"courier new, monospace"><b>tr=
y {</b></font></div><div><font face=3D"courier new, monospace"><b>=C2=A0 v =
=3D u;</b></font></div><div><font face=3D"courier new, monospace"><b>} catc=
h (const std::bad_variant_assign& ex) {</b></font></div><div><b style=
=3D"font-family:'courier new',monospace">=C2=A0 // v is valid, unsp=
ecified.</b></div><div><b style=3D"font-family:'courier new',monosp=
ace">=C2=A0 //=C2=A0</b><b style=3D"font-family:'courier new',monos=
pace">ex.nested_ptr=C2=A0</b><b style=3D"font-family:'courier new',=
monospace">stores the original exception.</b></div><div><font face=3D"couri=
er new, monospace"><b>} catch (const std::exception& ex) {</b></font></=
div><div><b style=3D"font-family:'courier new',monospace">=C2=A0 //=
old v is still there.</b></div><div><font face=3D"courier new, monospace">=
<b>}</b></font></div></blockquote><br>On Thursday, September 24, 2015 at 4:=
06:08 PM UTC-7, Matt Calabrese wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Thu, Sep 24, 2015 at =
3:48 PM, Matt Calabrese <span dir=3D"ltr"><<a rel=3D"nofollow">cala...@g=
oogle.com</a>></span> wrote:<blockquote class=3D"gmail_quote" style=3D"m=
argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div><div class=3D"gmail_quote"><div>The only time that I can recall wh=
ere I <i>did</i>=C2=A0encounter that, I just dealt with the field in that c=
ase via indirection, leaving the field with a noexcept move constructor.=C2=
=A0</div></div></div></div>
</blockquote></div><br></div><div>I take that back, I've encountered fi=
elds with move-constructors that could throw it in other places as well, bu=
t because I use noexcept-default-constructible as a fallback, assignment wa=
s always still fine. For detail, the only time where it actually showed up=
=C2=A0was because the variant represented the states of a state machine, an=
d the states were not default constructible.</div></div>
</blockquote></div></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1700_898126639.1443136647539--
------=_Part_1699_322913931.1443136647539--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 16:22:28 -0700
Raw View
--001a1142e64830c17a052086814f
Content-Type: text/plain; charset=UTF-8
On Thu, Sep 24, 2015 at 3:48 PM, Matt Calabrese <calabrese@google.com>
wrote:
>
> The above case is analogous to what is represented when you have a
> variant<T...> and optional<variant<T...>>. By having the notions separate
> and maintaining the never-empty guarantee in the underlying facility, you
> allow users to write simpler code. The fact that we would use optional here
> is particularly useful with respect to library specification, since it
> means that we don't even have to decide on or further standardize what
> "visit" or "which" would do on an invalid variant, because such a notion
> simply does not exist.
>
There is another option that I think is reasonable that I think you might
also find reasonable:
//////////
template<class... T>
class non_null_variant<T...> { /*...*/ };
template<class... T>
using variant = optional<non_null_variant<T...>>;
//////////
In that approach, the default name "variant" just is the full, functional
equivalent of what you advocate and has the equivalent of the invalid
state. By default it is "forwards compatible" in the sense that you want it
to be, but we'd also not be sacrificing the never-empty guarantee. The
handling of the invalid state would be implicitly covered by optional, so
it doesn't need any explicit specification. If people care about having
simple contracts, or if they're not dealing with types with things like
throwing move constructors, then they can use the underlying type, either
via direct instantiation, or by dereferencing the variant.
Is this at all reasonable to you, or do you also consider it valuable to
flatten? I'm not clear if that aspect is something you are for or against.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1142e64830c17a052086814f
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, Sep 24, 2015 at 3:48 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> 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"><div class=3D"gmail_ext=
ra"><div class=3D"gmail_quote"><div>The above case is analogous to what is =
represented when you have a variant<T...> and optional<variant<=
T...>>. By having the notions separate and maintaining the never-empt=
y guarantee in the underlying facility, you allow users to write simpler co=
de. The fact that we would use optional here is particularly useful with re=
spect to library specification, since it means that we don't even have =
to decide on or further standardize what "visit" or "which&q=
uot; would do on an invalid variant, because such a notion simply does not =
exist.</div></div></div></div></blockquote><div><br></div><div>There is ano=
ther option that I think is reasonable that I think you might also find rea=
sonable:</div><div><br></div><div>//////////</div><div>template<class...=
T></div><div>class non_null_variant<T...> { /*...*/ };</div><div>=
<br></div><div>template<class... T></div><div>using variant =3D optio=
nal<non_null_variant<T...>>;</div>//////////</div><div class=3D=
"gmail_quote"><br><div>In that approach, the default name "variant&quo=
t; just is the full, functional equivalent of what you advocate and has the=
equivalent of the invalid state. By default it is "forwards compatibl=
e" in the sense that you want it to be, but we'd also not be sacri=
ficing the never-empty guarantee. The handling of the invalid state would b=
e implicitly covered by optional, so it doesn't need any explicit speci=
fication. If people care about having simple contracts, or if they're n=
ot dealing with types with things like throwing move constructors, then the=
y can use the underlying type, either via direct instantiation, or by deref=
erencing the variant.</div><div><br></div><div>Is this at all reasonable to=
you, or do you also consider it valuable to flatten? I'm not clear if =
that aspect is something you are for or against.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1142e64830c17a052086814f--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Fri, 25 Sep 2015 01:31:22 +0200
Raw View
--001a11c26816040b76052086a10f
Content-Type: text/plain; charset=UTF-8
I think in general, for simplicity, we want a single standardized variant
with the best properties. If people want a different flavor of variant,
other than the standardized one, they can always implement their own. I
don't think it is worth the complexity to try to support multiple flavors.
The differences between a maybe-empty and never-empty variant may seem
extraordinary at the moment, but the average C++ programmer won't give a
damn about it. Whatever we ship they'll simply learn the properties of it
and use it however it is designed (unless it is really bad, it which case
they'll just ignore it.)
On Fri, Sep 25, 2015 at 1:22 AM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Thu, Sep 24, 2015 at 3:48 PM, Matt Calabrese <calabrese@google.com>
> wrote:
>>
>> The above case is analogous to what is represented when you have a
>> variant<T...> and optional<variant<T...>>. By having the notions separate
>> and maintaining the never-empty guarantee in the underlying facility, you
>> allow users to write simpler code. The fact that we would use optional here
>> is particularly useful with respect to library specification, since it
>> means that we don't even have to decide on or further standardize what
>> "visit" or "which" would do on an invalid variant, because such a notion
>> simply does not exist.
>>
>
> There is another option that I think is reasonable that I think you might
> also find reasonable:
>
> //////////
> template<class... T>
> class non_null_variant<T...> { /*...*/ };
>
> template<class... T>
> using variant = optional<non_null_variant<T...>>;
> //////////
>
> In that approach, the default name "variant" just is the full, functional
> equivalent of what you advocate and has the equivalent of the invalid
> state. By default it is "forwards compatible" in the sense that you want it
> to be, but we'd also not be sacrificing the never-empty guarantee. The
> handling of the invalid state would be implicitly covered by optional, so
> it doesn't need any explicit specification. If people care about having
> simple contracts, or if they're not dealing with types with things like
> throwing move constructors, then they can use the underlying type, either
> via direct instantiation, or by dereferencing the variant.
>
> Is this at all reasonable to you, or do you also consider it valuable to
> flatten? I'm not clear if that aspect is something you are for or against.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c26816040b76052086a10f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I think in general, for simplicity, we want a single stand=
ardized variant with the best properties.=C2=A0 If people want a different =
flavor of variant, other than the standardized one, they can always impleme=
nt their own.=C2=A0 I don't think it is worth the complexity to try to =
support multiple flavors.=C2=A0 The differences between a maybe-empty and n=
ever-empty variant may seem extraordinary at the moment, but the average C+=
+ programmer won't give a damn about it.=C2=A0 Whatever we ship they=
9;ll simply learn the properties of it and use it however it is designed (u=
nless it is really bad, it which case they'll just ignore it.)<div><div=
class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Fri, Sep 25, 2015 =
at 1:22 AM, 'Matt Calabrese' via ISO C++ Standard - Future Proposal=
s <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@isocpp.org" target=
=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<br><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D=
"gmail_quote"><span class=3D"">On Thu, Sep 24, 2015 at 3:48 PM, Matt Calabr=
ese <span dir=3D"ltr"><<a href=3D"mailto:calabrese@google.com" target=3D=
"_blank">calabrese@google.com</a>></span> wrote:</span><span class=3D"">=
<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;p=
adding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"=
gmail_quote"><div>The above case is analogous to what is represented when y=
ou have a variant<T...> and optional<variant<T...>>. By h=
aving the notions separate and maintaining the never-empty guarantee in the=
underlying facility, you allow users to write simpler code. The fact that =
we would use optional here is particularly useful with respect to library s=
pecification, since it means that we don't even have to decide on or fu=
rther standardize what "visit" or "which" would do on a=
n invalid variant, because such a notion simply does not exist.</div></div>=
</div></div></blockquote><div><br></div></span><div>There is another option=
that I think is reasonable that I think you might also find reasonable:</d=
iv><div><br></div><div>//////////</div><div>template<class... T></div=
><div>class non_null_variant<T...> { /*...*/ };</div><div><br></div><=
div>template<class... T></div><div>using variant =3D optional<non_=
null_variant<T...>>;</div>//////////</div><div class=3D"gmail_quot=
e"><br><div>In that approach, the default name "variant" just is =
the full, functional equivalent of what you advocate and has the equivalent=
of the invalid state. By default it is "forwards compatible" in =
the sense that you want it to be, but we'd also not be sacrificing the =
never-empty guarantee. The handling of the invalid state would be implicitl=
y covered by optional, so it doesn't need any explicit specification. I=
f people care about having simple contracts, or if they're not dealing =
with types with things like throwing move constructors, then they can use t=
he underlying type, either via direct instantiation, or by dereferencing th=
e variant.</div><div><br></div><div>Is this at all reasonable to you, or do=
you also consider it valuable to flatten? I'm not clear if that aspect=
is something you are for or against.</div></div></div></div><div class=3D"=
HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c26816040b76052086a10f--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 25 Sep 2015 09:47:13 -0700 (PDT)
Raw View
------=_Part_2103_1002244788.1443199633984
Content-Type: multipart/alternative;
boundary="----=_Part_2104_919094094.1443199633984"
------=_Part_2104_919094094.1443199633984
Content-Type: text/plain; charset=UTF-8
On Thursday, September 24, 2015 at 6:36:01 PM UTC-4, Andrew Tomazos wrote:
>
> A variant with a normal empty value is very easy to reason about. It
> default constructs to empty. It is queryable as empty. It is assignable
> to empty. If something goes wrong when changing types it is left empty.
> To change the type it destroys the old one and constructs the new one. The
> code to implement such a variant is short and simple. Everyone will
> understand how it works.
>
> The complexity entailed from these desperate attempts to try and hide the
> empty value are not worth it.
>
I disagree; never-empty is a highly desirable feature. The problem comes
from visitation. If I have the simplest of variants, `variant<int, float>`,
all of my visitor types *must* handle the empty state.
I will *never* put my variant into that state. It will *never* get into
that state by any means (since `int` and `float` are trivially copyable).
So why does every visitor have to have a `void operator()(<empty variant>)
{}` in it?
Now you could say that visitation should not require you to check the empty
state. Well... that's stupid. A good 80% of the point of visitation is that
it compile-time checks the typelist against the provided options. And
therefore, you *must* cover all of the available options. If empty is
available, you should be required to cover it; failure to do so should be
considered a compiler error.
And what about visitation when you return a value? Maybe you're writing a
factor visitor that takes the value and converts it into a specific type.
If your variant is conceptually never empty... what value do you return if
the variant is empty? You still have to cover the empty case, but
logically, there is nothing you can do if the desired type is not
default-constructable. Or does not have some reasonable default case.
Ultimately, having variant be never-empty satisfies *everyone's* needs. If
you need your variant to be empty, just give it a designated type that
means "empty" (monostate or whatever). You also conveniently avoid having
to argue with those who want to call `void` the empty state. And if you
don't need it to be empty, you don't have to pollute your visitors with
empty declarations.
> You are just creating an overengineered mess: If the types have these
> properties than the variant does this, otherwise it does that unless the
> first type has property P, in that case it double buffers to the heap and
> performs a triple construct-move-copy-swap, blah, blah, blah.
>
The user doesn't have to know about the details. Indeed, the standard
wouldn't even spell those cases out. It would simply say "variant doesn't
have an empty state, and all operations provide the strong exception
guarantee."
The discussion about double buffering and so forth is about how to
*implement* those behaviors efficiently. Those details only matter when
discussing standardization because the committee needs to decide what the
minimum overhead of requiring this behavior will be.
The lower the overhead that we can manage to implement efficiently, the
better never-empty looks.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2104_919094094.1443199633984
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, September 24, 2015 at 6:36:01 PM UTC-4, Andre=
w Tomazos 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"lt=
r">A variant with a normal empty value is very easy to reason about.=C2=A0 =
It default constructs to empty.=C2=A0 It is queryable as empty.=C2=A0 It is=
assignable to empty.=C2=A0 If something goes wrong when changing types it =
is left empty.=C2=A0 To change the type it destroys the old one and constru=
cts the new one.=C2=A0 The code to implement such a variant is short and si=
mple.=C2=A0 Everyone will understand how it works.<div><br></div><div>The c=
omplexity entailed from these desperate attempts to try and hide the empty =
value are not worth it.</div></div></blockquote><div><br>I disagree; never-=
empty is a highly desirable feature. The problem comes from visitation. If =
I have the simplest of variants, `variant<int, float>`, all of my vis=
itor types <i>must</i> handle the empty state.<br><br>I will <i>never</i> p=
ut my variant into that state. It will <i>never</i> get into that state by =
any means (since `int` and `float` are trivially copyable).<br><br>So why d=
oes every visitor have to have a `void operator()(<empty variant>) {}=
` in it?<br><br>Now you could say that visitation should not require you to=
check the empty state. Well... that's stupid. A good 80% of the point =
of visitation is that it compile-time checks the typelist against the provi=
ded options. And therefore, you <i>must</i> cover all of the available opti=
ons. If empty is available, you should be required to cover it; failure to =
do so should be considered a compiler error.<br><br>And what about visitati=
on when you return a value? Maybe you're writing a factor visitor that =
takes the value and converts it into a specific type. If your variant is co=
nceptually never empty... what value do you return if the variant is empty?=
You still have to cover the empty case, but logically, there is nothing yo=
u can do if the desired type is not default-constructable. Or does not have=
some reasonable default case.<br><br>Ultimately, having variant be never-e=
mpty satisfies <i>everyone's</i> needs. If you need your variant to be =
empty, just give it a designated type that means "empty" (monosta=
te or whatever). You also conveniently avoid having to argue with those who=
want to call `void` the empty state. And if you don't need it to be em=
pty, you don't have to pollute your visitors with empty declarations.<b=
r>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div> You are just creating an overengineered mess: =C2=A0If the types hav=
e these properties than the variant does this, otherwise it does that unles=
s the first type has property P, in that case it double buffers to the heap=
and performs a triple construct-move-copy-swap, blah, blah, blah.</div></d=
iv></blockquote><div><br>The user doesn't have to know about the detail=
s. Indeed, the standard wouldn't even spell those cases out. It would s=
imply say "variant doesn't have an empty state, and all operations=
provide the strong exception guarantee."<br><br>The discussion about =
double buffering and so forth is about how to <i>implement</i> those behavi=
ors efficiently. Those details only matter when discussing standardization =
because the committee needs to decide what the minimum overhead of requirin=
g this behavior will be.<br><br>The lower the overhead that we can manage t=
o implement efficiently, the better never-empty looks.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2104_919094094.1443199633984--
------=_Part_2103_1002244788.1443199633984--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Fri, 25 Sep 2015 11:52:41 -0700
Raw View
--001a11c30caa3b3047052096dac0
Content-Type: text/plain; charset=UTF-8
On Fri, Sep 25, 2015 at 9:47 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Thursday, September 24, 2015 at 6:36:01 PM UTC-4, Andrew Tomazos wrote:
>>
>> A variant with a normal empty value is very easy to reason about. It
>> default constructs to empty. It is queryable as empty. It is assignable
>> to empty. If something goes wrong when changing types it is left empty.
>> To change the type it destroys the old one and constructs the new one. The
>> code to implement such a variant is short and simple. Everyone will
>> understand how it works.
>>
>> The complexity entailed from these desperate attempts to try and hide the
>> empty value are not worth it.
>>
>
> I disagree; never-empty is a highly desirable feature. The problem comes
> from visitation. If I have the simplest of variants, `variant<int, float>`,
> all of my visitor types *must* handle the empty state.
>
+1
Even though I've voiced my dislike for the permanent backup storage option,
I've come around to think that it is still a better option than an invalid
state.
On Fri, Sep 25, 2015 at 9:47 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> So why does every visitor have to have a `void operator()(<empty variant>)
> {}` in it?
>
I think the more reasonable solution is to have it be UB to visit something
that is invalid, assuming there ends up being such an invalid state. As you
said, though, this is also not ideal.
On Fri, Sep 25, 2015 at 9:47 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> The user doesn't have to know about the details. Indeed, the standard
> wouldn't even spell those cases out. It would simply say "variant doesn't
> have an empty state, and all operations provide the strong exception
> guarantee."
>
> The discussion about double buffering and so forth is about how to
> *implement* those behaviors efficiently. Those details only matter when
> discussing standardization because the committee needs to decide what the
> minimum overhead of requiring this behavior will be.
>
+1
Again, even if some in this thread find my personal suggestion unpalatable,
I only provide it as yet another alternative because we (unfortunately, in
my opinion) seem to be going down the road towards an "invalid" state,
which IMO is a big mistake that people underestimate the ramifications of.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c30caa3b3047052096dac0
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 F=
ri, Sep 25, 2015 at 9:47 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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"><span class=3D"">On Thursd=
ay, September 24, 2015 at 6:36:01 PM UTC-4, Andrew Tomazos wrote:<blockquot=
e 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-lef=
t:1ex"><div dir=3D"ltr">A variant with a normal empty value is very easy to=
reason about.=C2=A0 It default constructs to empty.=C2=A0 It is queryable =
as empty.=C2=A0 It is assignable to empty.=C2=A0 If something goes wrong wh=
en changing types it is left empty.=C2=A0 To change the type it destroys th=
e old one and constructs the new one.=C2=A0 The code to implement such a va=
riant is short and simple.=C2=A0 Everyone will understand how it works.<div=
><br></div><div>The complexity entailed from these desperate attempts to tr=
y and hide the empty value are not worth it.</div></div></blockquote></span=
><div><br>I disagree; never-empty is a highly desirable feature. The proble=
m comes from visitation. If I have the simplest of variants, `variant<in=
t, float>`, all of my visitor types <i>must</i> handle the empty state.<=
br></div></div></blockquote><div><br></div><div>+1</div><div><br></div><div=
>Even though I've voiced my dislike for the permanent backup storage op=
tion, I've come around to think that it is still a better option than a=
n invalid state.</div><div><br></div><div>=C2=A0On Fri, Sep 25, 2015 at 9:4=
7 AM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gm=
ail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:</=
div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:sol=
id;padding-left:1ex"><div dir=3D"ltr"><div>So why does every visitor have t=
o have a `void operator()(<empty variant>) {}` in it?<br></div></div>=
</blockquote><div><br></div><div>I think the more reasonable solution is to=
have it be UB to visit something that is invalid, assuming there ends up b=
eing such an invalid state. As you said, though, this is also not ideal.</d=
iv><div><br></div><div>On Fri, Sep 25, 2015 at 9:47 AM, Nicol Bolas=C2=A0<s=
pan dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank=
">jmckesson@gmail.com</a>></span>=C2=A0wrote:</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"><div=
dir=3D"ltr"><div>The user doesn't have to know about the details. Inde=
ed, the standard wouldn't even spell those cases out. It would simply s=
ay "variant doesn't have an empty state, and all operations provid=
e the strong exception guarantee."<br><br>The discussion about double =
buffering and so forth is about how to <i>implement</i> those behaviors eff=
iciently. Those details only matter when discussing standardization because=
the committee needs to decide what the minimum overhead of requiring this =
behavior will be.</div></div></blockquote><div><br></div><div>+1</div><div>=
<br></div><div>Again, even if some in this thread find my personal suggesti=
on unpalatable, I only provide it as yet another alternative because we (un=
fortunately, in my opinion) seem to be going down the road towards an "=
;invalid" state, which IMO is a big mistake that people underestimate =
the ramifications of.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c30caa3b3047052096dac0--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Fri, 25 Sep 2015 22:13:53 +0200
Raw View
--001a11c268169e0f09052097fc6b
Content-Type: text/plain; charset=UTF-8
On Fri, Sep 25, 2015 at 6:47 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> If I have the simplest of variants, `variant<int, float>`, all of my
> visitor types *must* handle the empty state.
>
I will *never* put my variant into that state. It will *never* get into
> that state by any means (since `int` and `float` are trivially copyable).
>
So why does every visitor have to have a `void operator()(<empty variant>)
> {}` in it?
>
That is a strawman. The other maybe-empty C++ types such as std::any,
std::function, std::thread, std::optional, std::unique_ptr,
std::shared_ptr, etc, exhibit a variety of behaviors if you use them while
empty.
For example:
If I call .value() on an empty std::optional, it throws an exception.
If I call operator*() on an empty std::optional, it is undefined behavior.
If I call .value_or() on an empty std::optional, it returns a given default
value.
and so on.
Just because a type has a possible value, does not imply a particular
program has to use that value in a particular way or at all.
When we say "its just one more branch in the switch" we are referring to
the low level dispatch on the discriminator. It's just one more entry in
the jump table, so the empty value doesn't create an extra branch and
performance cost (unlike, for example, throwing on optional::operator*
would).
In particular, the existence of the empty value doesn't imply "all of your
visitor types must handle the empty state".
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c268169e0f09052097fc6b
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 F=
ri, Sep 25, 2015 at 6:47 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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>If I have the simples=
t of variants, `variant<int, float>`, all of my visitor types <i>must=
</i> handle the empty state.</div></div></blockquote><blockquote class=3D"g=
mail_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>I will <i>never</i> put my variant into that state. It wil=
l <i>never</i> get into that state by any means (since `int` and `float` ar=
e trivially copyable).<br></div></div></blockquote><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div di=
r=3D"ltr"><div>So why does every visitor have to have a `void operator()(&l=
t;empty variant>) {}` in it?<br></div></div></blockquote><div><br></div>=
<div>That is a strawman.=C2=A0 The other maybe-empty C++ types such as std:=
:any, std::function, std::thread, std::optional, std::unique_ptr, std::shar=
ed_ptr, etc, exhibit a variety of behaviors if you use them while empty.</d=
iv><div><br></div><div>For example:</div><div><br></div><div>If I call .val=
ue() on an empty std::optional, it throws an exception.</div><div><br></div=
><div>If I call operator*() on an empty std::optional, it is undefined beha=
vior.</div><div><br></div><div>If I call .value_or() on an empty std::optio=
nal, it returns a given default value.</div><div><br></div><div>and so on.<=
/div><div><br></div><div>Just because a type has a possible value, does not=
imply a particular program has to use that value in a particular way or at=
all.</div><div><br></div><div>When we say "its just one more branch i=
n the switch" we are referring to the low level dispatch on the discri=
minator.=C2=A0 It's just one more entry in the jump table, so the empty=
value doesn't create an extra branch and performance cost (unlike, for=
example, throwing on optional::operator* would).</div><div><br></div><div>=
In particular, the existence of the empty value doesn't imply "all=
of your visitor types must handle the empty state".</div><div><br></d=
iv></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c268169e0f09052097fc6b--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 25 Sep 2015 15:48:16 -0700 (PDT)
Raw View
------=_Part_2447_369186050.1443221296530
Content-Type: multipart/alternative;
boundary="----=_Part_2448_1916218919.1443221296531"
------=_Part_2448_1916218919.1443221296531
Content-Type: text/plain; charset=UTF-8
On Friday, September 25, 2015 at 4:13:57 PM UTC-4, Andrew Tomazos wrote:
>
> On Fri, Sep 25, 2015 at 6:47 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> If I have the simplest of variants, `variant<int, float>`, all of my
>> visitor types *must* handle the empty state.
>>
> I will *never* put my variant into that state. It will *never* get into
>> that state by any means (since `int` and `float` are trivially copyable).
>>
> So why does every visitor have to have a `void operator()(<empty variant>)
>> {}` in it?
>>
>
> That is a strawman.
>
.... how is that a strawman?
Later on, you're going to say that, in your potentially-empty variant
design, visitors don't have to check the empty state. Even if that's part
of such a design (and it *shouldn't* be, as I will explain later), my
statement is still not a strawman. At worst, it's just an incorrect
statement based on assuming facts about a design that were not stated.
"Strawman" is not shorthand for "statement I don't agree with."
The other maybe-empty C++ types such as std::any, std::function,
> std::thread, std::optional, std::unique_ptr, std::shared_ptr, etc, exhibit
> a variety of behaviors if you use them while empty.
>
.... Nobody's claiming that we *can't* define the behavior of a variant with
a required empty state. We all know what that would look like.
The question is not "can we"; it's "should we?" What are the costs of doing
so?
And the fact that other classes can be empty is irrelevant. Variant is its
own type and should not have to conform to arbitrary expectations because
they were useful to other types.
> Just because a type has a possible value, does not imply a particular
> program has to use that value in a particular way or at all.
>
But it *does* imply that the program has to make sure that the case is
checked. Just take `optional`; if you just use `value`, you're assuming
that the `optional` is not empty. And brokenness will ensure if it is.
> When we say "its just one more branch in the switch" we are referring to
> the low level dispatch on the discriminator. It's just one more entry in
> the jump table, so the empty value doesn't create an extra branch and
> performance cost (unlike, for example, throwing on optional::operator*
> would).
>
I said nothing about "extra branch and performance cost". I was talking
about having to *write code* into my visitors. It's not about how long that
would take to execute; it's about having to cover cases that the
compile-time will check (again, see below for why it should) that will
never happen at runtime.
> In particular, the existence of the empty value doesn't imply "all of your
> visitor types must handle the empty state".
>
Since you want to compare `variant` to `optional`, let's use that analogy.
With `optional`, the user must test for the possibility of it being empty.
And if the user does not, if the user assumes it's not empty and it
actually is, an exception is thrown.
Generally speaking, people don't like exceptions being thrown. So at the
end of the day, most people will prefer `optional::value_or` to get at the
data, where reasonable. It's the safe accessor function, the one that
always works.
Now with `variant`, things are different. Fetching types from a variant
directly with `get` is a code smell if not a full-on anti-pattern. Instead,
you use visitation. Now, you could do `if(var) then apply_visitor(var,
....);`. However, that's exceedingly fragile, much like using `if(opt) then
opt.value()`. That's why we invented `value_or` to begin with.
The `variant` equivalent of `value_or` is type-checking. That is, checking
that your visitor actually has a function for each of the states of the
variant, *including empty*. If you don't have that check, then you cannot
statically know your code works.
So for safety reasons, users will have to check the empty state. And a
*good* visitation system will verify that the empty state is checked for.
Always. Just like smart compilers will warn you if you switch on an enum
and you don't check all possible states (and have no default).
The only way to avoid this is to have multiple versions of visitation:
`apply_visitor` and `apply_visitor_not_empty` or whatever. And... it
doesn't even fix the problem because the user can use the wrong one by
accident, with no compile-time check.
So if you want compile-time checking (and if you don't, you *should*),
using a possibly-empty variant will *require* all users to handle the empty
state in their visitors.
Or you just have a never-empty variant, which can be given a type that
represents being empty. This solves all of these problems. Code that needs
emptiness will also be required to check for it, making their code safer.
And code that doesn't won't have to check for a state that will never exist.
The only, *only* advantage of an enforced empty state is making
implementing `variant` easier and *possibly* more efficient. But we're
already proving that a never-empty variant can provide the strong exception
guarantee with relatively minimal overhead.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2448_1916218919.1443221296531
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, September 25, 2015 at 4:13:57 PM UTC-4, Andrew Tomazos wrote:<bl=
ockquote 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><div class=
=3D"gmail_quote">On Fri, Sep 25, 2015 at 6:47 PM, Nicol Bolas <span dir=3D"=
ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D=
"KX9UpojWCAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:=
';return true;" onclick=3D"this.href=3D'javascript:';return tru=
e;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D=
"ltr"><div>If I have the simplest of variants, `variant<int, float>`,=
all of my visitor types <i>must</i> handle the empty state.</div></div></b=
lockquote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div>I will <i>never</i> put my=
variant into that state. It will <i>never</i> get into that state by any m=
eans (since `int` and `float` are trivially copyable).<br></div></div></blo=
ckquote><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>So why does every visitor ha=
ve to have a `void operator()(<empty variant>) {}` in it?<br></div></=
div></blockquote><div><br></div><div>That is a strawman.</div></div></div><=
/div></blockquote><div><br>... how is that a strawman?<br><br>Later on, you=
're going to say that, in your potentially-empty variant design, visito=
rs don't have to check the empty state. Even if that's part of such=
a design (and it <i>shouldn't</i> be, as I will explain later), my sta=
tement is still not a strawman. At worst, it's just an incorrect statem=
ent based on assuming facts about a design that were not stated.<br><br>&qu=
ot;Strawman" is not shorthand for "statement I don't agree wi=
th."<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 di=
r=3D"ltr"><div><div class=3D"gmail_quote"><div>=C2=A0 The other maybe-empty=
C++ types such as std::any, std::function, std::thread, std::optional, std=
::unique_ptr, std::shared_ptr, etc, exhibit a variety of behaviors if you u=
se them while empty.</div></div></div></div></blockquote><div><br>... Nobod=
y's claiming that we <i>can't</i> define the behavior of a variant =
with a required empty state. We all know what that would look like.<br><br>=
The question is not "can we"; it's "should we?" Wha=
t are the costs of doing so?<br><br>And the fact that other classes can be =
empty is irrelevant. Variant is its own type and should not have to conform=
to arbitrary expectations because they were useful to other types.<br>=C2=
=A0</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=
><div class=3D"gmail_quote"><div></div><div>Just because a type has a possi=
ble value, does not imply a particular program has to use that value in a p=
articular way or at all.</div></div></div></div></blockquote><div><br>But i=
t <i>does</i> imply that the program has to make sure that the case is chec=
ked. Just take `optional`; if you just use `value`, you're assuming tha=
t the `optional` is not empty. And brokenness will ensure if it is.<br></di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><div><div class=3D"gmail_quote"><div></div><div>When we say "its=
just one more branch in the switch" we are referring to the low level=
dispatch on the discriminator.=C2=A0 It's just one more entry in the j=
ump table, so the empty value doesn't create an extra branch and perfor=
mance cost (unlike, for example, throwing on optional::operator* would).</d=
iv></div></div></div></blockquote><div><br>I said nothing about "extra=
branch and performance cost". I was talking about having to <i>write =
code</i> into my visitors. It's not about how long that would take to e=
xecute; it's about having to cover cases that the compile-time will che=
ck (again, see below for why it should) that will never happen at runtime.<=
br>=C2=A0</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><div class=3D"gmail_quote"><div></div><div>In particular, the existe=
nce of the empty value doesn't imply "all of your visitor types mu=
st handle the empty state".</div></div></div></div></blockquote><div><=
br>Since you want to compare `variant` to `optional`, let's use that an=
alogy. With `optional`, the user must test for the possibility of it being =
empty. And if the user does not, if the user assumes it's not empty and=
it actually is, an exception is thrown.<br><br>Generally speaking, people =
don't like exceptions being thrown. So at the end of the day, most peop=
le will prefer `optional::value_or` to get at the data, where reasonable. I=
t's the safe accessor function, the one that always works.<br><br>Now w=
ith `variant`, things are different. Fetching types from a variant directly=
with `get` is a code smell if not a full-on anti-pattern. Instead, you use=
visitation. Now, you could do `if(var) then apply_visitor(var, ...);`. How=
ever, that's exceedingly fragile, much like using `if(opt) then opt.val=
ue()`. That's why we invented `value_or` to begin with.<br><br>The `var=
iant` equivalent of `value_or` is type-checking. That is, checking that you=
r visitor actually has a function for each of the states of the variant, <i=
>including empty</i>. If you don't have that check, then you cannot sta=
tically know your code works.<br><br>So for safety reasons, users will have=
to check the empty state. And a <i>good</i> visitation system will verify =
that the empty state is checked for. Always. Just like smart compilers will=
warn you if you switch on an enum and you don't check all possible sta=
tes (and have no default).<br><br>The only way to avoid this is to have mul=
tiple versions of visitation: `apply_visitor` and `apply_visitor_not_empty`=
or whatever. And... it doesn't even fix the problem because the user c=
an use the wrong one by accident, with no compile-time check.<br><br>So if =
you want compile-time checking (and if you don't, you <i>should</i>), u=
sing a possibly-empty variant will <i>require</i> all users to handle the e=
mpty state in their visitors.<br><br>Or you just have a never-empty variant=
, which can be given a type that represents being empty. This solves all of=
these problems. Code that needs emptiness will also be required to check f=
or it, making their code safer. And code that doesn't won't have to=
check for a state that will never exist.<br><br>The only, <i>only</i> adva=
ntage of an enforced empty state is making implementing `variant` easier an=
d <i>possibly</i> more efficient. But we're already proving that a neve=
r-empty variant can provide the strong exception guarantee with relatively =
minimal overhead.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_2448_1916218919.1443221296531--
------=_Part_2447_369186050.1443221296530--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sat, 26 Sep 2015 01:39:04 +0200
Raw View
--f46d04462e6a625b6505209ada0d
Content-Type: text/plain; charset=UTF-8
You're exaggerating the consequences of an empty value, and wildly leaping
to conclusions that don't hold.
A precondition of sqrt is that the parameter does not have a negative value.
This is no different than some function with a variant parameter, having a
precondition that it does not hold the empty value.
Compared to the complexity, generality and performance of the alternatives,
it remains my opinion that the simple "at most one" variant design, with an
empty value that has the normal consistent interface, is the one we should
standardize.
On Sat, Sep 26, 2015 at 12:48 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Friday, September 25, 2015 at 4:13:57 PM UTC-4, Andrew Tomazos wrote:
>>
>> On Fri, Sep 25, 2015 at 6:47 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> If I have the simplest of variants, `variant<int, float>`, all of my
>>> visitor types *must* handle the empty state.
>>>
>> I will *never* put my variant into that state. It will *never* get into
>>> that state by any means (since `int` and `float` are trivially copyable).
>>>
>> So why does every visitor have to have a `void operator()(<empty
>>> variant>) {}` in it?
>>>
>>
>> That is a strawman.
>>
>
> ... how is that a strawman?
>
> Later on, you're going to say that, in your potentially-empty variant
> design, visitors don't have to check the empty state. Even if that's part
> of such a design (and it *shouldn't* be, as I will explain later), my
> statement is still not a strawman. At worst, it's just an incorrect
> statement based on assuming facts about a design that were not stated.
>
> "Strawman" is not shorthand for "statement I don't agree with."
>
> The other maybe-empty C++ types such as std::any, std::function,
>> std::thread, std::optional, std::unique_ptr, std::shared_ptr, etc, exhibit
>> a variety of behaviors if you use them while empty.
>>
>
> ... Nobody's claiming that we *can't* define the behavior of a variant
> with a required empty state. We all know what that would look like.
>
> The question is not "can we"; it's "should we?" What are the costs of
> doing so?
>
> And the fact that other classes can be empty is irrelevant. Variant is its
> own type and should not have to conform to arbitrary expectations because
> they were useful to other types.
>
>
>> Just because a type has a possible value, does not imply a particular
>> program has to use that value in a particular way or at all.
>>
>
> But it *does* imply that the program has to make sure that the case is
> checked. Just take `optional`; if you just use `value`, you're assuming
> that the `optional` is not empty. And brokenness will ensure if it is.
>
>
>> When we say "its just one more branch in the switch" we are referring to
>> the low level dispatch on the discriminator. It's just one more entry in
>> the jump table, so the empty value doesn't create an extra branch and
>> performance cost (unlike, for example, throwing on optional::operator*
>> would).
>>
>
> I said nothing about "extra branch and performance cost". I was talking
> about having to *write code* into my visitors. It's not about how long
> that would take to execute; it's about having to cover cases that the
> compile-time will check (again, see below for why it should) that will
> never happen at runtime.
>
>
>> In particular, the existence of the empty value doesn't imply "all of
>> your visitor types must handle the empty state".
>>
>
> Since you want to compare `variant` to `optional`, let's use that analogy.
> With `optional`, the user must test for the possibility of it being empty.
> And if the user does not, if the user assumes it's not empty and it
> actually is, an exception is thrown.
>
> Generally speaking, people don't like exceptions being thrown. So at the
> end of the day, most people will prefer `optional::value_or` to get at the
> data, where reasonable. It's the safe accessor function, the one that
> always works.
>
> Now with `variant`, things are different. Fetching types from a variant
> directly with `get` is a code smell if not a full-on anti-pattern. Instead,
> you use visitation. Now, you could do `if(var) then apply_visitor(var,
> ...);`. However, that's exceedingly fragile, much like using `if(opt) then
> opt.value()`. That's why we invented `value_or` to begin with.
>
> The `variant` equivalent of `value_or` is type-checking. That is, checking
> that your visitor actually has a function for each of the states of the
> variant, *including empty*. If you don't have that check, then you cannot
> statically know your code works.
>
> So for safety reasons, users will have to check the empty state. And a
> *good* visitation system will verify that the empty state is checked for.
> Always. Just like smart compilers will warn you if you switch on an enum
> and you don't check all possible states (and have no default).
>
> The only way to avoid this is to have multiple versions of visitation:
> `apply_visitor` and `apply_visitor_not_empty` or whatever. And... it
> doesn't even fix the problem because the user can use the wrong one by
> accident, with no compile-time check.
>
> So if you want compile-time checking (and if you don't, you *should*),
> using a possibly-empty variant will *require* all users to handle the
> empty state in their visitors.
>
> Or you just have a never-empty variant, which can be given a type that
> represents being empty. This solves all of these problems. Code that needs
> emptiness will also be required to check for it, making their code safer.
> And code that doesn't won't have to check for a state that will never exist.
>
> The only, *only* advantage of an enforced empty state is making
> implementing `variant` easier and *possibly* more efficient. But we're
> already proving that a never-empty variant can provide the strong exception
> guarantee with relatively minimal overhead.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--f46d04462e6a625b6505209ada0d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">You're exaggerating the consequences of an empty value=
, and wildly leaping to conclusions that don't hold.<div><br></div><div=
>A precondition of sqrt is that the parameter does not have a negative valu=
e.</div><div><br></div><div>This is no different than some function with a =
variant parameter, having a precondition that it does not hold the empty va=
lue.</div><div><br></div><div>Compared to the complexity, generality and pe=
rformance of the alternatives, it remains my opinion that the simple "=
at most one" variant design, with an empty value that has the normal c=
onsistent interface, is the one we should standardize.</div><div><br></div>=
<div><div><div class=3D"gmail_extra"><div class=3D"gmail_quote">On Sat, Sep=
26, 2015 at 12:48 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:=
jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> w=
rote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex">On Friday, September 25, 2015 at 4:13:57 PM UTC-4=
, Andrew Tomazos wrote:<span class=3D""><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rg=
b(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><=
div><div class=3D"gmail_quote">On Fri, Sep 25, 2015 at 6:47 PM, Nicol Bolas=
<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span>=
wrote:<br><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-st=
yle:solid;padding-left:1ex"><div dir=3D"ltr"><div>If I have the simplest of=
variants, `variant<int, float>`, all of my visitor types <i>must</i>=
handle the empty state.</div></div></blockquote><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>I will <i>never</i> put my variant into that state. It will <=
i>never</i> get into that state by any means (since `int` and `float` are t=
rivially copyable).<br></div></div></blockquote><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>So why does every visitor have to have a `void operator()(<=
;empty variant>) {}` in it?<br></div></div></blockquote><div><br></div><=
div>That is a strawman.</div></div></div></div></blockquote></span><div><br=
>... how is that a strawman?<br><br>Later on, you're going to say that,=
in your potentially-empty variant design, visitors don't have to check=
the empty state. Even if that's part of such a design (and it <i>shoul=
dn't</i> be, as I will explain later), my statement is still not a stra=
wman. At worst, it's just an incorrect statement based on assuming fact=
s about a design that were not stated.<br><br>"Strawman" is not s=
horthand for "statement I don't agree with."<br><br></div><sp=
an class=3D""><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><div class=3D"gmail_qu=
ote"><div>=C2=A0 The other maybe-empty C++ types such as std::any, std::fun=
ction, std::thread, std::optional, std::unique_ptr, std::shared_ptr, etc, e=
xhibit a variety of behaviors if you use them while empty.</div></div></div=
></div></blockquote></span><div><br>... Nobody's claiming that we <i>ca=
n't</i> define the behavior of a variant with a required empty state. W=
e all know what that would look like.<br><br>The question is not "can =
we"; it's "should we?" What are the costs of doing so?<b=
r><br>And the fact that other classes can be empty is irrelevant. Variant i=
s its own type and should not have to conform to arbitrary expectations bec=
ause they were useful to other types.<br>=C2=A0</div><span class=3D""><bloc=
kquote 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;paddin=
g-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><di=
v>Just because a type has a possible value, does not imply a particular pro=
gram has to use that value in a particular way or at all.</div></div></div>=
</div></blockquote></span><div><br>But it <i>does</i> imply that the progra=
m has to make sure that the case is checked. Just take `optional`; if you j=
ust use `value`, you're assuming that the `optional` is not empty. And =
brokenness will ensure if it is.<br></div><span class=3D""><div>=C2=A0</div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;=
padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></d=
iv><div>When we say "its just one more branch in the switch" we a=
re referring to the low level dispatch on the discriminator.=C2=A0 It's=
just one more entry in the jump table, so the empty value doesn't crea=
te an extra branch and performance cost (unlike, for example, throwing on o=
ptional::operator* would).</div></div></div></div></blockquote></span><div>=
<br>I said nothing about "extra branch and performance cost". I w=
as talking about having to <i>write code</i> into my visitors. It's not=
about how long that would take to execute; it's about having to cover =
cases that the compile-time will check (again, see below for why it should)=
that will never happen at runtime.<br>=C2=A0</div><span class=3D""><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>=
In particular, the existence of the empty value doesn't imply "all=
of your visitor types must handle the empty state".</div></div></div>=
</div></blockquote></span><div><br>Since you want to compare `variant` to `=
optional`, let's use that analogy. With `optional`, the user must test =
for the possibility of it being empty. And if the user does not, if the use=
r assumes it's not empty and it actually is, an exception is thrown.<br=
><br>Generally speaking, people don't like exceptions being thrown. So =
at the end of the day, most people will prefer `optional::value_or` to get =
at the data, where reasonable. It's the safe accessor function, the one=
that always works.<br><br>Now with `variant`, things are different. Fetchi=
ng types from a variant directly with `get` is a code smell if not a full-o=
n anti-pattern. Instead, you use visitation. Now, you could do `if(var) the=
n apply_visitor(var, ...);`. However, that's exceedingly fragile, much =
like using `if(opt) then opt.value()`. That's why we invented `value_or=
` to begin with.<br><br>The `variant` equivalent of `value_or` is type-chec=
king. That is, checking that your visitor actually has a function for each =
of the states of the variant, <i>including empty</i>. If you don't have=
that check, then you cannot statically know your code works.<br><br>So for=
safety reasons, users will have to check the empty state. And a <i>good</i=
> visitation system will verify that the empty state is checked for. Always=
.. Just like smart compilers will warn you if you switch on an enum and you =
don't check all possible states (and have no default).<br><br>The only =
way to avoid this is to have multiple versions of visitation: `apply_visito=
r` and `apply_visitor_not_empty` or whatever. And... it doesn't even fi=
x the problem because the user can use the wrong one by accident, with no c=
ompile-time check.<br><br>So if you want compile-time checking (and if you =
don't, you <i>should</i>), using a possibly-empty variant will <i>requi=
re</i> all users to handle the empty state in their visitors.<br><br>Or you=
just have a never-empty variant, which can be given a type that represents=
being empty. This solves all of these problems. Code that needs emptiness =
will also be required to check for it, making their code safer. And code th=
at doesn't won't have to check for a state that will never exist.<b=
r><br>The only, <i>only</i> advantage of an enforced empty state is making =
implementing `variant` easier and <i>possibly</i> more efficient. But we=
9;re already proving that a never-empty variant can provide the strong exce=
ption guarantee with relatively minimal overhead.<br></div><div class=3D"">=
<div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--f46d04462e6a625b6505209ada0d--
.
Author: David Krauss <potswa@gmail.com>
Date: Sat, 26 Sep 2015 09:06:30 +0800
Raw View
--Apple-Mail=_866F996F-E67E-42B8-AB9C-7CFCA463D61F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9326, at 12:47 AM, Nicol Bolas <jmckesson@gmail.=
com> wrote:
>=20
> I disagree; never-empty is a highly desirable feature. The problem comes =
from visitation. If I have the simplest of variants, `variant<int, float>`,=
all of my visitor types must handle the empty state.
1. That=E2=80=99s like saying every nullable pointer parameter everywhere n=
eeds to be validated against nullptr every time it enters a function. Maybe=
true on some lofty level, but actual programmers are able to maintain inva=
riants. Nobody is proposing a version of unique_ptr without DefaultConstruc=
tible, although in practice nullptr values seldom live long enough to be ob=
served.
2. A visitor does whatever it does. If it can=E2=80=99t handle disengagemen=
t, then the only thing left is to throw an exception. Actually I don=E2=80=
=99t think any visitor should be allowed to handle disengagement; it should=
not be mapped to an object type for the sake of argument passing.
Disengagement is different from merely representing a value which is empty =
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the wrapped object which is what goes into visitors. The term =
=E2=80=9Cempty state=E2=80=9D is confusingly ambiguous in this way. Treatin=
g the discriminator as a user-accessible scalar value adds to the confusion=
..
--=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/.
--Apple-Mail=_866F996F-E67E-42B8-AB9C-7CFCA463D61F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9326, at 12:47 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail=
..com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple=
-interchange-newline"><div class=3D""><span style=3D"font-family: Helvetica=
; font-size: 12px; font-style: normal; font-variant: normal; font-weight: n=
ormal; letter-spacing: normal; line-height: normal; orphans: auto; text-ali=
gn: start; text-indent: 0px; text-transform: none; white-space: normal; wid=
ows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; =
display: inline !important;" class=3D"">I disagree; never-empty is a highly=
desirable feature. The problem comes from visitation. If I have the simple=
st of variants, `variant<int, float>`, all of my visitor types<span c=
lass=3D"Apple-converted-space"> </span></span><i style=3D"font-family:=
Helvetica; font-size: 12px; font-variant: normal; font-weight: normal; let=
ter-spacing: normal; line-height: normal; orphans: auto; text-align: start;=
text-indent: 0px; text-transform: none; white-space: normal; widows: auto;=
word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D"">must</i><sp=
an style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; fo=
nt-variant: normal; font-weight: normal; letter-spacing: normal; line-heigh=
t: normal; orphans: auto; text-align: start; text-indent: 0px; text-transfo=
rm: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tex=
t-stroke-width: 0px; float: none; display: inline !important;" class=3D""><=
span class=3D"Apple-converted-space"> </span>handle the empty state.</=
span><br style=3D"font-family: Helvetica; font-size: 12px; font-style: norm=
al; font-variant: normal; font-weight: normal; letter-spacing: normal; line=
-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-t=
ransform: none; white-space: normal; widows: auto; word-spacing: 0px; -webk=
it-text-stroke-width: 0px;" class=3D""></div></blockquote></div><br class=
=3D""><div class=3D"">1. That=E2=80=99s like saying every nullable pointer =
parameter everywhere needs to be validated against nullptr every time it en=
ters a function. Maybe true on some lofty level, but actual programmers are=
able to maintain invariants. Nobody is proposing a version of <font face=
=3D"Courier" class=3D"">unique_ptr</font> without DefaultConstructible=
, although in practice <font face=3D"Courier" class=3D"">nullptr</font=
> values seldom live long enough to be observed.</div><div class=3D"">=
<br class=3D""></div><div class=3D"">2. A visitor does whatever it does. If=
it can=E2=80=99t handle disengagement, then the only thing left is to thro=
w an exception. Actually I don=E2=80=99t think <i class=3D"">any</i> v=
isitor should be allowed to handle disengagement; it should not be mapped t=
o an object type for the sake of argument passing.</div><div class=3D""><br=
class=3D""></div><div class=3D"">Disengagement is different from merely re=
presenting a value which is empty of state. The term =E2=80=9Cempty state=
=E2=80=9D appertains to the variant wrapper, not the wrapped object which i=
s what goes into visitors. The term =E2=80=9Cempty state=E2=80=9D is confus=
ingly ambiguous in this way. Treating the discriminator as a user-accessibl=
e scalar value adds to the confusion.</div><div class=3D""><br class=3D""><=
/div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_866F996F-E67E-42B8-AB9C-7CFCA463D61F--
.
Author: Magnus Fromreide <magfr@lysator.liu.se>
Date: Sat, 26 Sep 2015 16:36:58 +0200
Raw View
On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>=20
> Disengagement is different from merely representing a value which is empt=
y
> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the varian=
t wrapper, not the
> wrapped object which is what goes into visitors. The term =E2=80=9Cempty =
state=E2=80=9D is
> confusingly ambiguous in this way. Treating the discriminator as a
> user-accessible scalar value adds to the confusion.
My concern is that I don't want the types variant<T> and optional<T> to be
functionally equivalent, regardless of how variant is implemented.
Now, I have to admit to not having paid all that much attention to the back
and forth of the debate about variant but this should imply that I don't
want to see a publicly accessible empty state in variant.
/MF
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 07:51:06 -0700 (PDT)
Raw View
------=_Part_2694_1059264140.1443279066575
Content-Type: multipart/alternative;
boundary="----=_Part_2695_460991045.1443279066575"
------=_Part_2695_460991045.1443279066575
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:
>
> On 2015=E2=80=9309=E2=80=9326, at 12:47 AM, Nicol Bolas <jmck...@gmail.co=
m <javascript:>>=20
> wrote:
>
> I disagree; never-empty is a highly desirable feature. The problem comes=
=20
> from visitation. If I have the simplest of variants, `variant<int, float>=
`,=20
> all of my visitor types *must* handle the empty state.
>
>
> 1. That=E2=80=99s like saying every nullable pointer parameter everywhere=
needs to=20
> be validated against nullptr every time it enters a function.
>
Is this not the reason why the C++ Core Guidelines library includes=20
`not_null`? Good programming practice these days is to make invariants=20
*statically* visible and checked.
You can freely disagree with these guidelines if you want, of course. But=
=20
people do follow them.
=20
> 2. A visitor does whatever it does. If it can=E2=80=99t handle disengagem=
ent, then=20
> the only thing left is to throw an exception. Actually I don=E2=80=99t th=
ink *any* visitor=20
> should be allowed to handle disengagement; it should not be mapped to an=
=20
> object type for the sake of argument passing.
>
> Disengagement is different from merely representing a value which is empt=
y=20
> of state.
>
Changing the word used does not change the question; we all know what=20
you're talking about. Whether you call it "disengaged", "empty", or=20
whatever, you're saying the same thing: the `variant` type has the=20
possibility of containing *none* of the values in its typelist.
The question is this: why do we *need* to allow variants to be=20
"disengaged/empty/etc"?
The reasons put forth for doing so thus far are:
1) Efficiency. A variant which can be disengaged can implement=20
copy/move/construction operations with zero overhead, simply by becoming=20
disengaged on constructor/assignment failure. Such variants can offer the=
=20
basic exception guarantee essentially for free.
2) Orthogonality with other types (any/optional).
We're already seeing that clever implementations of never-empty variants=20
can be nearly equally efficient as empty-able variants. A never-empty=20
variant can offer the *strong* exception guarantee at minimal cost. And=20
this cost will primarily be born by mis-behaving types (ie: throwing move=
=20
types). So #1, while still *technically* true, has become a lot less=20
convincing of an argument.
As for the other reason... well I just can't find a reason to care.=20
`variant` isn't `any`. `variant` isn't `optional`. This orthogonality=20
argument is ultimately based on trying to make `variant` into something it=
=20
is not intended to be.
Each of these types has a specific purpose, and its interface is designed=
=20
around fulfilling that *specific* purpose. `any` is for passing a value=20
type through code without that code statically knowing the type being=20
passed. `optional` is a value type which may or may not be present.=20
`variant` is for processing values which could assume a number of different=
=20
forms.
None of these are designed to fulfill the functional programming notion of=
=20
"sum types". Those which technically are sum types only achieve that status=
*by=20
accident*. So let's not try to make a thing into something it isn't.
`any` has the concept of being "empty", not to be orthogonal with=20
`function` does. Both of these are allowed to be empty because C++ users=20
need to be able to default-construct types. And since both of these are=20
holders of more-or-less any type, they have no reasonable default state=20
which could be *valid*. Therefore, the choices are to make them not=20
default-constructable at all, or give them an empty state. The latter was=
=20
considered better.
The argument for empty `optional` is *by design*. The whole point of the=20
type is that it can be empty, that it can be T or nothing, which is=20
different from a variable which can only be T.
`variant` has neither of these. There is a perfectly sensible thing to=20
default construct in a `variant`, as defined by the C++ behavior of unions:=
=20
the first type. As such, the argument for allowing empty `any`s does not=20
apply to `variant`.
A `variant` is a type that can be T, U, V, or W. If you need a type that=20
can be T, U, V, W or nothing, then you do exactly what you would if you=20
needed a type that could be T or nothing: combine T with `optional`. You=20
can even stick that in a convenient typedef:
template<typename ...Ts> using opt_variant =3D optional<variant<Ts...>>;
Solving the problem of a type that needs to be "thing or nothing" is *why*=
=20
we invented `optional` in the first place. We shouldn't have to add "or=20
nothing" to all of our types now that we have `optional`.
This also means we don't have to give types default constructors just to=20
satisfy C++ usage anymore. Just declare an `optional` of it, construct it=
=20
empty, then initialize it later on when you're ready to properly do so. You=
=20
can even copy/move out of it when you're ready to pass it to whomever needs=
=20
it.
Do you have any other reasons why we need `variant` to be able to become=20
"disengaged/empty/etc"? Note that I said "need", not "prefer". What *actual=
=20
problems* would such a concept solve for you?
=20
> The term =E2=80=9Cempty state=E2=80=9D appertains to the variant wrapper,=
not the wrapped=20
> object which is what goes into visitors. The term =E2=80=9Cempty state=E2=
=80=9D is=20
> confusingly ambiguous in this way. Treating the discriminator as a=20
> user-accessible scalar value adds to the confusion.
>
.... I agree that directly accessing the discriminator index value is not=20
good design, and attempts to use `which` should fail code review. However,=
=20
some people need it, and if it makes their lives slightly easier at no cost=
=20
to me, let them have it.
Allowing "disengagement" has a cost to me: the cost of verifying such=20
objects. The cost of being `invalid` was one I was willing to pay, because=
=20
one could write variants where it was impossible to achieve such a state.=
=20
However, a general "disengagement" state, one which any variant can easily=
=20
enter simply by default construction?
Absolutely not.
--=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_2695_460991045.1443279066575
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"=
><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=9326, at 12:4=
7 AM, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" gdf-obfusca=
ted-mailto=3D"aEQs0YDmCAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
9;javascript:';return true;" onclick=3D"this.href=3D'javascript:=
9;;return true;">jmck...@gmail.com</a>> wrote:</div><br><div><span style=
=3D"font-family:Helvetica;font-size:12px;font-style:normal;font-variant:nor=
mal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:=
start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0=
px;float:none;display:inline!important">I disagree; never-empty is a highly=
desirable feature. The problem comes from visitation. If I have the simple=
st of variants, `variant<int, float>`, all of my visitor types<span>=
=C2=A0</span></span><i style=3D"font-family:Helvetica;font-size:12px;font-v=
ariant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;t=
ext-align:start;text-indent:0px;text-transform:none;white-space:normal;word=
-spacing:0px">must</i><span style=3D"font-family:Helvetica;font-size:12px;f=
ont-style:normal;font-variant:normal;font-weight:normal;letter-spacing:norm=
al;line-height:normal;text-align:start;text-indent:0px;text-transform:none;=
white-space:normal;word-spacing:0px;float:none;display:inline!important"><s=
pan>=C2=A0</span>handle the empty state.</span><br style=3D"font-family:Hel=
vetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:nor=
mal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0=
px;text-transform:none;white-space:normal;word-spacing:0px"></div></blockqu=
ote></div><br><div>1. That=E2=80=99s like saying every nullable pointer par=
ameter everywhere needs to be validated against nullptr every time it enter=
s a function.</div></div></blockquote><div><br>Is this not the reason why t=
he C++ Core Guidelines library includes `not_null`? Good programming practi=
ce these days is to make invariants <i>statically</i> visible and checked.<=
br><br>You can freely disagree with these guidelines if you want, of course=
.. But people do follow them.<br>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div style=3D"word-wrap:break-word"><div></div><div>2. A visi=
tor does whatever it does. If it can=E2=80=99t handle disengagement, then t=
he only thing left is to throw an exception. Actually I don=E2=80=99t think=
<i>any</i>=C2=A0visitor should be allowed to handle disengagement; it shou=
ld not be mapped to an object type for the sake of argument passing.</div><=
div><br></div><div>Disengagement is different from merely representing a va=
lue which is empty of state.</div></div></blockquote><div><br>Changing the =
word used does not change the question; we all know what you're talking=
about. Whether you call it "disengaged", "empty", or w=
hatever, you're saying the same thing: the `variant` type has the possi=
bility of containing <i>none</i> of the values in its typelist.<br><br>The =
question is this: why do we <i>need</i> to allow variants to be "disen=
gaged/empty/etc"?<br><br>The reasons put forth for doing so thus far a=
re:<br><br>1) Efficiency. A variant which can be disengaged can implement c=
opy/move/construction operations with zero overhead, simply by becoming dis=
engaged on constructor/assignment failure. Such variants can offer the basi=
c exception guarantee essentially for free.<br><br>2) Orthogonality with ot=
her types (any/optional).<br><br>We're already seeing that clever imple=
mentations of never-empty variants can be nearly equally efficient as empty=
-able variants. A never-empty variant can offer the <i>strong</i> exception=
guarantee at minimal cost. And this cost will primarily be born by mis-beh=
aving types (ie: throwing move types). So #1, while still <i>technically</i=
> true, has become a lot less convincing of an argument.<br><br>As for the =
other reason... well I just can't find a reason to care. `variant` isn&=
#39;t `any`. `variant` isn't `optional`. This orthogonality argument is=
ultimately based on trying to make `variant` into something it is not inte=
nded to be.<br><br>Each of these types has a specific purpose, and its inte=
rface is designed around fulfilling that <i>specific</i> purpose. `any` is =
for passing a value type through code without that code statically knowing =
the type being passed. `optional` is a value type which may or may not be p=
resent. `variant` is for processing values which could assume a number of d=
ifferent forms.<br><br>None of these are designed to fulfill the functional=
programming notion of "sum types". Those which technically are s=
um types only achieve that status <i>by accident</i>. So let's not try =
to make a thing into something it isn't.<br><br>`any` has the concept o=
f being "empty", not to be orthogonal with `function` does. Both =
of these are allowed to be empty because C++ users need to be able to defau=
lt-construct types. And since both of these are holders of more-or-less any=
type, they have no reasonable default state which could be <i>valid</i>. T=
herefore, the choices are to make them not default-constructable at all, or=
give them an empty state. The latter was considered better.<br><br>The arg=
ument for empty `optional` is <i>by design</i>. The whole point=20
of the type is that it can be empty, that it can be T or nothing, which=20
is different from a variable which can only be T.<br><br>`variant` has neit=
her of these. There is a perfectly sensible thing to default construct in a=
`variant`, as defined by the C++ behavior of unions: the first type. As su=
ch, the argument for allowing empty `any`s does not apply to `variant`.<br>=
<br>A `variant` is a type that can be T, U, V, or W. If you need a type tha=
t can be T, U, V, W or nothing, then you do exactly what you would if you n=
eeded a type that could be T or nothing: combine T with `optional`. You can=
even stick that in a convenient typedef:<br><br>template<typename ...Ts=
> using opt_variant =3D optional<variant<Ts...>>;<br><br>Sol=
ving the problem of a type that needs to be "thing or nothing" is=
<i>why</i> we invented `optional` in the first place. We shouldn't hav=
e to add "or nothing" to all of our types now that we have `optio=
nal`.<br><br>This also means we don't have to give types default constr=
uctors just to satisfy C++ usage anymore. Just declare an `optional` of it,=
construct it empty, then initialize it later on when you're ready to p=
roperly do so. You can even copy/move out of it when you're ready to pa=
ss it to whomever needs it.<br><br>Do you have any other reasons why we nee=
d `variant` to be able to become "disengaged/empty/etc"? Note tha=
t I said "need", not "prefer". What <i>actual problems<=
/i> would such a concept solve for you?<br>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div>The term =
=E2=80=9Cempty state=E2=80=9D appertains to the variant wrapper, not the wr=
apped object which is what goes into visitors. The term =E2=80=9Cempty stat=
e=E2=80=9D is confusingly ambiguous in this way. Treating the discriminator=
as a user-accessible scalar value adds to the confusion.</div></div></bloc=
kquote><div><br>... I agree that directly accessing the discriminator index=
value is not good design, and attempts to use `which` should fail code rev=
iew. However, some people need it, and if it makes their lives slightly eas=
ier at no cost to me, let them have it.<br><br>Allowing "disengagement=
" has a cost to me: the cost of verifying such objects. The cost of be=
ing `invalid` was one I was willing to pay, because one could write variant=
s where it was impossible to achieve such a state. However, a general "=
;disengagement" state, one which any variant can easily enter simply b=
y default construction?<br><br>Absolutely not.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_2695_460991045.1443279066575--
------=_Part_2694_1059264140.1443279066575--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sat, 26 Sep 2015 11:58:02 -0300
Raw View
On 9/26/2015 11:36 AM, Magnus Fromreide wrote:
> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>
>> Disengagement is different from merely representing a value which is emp=
ty
>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the varia=
nt wrapper, not the
>> wrapped object which is what goes into visitors. The term =E2=80=9Cempty=
state=E2=80=9D is
>> confusingly ambiguous in this way. Treating the discriminator as a
>> user-accessible scalar value adds to the confusion.
>
> My concern is that I don't want the types variant<T> and optional<T> to b=
e
> functionally equivalent, regardless of how variant is implemented.
The fundamental model for `optional<T>` is a union of `nullopt_t` and=20
`T`, so it would be reasonable to expect `variant<nullopt_t, T>` to be=20
functionally equivalent.
> Now, I have to admit to not having paid all that much attention to the ba=
ck
> and forth of the debate about variant but this should imply that I don't
> want to see a publicly accessible empty state in variant.
This does not seem to be related to `optional<T>`, which does not have=20
an empty state. Instead, it defines its active member changing semantics=20
as first switch to `nullopt_t`, then act.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 08:04:17 -0700 (PDT)
Raw View
------=_Part_209_1152813331.1443279857192
Content-Type: multipart/alternative;
boundary="----=_Part_210_409928705.1443279857193"
------=_Part_210_409928705.1443279857193
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 10:58:02 AM UTC-4, Agust=C3=ADn K-ballo =
Berg=C3=A9=20
wrote:
>
> On 9/26/2015 11:36 AM, Magnus Fromreide wrote:=20
> > On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:=20
> >>=20
> >> Disengagement is different from merely representing a value which is=
=20
> empty=20
> >> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the var=
iant wrapper, not=20
> the=20
> >> wrapped object which is what goes into visitors. The term =E2=80=9Cemp=
ty state=E2=80=9D=20
> is=20
> >> confusingly ambiguous in this way. Treating the discriminator as a=20
> >> user-accessible scalar value adds to the confusion.=20
> >=20
> > My concern is that I don't want the types variant<T> and optional<T> to=
=20
> be=20
> > functionally equivalent, regardless of how variant is implemented.=20
>
> The fundamental model for `optional<T>` is a union of `nullopt_t` and=20
> `T`, so it would be reasonable to expect `variant<nullopt_t, T>` to be=20
> functionally equivalent.
>
Agreed, in terms of "functional equivalence" (obviously, they need not use=
=20
the same interface). His point was that `variant<T>` shouldn't be the same=
=20
thing; if you want a union of nullopt_t and T, you should have to=20
explicitly state it with `variant`.
--=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_210_409928705.1443279857193
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 10:58:02 AM UTC-4, Agust=C3=ADn K-ballo =
Berg=C3=A9 wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 9/26/2015 =
11:36 AM, Magnus Fromreide wrote:
<br>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
<br>>>
<br>>> Disengagement is different from merely representing a value wh=
ich is empty
<br>>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to=
the variant wrapper, not the
<br>>> wrapped object which is what goes into visitors. The term =E2=
=80=9Cempty state=E2=80=9D is
<br>>> confusingly ambiguous in this way. Treating the discriminator =
as a
<br>>> user-accessible scalar value adds to the confusion.
<br>>
<br>> My concern is that I don't want the types variant<T> and=
optional<T> to be
<br>> functionally equivalent, regardless of how variant is implemented.
<br>
<br>The fundamental model for `optional<T>` is a union of `nullopt_t`=
and=20
<br>`T`, so it would be reasonable to expect `variant<nullopt_t, T>` =
to be=20
<br>functionally equivalent.<br></blockquote><div><br>Agreed, in terms of &=
quot;functional equivalence" (obviously, they need not use the same in=
terface). His point was that `variant<T>` shouldn't be the same t=
hing; if you want a union of nullopt_t and T, you should have to explicitly=
state it with `variant`.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_210_409928705.1443279857193--
------=_Part_209_1152813331.1443279857192--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 26 Sep 2015 18:37:27 +0200
Raw View
This is a multi-part message in MIME format.
--------------000502040305010009090301
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>> Disengagement is different from merely representing a value which is emp=
ty
>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the varia=
nt wrapper, not the
>> wrapped object which is what goes into visitors. The term =E2=80=9Cempty=
state=E2=80=9D is
>> confusingly ambiguous in this way. Treating the discriminator as a
>> user-accessible scalar value adds to the confusion.
> My concern is that I don't want the types variant<T> and optional<T> to b=
e
> functionally equivalent, regardless of how variant is implemented.
You mean variant<nullopt_t,T> and optional<T> isn't it?
I like to see optional<T> as a specialization of variant<nullopt_t, T>=20
providing an interface similar to a smart pointer to T.
I like to see visitation on sum types as pattern matching, so when=20
visiting an optional<T>, I would like to handle disengagement by=20
matching the nullopt_t type.
Vicente
--=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/.
--------------000502040305010009090301
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 26/09/15 16:36, Magnus Fromreide a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote cite=3D"mid:20150926143658.GA27361@noemi" type=3D"cite">
<pre wrap=3D"">On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss=
wrote:
</pre>
<blockquote type=3D"cite">
<pre wrap=3D"">
Disengagement is different from merely representing a value which is empty
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is
confusingly ambiguous in this way. Treating the discriminator as a
user-accessible scalar value adds to the confusion.
</pre>
</blockquote>
<pre wrap=3D"">
My concern is that I don't want the types variant<T> and optional<=
T> to be
functionally equivalent, regardless of how variant is implemented.</pre>
</blockquote>
You mean variant<nullopt_t,T> and optional<T> isn't it?<br>
<br>
<font size=3D"+1">I like to see optional<T> as a specialization
of variant<nullopt_t, T> providing an interface similar to a
smart pointer to T.<br>
<br>
</font><font size=3D"+1">I like to see visitation on sum types as
pattern matching, so when visiting an optional<T>, I would
like to handle disengagement by matching the nullopt_t </font><font
size=3D"+1"><font size=3D"+1">type</font>.<br>
<br>
Vicente<br>
</font>
</body>
</html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--------------000502040305010009090301--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 26 Sep 2015 19:10:31 +0200
Raw View
Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :
> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:
>> On 2015=E2=80=9309=E2=80=9326, at 12:47 AM, Nicol Bolas <jmck...@gmail.c=
om <javascript:>>
>> wrote:
>>
>> I disagree; never-empty is a highly desirable feature. The problem comes
>> from visitation. If I have the simplest of variants, `variant<int, float=
>`,
>> all of my visitor types *must* handle the empty state.
>>
>>
>> 1. That=E2=80=99s like saying every nullable pointer parameter everywher=
e needs to
>> be validated against nullptr every time it enters a function.
>>
> Is this not the reason why the C++ Core Guidelines library includes
> `not_null`? Good programming practice these days is to make invariants
> *statically* visible and checked.
>
> You can freely disagree with these guidelines if you want, of course. But
> people do follow them.
> =20
>
>> 2. A visitor does whatever it does. If it can=E2=80=99t handle disengage=
ment, then
>> the only thing left is to throw an exception. Actually I don=E2=80=99t t=
hink *any* visitor
>> should be allowed to handle disengagement; it should not be mapped to an
>> object type for the sake of argument passing.
>>
>> Disengagement is different from merely representing a value which is emp=
ty
>> of state.
>>
> Changing the word used does not change the question; we all know what
> you're talking about. Whether you call it "disengaged", "empty", or
> whatever, you're saying the same thing: the `variant` type has the
> possibility of containing *none* of the values in its typelist.
I'm for variant<Ts...> been never-empty and without the invalid-state.=20
However I see the need to have also a variadic optional call it=20
discriminated_union<Ts...>, optionals<Ts...> or whatever we find more=20
appropriated.
> The question is this: why do we *need* to allow variants to be
> "disengaged/empty/etc"?
>
> The reasons put forth for doing so thus far are:
>
> 1) Efficiency. A variant which can be disengaged can implement
> copy/move/construction operations with zero overhead, simply by becoming
> disengaged on constructor/assignment failure. Such variants can offer the
> basic exception guarantee essentially for free.
>
> 2) Orthogonality with other types (any/optional).
>
> We're already seeing that clever implementations of never-empty variants
> can be nearly equally efficient as empty-able variants. A never-empty
> variant can offer the *strong* exception guarantee at minimal cost. And
> this cost will primarily be born by mis-behaving types (ie: throwing move
> types). So #1, while still *technically* true, has become a lot less
> convincing of an argument.
>
> As for the other reason... well I just can't find a reason to care.
> `variant` isn't `any`. `variant` isn't `optional`. This orthogonality
> argument is ultimately based on trying to make `variant` into something i=
t
> is not intended to be.
Let me see if the following use case. While handling an any we could=20
only be interested in some specific types, e.g. A and B and be able to=20
visit this any for these possible types.
any a =3D ...;
// ...
auto& x =3D select<A,B>(a);
Note this select function is something similar to the try_recover from=20
David.
I would like the type of x to behave as a possible null variant of A and=20
B. When the any stores a type other than A or B is as if it stored=20
nullopt_t.
> Each of these types has a specific purpose, and its interface is designed
> around fulfilling that *specific* purpose. `any` is for passing a value
> type through code without that code statically knowing the type being
> passed. `optional` is a value type which may or may not be present.
> `variant` is for processing values which could assume a number of differe=
nt
> forms.
>
> None of these are designed to fulfill the functional programming notion o=
f
> "sum types". Those which technically are sum types only achieve that stat=
us *by
> accident*. So let's not try to make a thing into something it isn't.
I agree for any, but not for optional<T>.
>
> `any` has the concept of being "empty", not to be orthogonal with
> `function` does. Both of these are allowed to be empty because C++ users
> need to be able to default-construct types. And since both of these are
> holders of more-or-less any type, they have no reasonable default state
> which could be *valid*. Therefore, the choices are to make them not
> default-constructable at all, or give them an empty state. The latter was
> considered better.
>
> The argument for empty `optional` is *by design*. The whole point of the
> type is that it can be empty, that it can be T or nothing, which is
> different from a variable which can only be T.
>
> `variant` has neither of these. There is a perfectly sensible thing to
> default construct in a `variant`, as defined by the C++ behavior of union=
s:
> the first type. As such, the argument for allowing empty `any`s does not
> apply to `variant`.
>
> A `variant` is a type that can be T, U, V, or W. If you need a type that
> can be T, U, V, W or nothing, then you do exactly what you would if you
> needed a type that could be T or nothing: combine T with `optional`. You
> can even stick that in a convenient typedef:
>
> template<typename ...Ts> using opt_variant =3D optional<variant<Ts...>>;
>
> Solving the problem of a type that needs to be "thing or nothing" is *why=
*
> we invented `optional` in the first place. We shouldn't have to add "or
> nothing" to all of our types now that we have `optional`.
I understand that orthogonality is good.
I don't think that this means that we need to add opt_ for all the types=20
if we don't obtain something better than optional<T>.
However nesting sum types should be equivalent to a flatten sum type
optional<variant<Ts...>>
variant<nullopt_t, variant<Ts...>>
variant<nullopt_t, Ts...>
I believe that in the same way that we have optional<T> providing a=20
better and more specific interface than variant<nullopt_t, T>, we need
optionals<Ts...> or discriminated_union<Ts...> as a separated class that=20
provide a better and more specific interface.
Note that I'm not suggesting to specialize the behavior for=20
variant<nullopt_t, Ts...>, as we did for vector<bool>
>
> This also means we don't have to give types default constructors just to
> satisfy C++ usage anymore. Just declare an `optional` of it, construct it
> empty, then initialize it later on when you're ready to properly do so. Y=
ou
> can even copy/move out of it when you're ready to pass it to whomever nee=
ds
> it.
>
> Do you have any other reasons why we need `variant` to be able to become
> "disengaged/empty/etc"? Note that I said "need", not "prefer". What *actu=
al
> problems* would such a concept solve for you?
optionals<Ts...> can be implemented more efficiently than=20
optional<variants<Ts...>>, but I want it to be a model of sum type=20
nullopt_t + Ts... and be able to visit it all at once. I don't want to=20
have to check if the optional is engaged and only then do visit the=20
stored value.
> =20
>
>> The term =E2=80=9Cempty state=E2=80=9D appertains to the variant wrapper=
, not the wrapped
>> object which is what goes into visitors. The term =E2=80=9Cempty state=
=E2=80=9D is
>> confusingly ambiguous in this way. Treating the discriminator as a
>> user-accessible scalar value adds to the confusion.
>>
> ... I agree that directly accessing the discriminator index value is not
> good design, and attempts to use `which` should fail code review. However=
,
> some people need it, and if it makes their lives slightly easier at no co=
st
> to me, let them have it.
>
> Allowing "disengagement" has a cost to me: the cost of verifying such
> objects. The cost of being `invalid` was one I was willing to pay, becaus=
e
> one could write variants where it was impossible to achieve such a state.
> However, a general "disengagement" state, one which any variant can easil=
y
> enter simply by default construction?
>
> Absolutely not.
>
I don't understand why we can not have both. variant never empty and=20
discriminated_union/optionals possibly empty.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 27 Sep 2015 01:16:49 +0800
Raw View
--Apple-Mail=_CB8DFDFF-83D7-4916-B5AC-A409753B5123
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9326, at 10:51 PM, Nicol Bolas <jmckesson@gmail.=
com> wrote:
>=20
> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:
>=20
> 1. That=E2=80=99s like saying every nullable pointer parameter everywhere=
needs to be validated against nullptr every time it enters a function.
>=20
> Is this not the reason why the C++ Core Guidelines library includes `not_=
null`? Good programming practice these days is to make invariants staticall=
y visible and checked.
>=20
> You can freely disagree with these guidelines if you want, of course. But=
people do follow them.
Some people. In any case, the one(s) who added it to that library.
No such thing has been proposed for the standard =E2=80=94 as I mentioned j=
ust after that quote cuts off. That=E2=80=99s a far cry from a shoo-in requ=
irement on new standard types.
> The question is this: why do we need to allow variants to be "disengaged/=
empty/etc=E2=80=9D?
Exceptions. Unless you want to bring Boost=E2=80=99s heap double-buffering =
back from the dead or to double sizeof(variant).
If the implementations are getting cleverer, then I=E2=80=99ll happily revi=
ew the state of the art, after the next meeting. In the meantime, it seems =
safe to prioritize things that might make immediate progress.
--=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/.
--Apple-Mail=_CB8DFDFF-83D7-4916-B5AC-A409753B5123
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9326, at 10:51 PM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail=
..com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple=
-interchange-newline"><div class=3D"">On Friday, September 25, 2015 at 9:06=
:36 PM UTC-4, David Krauss wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;"><div style=3D"word-wrap:break-word" class=3D""><br class=3D""><div class=
=3D"">1. That=E2=80=99s like saying every nullable pointer parameter everyw=
here needs to be validated against nullptr every time it enters a function.=
</div></div></blockquote><div class=3D""><br class=3D"">Is this not the rea=
son why the C++ Core Guidelines library includes `not_null`? Good programmi=
ng practice these days is to make invariants <i class=3D"">statically</i> v=
isible and checked.<br class=3D""><br class=3D"">You can freely disagree wi=
th these guidelines if you want, of course. But people do follow them.<br c=
lass=3D""></div></div></blockquote><div><br class=3D""></div><div>Some peop=
le. In any case, the one(s) who added it to that library.</div><div><br cla=
ss=3D""></div><div>No such thing has been proposed for the standard =E2=80=
=94 as I mentioned just after that quote cuts off. That=E2=80=99s a far cry=
from a shoo-in requirement on new standard types.</div><br class=3D""><blo=
ckquote type=3D"cite" class=3D""><div class=3D""><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div style=3D"word-wrap:break-word" class=3D""><div clas=
s=3D""></div></div></blockquote><div class=3D"">The question is this: why d=
o we <i class=3D"">need</i> to allow variants to be "disengaged/empty/etc=
=E2=80=9D?<br class=3D""></div></div></blockquote></div><br class=3D""><div=
class=3D"">Exceptions. Unless you want to bring Boost=E2=80=99s heap doubl=
e-buffering back from the dead or to double <font face=3D"Courier" class=3D=
"">sizeof(variant)</font>.</div><div class=3D""><br class=3D""></div><div c=
lass=3D"">If the implementations are getting cleverer, then I=E2=80=99ll ha=
ppily review the state of the art, after the next meeting. In the meantime,=
it seems safe to prioritize things that might make immediate progress.</di=
v><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_CB8DFDFF-83D7-4916-B5AC-A409753B5123--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 26 Sep 2015 19:21:33 +0200
Raw View
Le 26/09/15 19:10, Vicente J. Botet Escriba a =C3=A9crit :
> Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :
>> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:
>
>>
>> This also means we don't have to give types default constructors just to
>> satisfy C++ usage anymore. Just declare an `optional` of it,=20
>> construct it
>> empty, then initialize it later on when you're ready to properly do=20
>> so. You
>> can even copy/move out of it when you're ready to pass it to whomever=20
>> needs
>> it.
>>
>> Do you have any other reasons why we need `variant` to be able to become
>> "disengaged/empty/etc"? Note that I said "need", not "prefer". What=20
>> *actual
>> problems* would such a concept solve for you?
> optionals<Ts...> can be implemented more efficiently than=20
> optional<variants<Ts...>>, but I want it to be a model of sum type=20
> nullopt_t + Ts... and be able to visit it all at once. I don't want to=20
> have to check if the optional is engaged and only then do visit the=20
> stored value.
I want to be able to visit nullable variants like
optionals<T1, T2> o =3D ...;
auto x=3D match(o,
[](nullopt_t)->U {...},
[](T1)->U {...},
[](T2)->U {...}
);
See the proposal P0050: A Generic C++ match function .
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 11:06:54 -0700 (PDT)
Raw View
------=_Part_3054_683995080.1443290814111
Content-Type: multipart/alternative;
boundary="----=_Part_3055_2046639679.1443290814118"
------=_Part_3055_2046639679.1443290814118
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 1:10:34 PM UTC-4, Vicente J. Botet=20
Escriba wrote:
>
> Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :=20
> > On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:=
=20
> >> On 2015=E2=80=9309=E2=80=9326, at 12:47 AM, Nicol Bolas <jmck...@gmail=
..com=20
> <javascript:>>=20
> >> wrote:=20
> >>=20
> >> I disagree; never-empty is a highly desirable feature. The problem=20
> comes=20
> >> from visitation. If I have the simplest of variants, `variant<int,=20
> float>`,=20
> >> all of my visitor types *must* handle the empty state.=20
> >>=20
> >>=20
> >> 1. That=E2=80=99s like saying every nullable pointer parameter everywh=
ere needs=20
> to=20
> >> be validated against nullptr every time it enters a function.=20
> >>=20
> > Is this not the reason why the C++ Core Guidelines library includes=20
> > `not_null`? Good programming practice these days is to make invariants=
=20
> > *statically* visible and checked.=20
> >=20
> > You can freely disagree with these guidelines if you want, of course.=
=20
> But=20
> > people do follow them.=20
> > =20
> >=20
> >> 2. A visitor does whatever it does. If it can=E2=80=99t handle disenga=
gement,=20
> then=20
> >> the only thing left is to throw an exception. Actually I don=E2=80=99t=
think=20
> *any* visitor=20
> >> should be allowed to handle disengagement; it should not be mapped to=
=20
> an=20
> >> object type for the sake of argument passing.=20
> >>=20
> >> Disengagement is different from merely representing a value which is=
=20
> empty=20
> >> of state.=20
> >>=20
> > Changing the word used does not change the question; we all know what=
=20
> > you're talking about. Whether you call it "disengaged", "empty", or=20
> > whatever, you're saying the same thing: the `variant` type has the=20
> > possibility of containing *none* of the values in its typelist.=20
> I'm for variant<Ts...> been never-empty and without the invalid-state.=20
> However I see the need to have also a variadic optional call it=20
> discriminated_union<Ts...>, optionals<Ts...> or whatever we find more=20
> appropriated.
>
.... why? Why do we need to add more types for something that's as simple as=
=20
`optional<variant<Ts...>>` (if you want disengagement rather than an=20
explicit empty state) or `variant<monostate, Ts...>` (if you want an empty=
=20
state)?
I'll explain below why these are two different things.
=20
> > The question is this: why do we *need* to allow variants to be=20
> > "disengaged/empty/etc"?=20
> >=20
> > The reasons put forth for doing so thus far are:=20
> >=20
> > 1) Efficiency. A variant which can be disengaged can implement=20
> > copy/move/construction operations with zero overhead, simply by becomin=
g=20
> > disengaged on constructor/assignment failure. Such variants can offer=
=20
> the=20
> > basic exception guarantee essentially for free.=20
> >=20
> > 2) Orthogonality with other types (any/optional).=20
> >=20
> > We're already seeing that clever implementations of never-empty variant=
s=20
> > can be nearly equally efficient as empty-able variants. A never-empty=
=20
> > variant can offer the *strong* exception guarantee at minimal cost. And=
=20
> > this cost will primarily be born by mis-behaving types (ie: throwing=20
> move=20
> > types). So #1, while still *technically* true, has become a lot less=20
> > convincing of an argument.=20
> >=20
> > As for the other reason... well I just can't find a reason to care.=20
> > `variant` isn't `any`. `variant` isn't `optional`. This orthogonality=
=20
> > argument is ultimately based on trying to make `variant` into something=
=20
> it=20
> > is not intended to be.=20
> Let me see if the following use case. While handling an any we could=20
> only be interested in some specific types, e.g. A and B and be able to=20
> visit this any for these possible types.=20
>
> any a =3D ...;=20
> // ...=20
> auto& x =3D select<A,B>(a);=20
>
> Note this select function is something similar to the try_recover from=20
> David.=20
>
> I would like the type of x to behave as a possible null variant of A and=
=20
> B. When the any stores a type other than A or B is as if it stored=20
> nullopt_t.
>
To me, `any` is all about type hiding; it's purely a type-safe void* with=
=20
value semantics. It's about the source and destination knowing what needs=
=20
to be given, but wanting the code in-between to be able to be type-agnostic=
..
Consider a message passing system, where specific message types communicate=
=20
with `any`, but the message system itself doesn't care what the type=20
actually is. `void*`s have been common ways to handle this, but `any` is an=
=20
alternative that works so much better.
If I had an `any` receiver that could be given one of a number of types, I=
=20
would rather build that concept in layers. That is, use the `any` to do=20
type hiding, but the value within that `any` would be a `variant<A, B>`. At=
=20
the destination site, you extract the variant and perform visitation as=20
normal.
That way, if the caller adds types to the `variant`, the eventual receiver=
=20
will fail to execute. *Always* fail to execute, not just when it is given=
=20
the wrong type. It will be broken until that code is properly updated to=20
use the new `variant`. Making such a change breaks the contract between the=
=20
source and destination, and that code should be as noisily broken as=20
possible until the contract is re-established.
Visitation is a concept that should be applied to types that can only=20
assume a specific bounded set. Not those that could contain anything.
=20
> > This also means we don't have to give types default constructors just t=
o=20
> > satisfy C++ usage anymore. Just declare an `optional` of it, construct=
=20
> it=20
> > empty, then initialize it later on when you're ready to properly do so.=
=20
> You=20
> > can even copy/move out of it when you're ready to pass it to whomever=
=20
> needs=20
> > it.=20
> >=20
> > Do you have any other reasons why we need `variant` to be able to becom=
e=20
> > "disengaged/empty/etc"? Note that I said "need", not "prefer". What=20
> *actual=20
> > problems* would such a concept solve for you?=20
> optionals<Ts...> can be implemented more efficiently than=20
> optional<variants<Ts...>>, but I want it to be a model of sum type=20
> nullopt_t + Ts... and be able to visit it all at once. I don't want to=20
> have to check if the optional is engaged and only then do visit the=20
> stored value.
>
Why not?
To me, there's a big difference between `optional<variant<Ts...>>` and=20
`variant<monostate, Ts...>`
In the former case, what you have is a value which may or may not be=20
present. If it is present, it exists in one of a number of states.
In the latter case, what you have is a value which exists in one of a=20
number of states, with one of those states *conceptually* being "empty". It=
=20
is empty because the user of it decides that it means nothing, not because=
=20
the `variant` declares it so.
In the former case, my visitor for the `variant` does not need to check for=
=20
the disengaged state, because the caller had to do that in order to fetch=
=20
the variant value at all. In the latter case, my visitor *must* check for=
=20
the empty state, because it is in the typelist and all elements in the=20
typelist are statically verified by the visitation function.
These are two different syntaxes that spell out two different types that=20
mean *two different things* to the user. They both have genuinely valid use=
=20
cases, so you should not prefer one to the other.
There are more reasons why you don't want to automatically convert=20
`optional<variant<Ts...>>` into `variant<nullopt_t, Ts...>`. One is simple=
=20
practicality; you throw off the entire index count by doing this. Index 0=
=20
suddenly means the `nullopt_t`, rather than the first Ts.
Another reason being that you won't be able to do this:
optional<variant<Ts...>> opt_v =3D ...;
if(opt_v)
{
auto &v =3D opt_v.value();
//Use `v` as a non-empty variant.
}
Your way would require a copy, rather than a reference.
Nor can you pull this one off:
optional<variant<Ts...>> opt_v =3D ...;
auto v =3D std::move(opt_v).value_or(variant<Ts...>{});
I see absolutely no reason to forbid either of these. Notice that if you=20
replace `variant<Ts...>` with some arbitrary type `T`, the above code would=
=20
work just fine. I don't see why we should have `optional` suddenly=20
transform its entire meaning just because the `T` is different.
We did that with `vector<bool>`, remember? And we suffered no end of pain=
=20
because of it.
=20
> > =20
> >=20
> >> The term =E2=80=9Cempty state=E2=80=9D appertains to the variant wrapp=
er, not the=20
> wrapped=20
> >> object which is what goes into visitors. The term =E2=80=9Cempty state=
=E2=80=9D is=20
> >> confusingly ambiguous in this way. Treating the discriminator as a=20
> >> user-accessible scalar value adds to the confusion.=20
> >>=20
> > ... I agree that directly accessing the discriminator index value is no=
t=20
> > good design, and attempts to use `which` should fail code review.=20
> However,=20
> > some people need it, and if it makes their lives slightly easier at no=
=20
> cost=20
> > to me, let them have it.=20
> >=20
> > Allowing "disengagement" has a cost to me: the cost of verifying such=
=20
> > objects. The cost of being `invalid` was one I was willing to pay,=20
> because=20
> > one could write variants where it was impossible to achieve such a=20
> state.=20
> > However, a general "disengagement" state, one which any variant can=20
> easily=20
> > enter simply by default construction?=20
> >=20
> > Absolutely not.=20
> >=20
> I don't understand why we can not have both. variant never empty and=20
> discriminated_union/optionals possibly empty.=20
>
Because a never-empty variant can represent a possibly empty variant just=
=20
fine; simply give it a state that means "empty". We don't need a whole new=
=20
class just for that.=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_3055_2046639679.1443290814118
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 1:10:34 PM UTC-4, Vicente J. Botet Escri=
ba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Le 26/09/15 16:51, Ni=
col Bolas a =C3=A9crit :
<br>> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wr=
ote:
<br>>> On 2015=E2=80=9309=E2=80=9326, at 12:47 AM, Nicol Bolas <<a=
>jmck...@gmail.com</a> <javascript:>>
<br>>> wrote:
<br>>>
<br>>> I disagree; never-empty is a highly desirable feature. The pro=
blem comes
<br>>> from visitation. If I have the simplest of variants, `variant&=
lt;int, float>`,
<br>>> all of my visitor types *must* handle the empty state.
<br>>>
<br>>>
<br>>> 1. That=E2=80=99s like saying every nullable pointer parameter=
everywhere needs to
<br>>> be validated against nullptr every time it enters a function.
<br>>>
<br>> Is this not the reason why the C++ Core Guidelines library include=
s
<br>> `not_null`? Good programming practice these days is to make invari=
ants
<br>> *statically* visible and checked.
<br>>
<br>> You can freely disagree with these guidelines if you want, of cour=
se. But
<br>> people do follow them.
<br>> =C2=A0=20
<br>>
<br>>> 2. A visitor does whatever it does. If it can=E2=80=99t handle=
disengagement, then
<br>>> the only thing left is to throw an exception. Actually I don=
=E2=80=99t think *any* visitor
<br>>> should be allowed to handle disengagement; it should not be ma=
pped to an
<br>>> object type for the sake of argument passing.
<br>>>
<br>>> Disengagement is different from merely representing a value wh=
ich is empty
<br>>> of state.
<br>>>
<br>> Changing the word used does not change the question; we all know w=
hat
<br>> you're talking about. Whether you call it "disengaged&quo=
t;, "empty", or
<br>> whatever, you're saying the same thing: the `variant` type has=
the
<br>> possibility of containing *none* of the values in its typelist.
<br>I'm for variant<Ts...> been never-empty and without the inval=
id-state.=20
<br>However I see the need to have also a variadic optional call it=20
<br>discriminated_union<Ts...>, optionals<Ts...> or whatever we=
find more=20
<br>appropriated.<br></blockquote><div><br>... why? Why do we need to add m=
ore types for something that's as simple as `optional<variant<Ts.=
...>>` (if you want disengagement rather than an explicit empty state)=
or `variant<monostate, Ts...>` (if you want an empty state)?<br><br>=
I'll explain below why these are two different things.<br>=C2=A0</div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;">> The question is this: why =
do we *need* to allow variants to be
<br>> "disengaged/empty/etc"?
<br>>
<br>> The reasons put forth for doing so thus far are:
<br>>
<br>> 1) Efficiency. A variant which can be disengaged can implement
<br>> copy/move/construction operations with zero overhead, simply by be=
coming
<br>> disengaged on constructor/assignment failure. Such variants can of=
fer the
<br>> basic exception guarantee essentially for free.
<br>>
<br>> 2) Orthogonality with other types (any/optional).
<br>>
<br>> We're already seeing that clever implementations of never-empt=
y variants
<br>> can be nearly equally efficient as empty-able variants. A never-em=
pty
<br>> variant can offer the *strong* exception guarantee at minimal cost=
.. And
<br>> this cost will primarily be born by mis-behaving types (ie: throwi=
ng move
<br>> types). So #1, while still *technically* true, has become a lot le=
ss
<br>> convincing of an argument.
<br>>
<br>> As for the other reason... well I just can't find a reason to =
care.
<br>> `variant` isn't `any`. `variant` isn't `optional`. This or=
thogonality
<br>> argument is ultimately based on trying to make `variant` into some=
thing it
<br>> is not intended to be.
<br>Let me see if the following use case. While handling an any we could=20
<br>only be interested in some specific types, e.g. A and B and be able to=
=20
<br>visit this any for these possible types.
<br>
<br>any a =3D ...;
<br>// ...
<br>auto& x =3D select<A,B>(a);
<br>
<br>Note this select function is something similar to the try_recover from=
=20
<br>David.
<br>
<br>I would like the type of x to behave as a possible null variant of A an=
d=20
<br>B. When the any stores a type other than A or B is as if it stored=20
<br>nullopt_t.<br></blockquote><div><br>To me, `any` is all about type hidi=
ng; it's purely a type-safe void* with value semantics. It's about =
the source and destination knowing what needs to be given, but wanting the =
code in-between to be able to be type-agnostic.<br><br>Consider a message p=
assing system, where specific message types communicate with `any`, but the=
message system itself doesn't care what the type actually is. `void*`s=
have been common ways to handle this, but `any` is an alternative that wor=
ks so much better.<br><br>If I had an `any` receiver that could be given on=
e of a number of types, I would rather build that concept in layers. That i=
s, use the `any` to do type hiding, but the value within that `any` would b=
e a `variant<A, B>`. At the destination site, you extract the variant=
and perform visitation as normal.<br><br>That way, if the caller adds type=
s to the `variant`, the eventual receiver will fail to execute. <i>Always</=
i> fail to execute, not just when it is given the wrong type. It will be br=
oken until that code is properly updated to use the new `variant`. Making s=
uch a change breaks the contract between the source and destination, and th=
at code should be as noisily broken as possible until the contract is re-es=
tablished.<br><br>Visitation is a concept that should be applied to types t=
hat can only assume a specific bounded set. Not those that could contain an=
ything.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
> This also means we don't have to give types default constructors j=
ust to
<br>> satisfy C++ usage anymore. Just declare an `optional` of it, const=
ruct it
<br>> empty, then initialize it later on when you're ready to proper=
ly do so. You
<br>> can even copy/move out of it when you're ready to pass it to w=
homever needs
<br>> it.
<br>>
<br>> Do you have any other reasons why we need `variant` to be able to =
become
<br>> "disengaged/empty/etc"? Note that I said "need"=
;, not "prefer". What *actual
<br>> problems* would such a concept solve for you?
<br>optionals<Ts...> can be implemented more efficiently than=20
<br>optional<variants<Ts...>>, but I want it to be a model of s=
um type=20
<br>nullopt_t + Ts... and be able to visit it all at once. I don't want=
to=20
<br>have to check if the optional is engaged and only then do visit the=20
<br>stored value.<br></blockquote><div><br>Why not?<br><br>To me, there'=
;s a big difference between `optional<variant<Ts...>>` and `var=
iant<monostate, Ts...>`<br><br>In the former case, what you have is a=
value which may or may not be present. If it is present, it exists in one =
of a number of states.<br><br>In the latter case, what you have is a value =
which exists in one of a number of states, with one of those states <i>conc=
eptually</i> being "empty". It is empty because the user of it de=
cides that it means nothing, not because the `variant` declares it so.<br><=
br>In the former case, my visitor for the `variant` does not need to check =
for the disengaged state, because the caller had to do that in order to fet=
ch the variant value at all. In the latter case, my visitor <i>must</i> che=
ck for the empty state, because it is in the typelist and all elements in t=
he typelist are statically verified by the visitation function.<br><br>Thes=
e are two different syntaxes that spell out two different types that mean <=
i>two different things</i> to the user. They both have genuinely valid use =
cases, so you should not prefer one to the other.<br><br>There are more rea=
sons why you don't want to automatically convert `optional<variant&l=
t;Ts...>>` into `variant<nullopt_t, Ts...>`. One is simple prac=
ticality; you throw off the entire index count by doing this. Index 0 sudde=
nly means the `nullopt_t`, rather than the first Ts.<br><br>Another reason =
being that you won't be able to do this:<br><br><div class=3D"prettypri=
nt" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 1=
87, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><=
code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">optional</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">variant</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify"><</span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Ts</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">...>></span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> opt_v </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">..=
..;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">opt_v</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&</span><span style=3D"color: #000;" class=3D"styled-by-prettify">v </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> opt_v</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">value</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 </span><span style=3D"color: #800=
;" class=3D"styled-by-prettify">//Use `v` as a non-empty variant.</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></div=
><br>Your way would require a copy, rather than a reference.<br><br>Nor can=
you pull this one off:<br><br><div class=3D"prettyprint" style=3D"backgrou=
nd-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-styl=
e: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyp=
rint"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">optional</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">variant</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify"><</span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">Ts</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...>=
;></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> opt_=
v </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</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></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> v </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">move</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">opt_v</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">).</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">value_or</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">variant</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #6=
06;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">...>{});</span></div></code></div><br>I see ab=
solutely no reason to forbid either of these. Notice that if you replace `v=
ariant<Ts...>` with some arbitrary type `T`, the above code would wor=
k just fine. I don't see why we should have `optional` suddenly transfo=
rm its entire meaning just because the `T` is different.<br><br>We did that=
with `vector<bool>`, remember? And we suffered no end of pain becaus=
e of it.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> =
=C2=A0=20
<br>>
<br>>> The term =E2=80=9Cempty state=E2=80=9D appertains to the varia=
nt wrapper, not the wrapped
<br>>> object which is what goes into visitors. The term =E2=80=9Cemp=
ty state=E2=80=9D is
<br>>> confusingly ambiguous in this way. Treating the discriminator =
as a
<br>>> user-accessible scalar value adds to the confusion.
<br>>>
<br>> ... I agree that directly accessing the discriminator index value =
is not
<br>> good design, and attempts to use `which` should fail code review. =
However,
<br>> some people need it, and if it makes their lives slightly easier a=
t no cost
<br>> to me, let them have it.
<br>>
<br>> Allowing "disengagement" has a cost to me: the cost of v=
erifying such
<br>> objects. The cost of being `invalid` was one I was willing to pay,=
because
<br>> one could write variants where it was impossible to achieve such a=
state.
<br>> However, a general "disengagement" state, one which any =
variant can easily
<br>> enter simply by default construction?
<br>>
<br>> Absolutely not.
<br>>
<br>I don't understand why we can not have both. variant never empty an=
d=20
<br>discriminated_union/optionals possibly empty.
<br></blockquote><div><br>Because a never-empty variant can represent a pos=
sibly empty variant just fine; simply give it a state that means "empt=
y". We don't need a whole new class just for that. <br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_3055_2046639679.1443290814118--
------=_Part_3054_683995080.1443290814111--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 11:32:02 -0700 (PDT)
Raw View
------=_Part_2812_919334948.1443292322649
Content-Type: multipart/alternative;
boundary="----=_Part_2813_1763453766.1443292322649"
------=_Part_2813_1763453766.1443292322649
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 1:16:54 PM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9326, at 10:51 PM, Nicol Bolas <jmck...@gmail.co=
m <javascript:>>=20
> wrote:
>
> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:
>>
>>
>> 1. That=E2=80=99s like saying every nullable pointer parameter everywher=
e needs=20
>> to be validated against nullptr every time it enters a function.
>>
>
> Is this not the reason why the C++ Core Guidelines library includes=20
> `not_null`? Good programming practice these days is to make invariants=20
> *statically* visible and checked.
>
> You can freely disagree with these guidelines if you want, of course. But=
=20
> people do follow them.
>
>
> Some people. In any case, the one(s) who added it to that library.
>
> No such thing has been proposed for the standard =E2=80=94 as I mentioned=
just=20
> after that quote cuts off. That=E2=80=99s a far cry from a shoo-in requir=
ement on=20
> new standard types.
>
`not_null` is just an example. Sticking invariants in types has been a part=
=20
of C++ since RAII came along. `not_null` is just a non-behavioral example.
But if you want something being proposed, there's `observer_ptr`, which=20
represents the invariant of being unowned (and therefore you shouldn't=20
delete).
> The question is this: why do we *need* to allow variants to be=20
> "disengaged/empty/etc=E2=80=9D?
>
>
> Exceptions. Unless you want to bring Boost=E2=80=99s heap double-bufferin=
g back=20
> from the dead or to double sizeof(variant).
>
> If the implementations are getting cleverer, then I=E2=80=99ll happily re=
view the=20
> state of the art, after the next meeting. In the meantime, it seems safe =
to=20
> prioritize things that might make immediate progress.
>
"In the meantime"?=20
*Have you not been paying attention to this thread?*For the past few days,=
=20
we've been discussing an implementation strategy for a never-empty/invalid=
=20
variant=20
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jtQ_UVkG_Ko/Ixj=
22Vh2BgAJ>=20
that provides the strong exception guarantee, which:
1) Doesn't allocate heap memory. Ever
2) Only increases the size of `variant` when it *absolutely must* to meet=
=20
the strong exception guarantee. In this implementation, it does so only if=
=20
the type contains *two* throwing-move types. So if you stick to=20
non-throwing-move types, you lose nothing in terms of `variant` size.
3) The size of the `variant` is the larger of: a) the largest non-throwing=
=20
move type or b) twice the size of the largest throwing move type. And=20
again, this only happens if there are *two* throwing-move types.
--=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_2813_1763453766.1443292322649
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Saturday, September 26, 2015 at 1:16:54 PM UTC-4, David Krauss w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:b=
reak-word"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=
=9326, at 10:51 PM, Nicol Bolas <<a href=3D"javascript:" target=3D"_blan=
k" gdf-obfuscated-mailto=3D"jE9Z7HMbCQAJ" rel=3D"nofollow" onmousedown=3D"t=
his.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
javascript:';return true;">jmck...@gmail.com</a>> wrote:</div><br><d=
iv>On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-word"><=
br><div>1. That=E2=80=99s like saying every nullable pointer parameter ever=
ywhere needs to be validated against nullptr every time it enters a functio=
n.</div></div></blockquote><div><br>Is this not the reason why the C++ Core=
Guidelines library includes `not_null`? Good programming practice these da=
ys is to make invariants <i>statically</i> visible and checked.<br><br>You =
can freely disagree with these guidelines if you want, of course. But peopl=
e do follow them.<br></div></div></blockquote><div><br></div><div>Some peop=
le. In any case, the one(s) who added it to that library.</div><div><br></d=
iv><div>No such thing has been proposed for the standard =E2=80=94 as I men=
tioned just after that quote cuts off. That=E2=80=99s a far cry from a shoo=
-in requirement on new standard types.<br></div></div></div></blockquote><d=
iv><br>`not_null` is just an example. Sticking invariants in types has been=
a part of C++ since RAII came along. `not_null` is just a non-behavioral e=
xample.<br><br>But if you want something being proposed, there's `obser=
ver_ptr`, which represents the invariant of being unowned (and therefore yo=
u shouldn't delete).<br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div style=3D"word-wrap:break-word"><div><blockquote type=3D"cite"><d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-wo=
rd"><div></div></div></blockquote><div>The question is this: why do we <i>n=
eed</i> to allow variants to be "disengaged/empty/etc=E2=80=9D?<br></d=
iv></div></blockquote></div><br><div>Exceptions. Unless you want to bring B=
oost=E2=80=99s heap double-buffering back from the dead or to double <font =
face=3D"Courier">sizeof(variant)</font>.</div><div><br></div><div>If the im=
plementations are getting cleverer, then I=E2=80=99ll happily review the st=
ate of the art, after the next meeting. In the meantime, it seems safe to p=
rioritize things that might make immediate progress.</div></div></blockquot=
e><div><br>"In the meantime"? <i>Have you not been paying attenti=
on to this thread?<br><br></i>For the past few days, we've been <a href=
=3D"https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jtQ_UVkG_Ko/=
Ixj22Vh2BgAJ">discussing an implementation strategy for a never-empty/inval=
id variant</a> that provides the strong exception guarantee, which:<br><br>=
1) Doesn't allocate heap memory. Ever<br><br>2) Only increases the size=
of `variant` when it <i>absolutely must</i> to meet the strong exception g=
uarantee. In this implementation, it does so only if the type contains <i>t=
wo</i> throwing-move types. So if you stick to non-throwing-move types, you=
lose nothing in terms of `variant` size.<br><br>3) The size of the `varian=
t` is the larger of: a) the largest non-throwing move type or b) twice the =
size of the largest throwing move type. And again, this only happens if the=
re are <i>two</i> throwing-move types.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_2813_1763453766.1443292322649--
------=_Part_2812_919334948.1443292322649--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 11:33:24 -0700 (PDT)
Raw View
------=_Part_361_1945194023.1443292404432
Content-Type: multipart/alternative;
boundary="----=_Part_362_2033389678.1443292404432"
------=_Part_362_2033389678.1443292404432
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 1:21:34 PM UTC-4, Vicente J. Botet=20
Escriba wrote:
>
> Le 26/09/15 19:10, Vicente J. Botet Escriba a =C3=A9crit :=20
> > Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :=20
> >> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote:=
=20
> >=20
> >>=20
> >> This also means we don't have to give types default constructors just=
=20
> to=20
> >> satisfy C++ usage anymore. Just declare an `optional` of it,=20
> >> construct it=20
> >> empty, then initialize it later on when you're ready to properly do=20
> >> so. You=20
> >> can even copy/move out of it when you're ready to pass it to whomever=
=20
> >> needs=20
> >> it.=20
> >>=20
> >> Do you have any other reasons why we need `variant` to be able to=20
> become=20
> >> "disengaged/empty/etc"? Note that I said "need", not "prefer". What=20
> >> *actual=20
> >> problems* would such a concept solve for you?=20
> > optionals<Ts...> can be implemented more efficiently than=20
> > optional<variants<Ts...>>, but I want it to be a model of sum type=20
> > nullopt_t + Ts... and be able to visit it all at once. I don't want to=
=20
> > have to check if the optional is engaged and only then do visit the=20
> > stored value.=20
> I want to be able to visit nullable variants like=20
>
> optionals<T1, T2> o =3D ...;=20
> auto x=3D match(o,=20
> [](nullopt_t)->U {...},=20
> [](T1)->U {...},=20
> [](T2)->U {...}=20
> );=20
>
.... why would you not do:
variant<monostate, T1, T2> v =3D ...;
Why do you need a whole new type for something that a never-empty variant=
=20
gives you by design?
--=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_362_2033389678.1443292404432
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 1:21:34 PM UTC-4, Vicente J. Botet Escri=
ba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Le 26/09/15 19:10, Vi=
cente J. Botet Escriba a =C3=A9crit :
<br>> Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :
<br>>> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Kraus=
s wrote:
<br>>
<br>>>
<br>>> This also means we don't have to give types default constr=
uctors just to
<br>>> satisfy C++ usage anymore. Just declare an `optional` of it,=
=20
<br>>> construct it
<br>>> empty, then initialize it later on when you're ready to pr=
operly do=20
<br>>> so. You
<br>>> can even copy/move out of it when you're ready to pass it =
to whomever=20
<br>>> needs
<br>>> it.
<br>>>
<br>>> Do you have any other reasons why we need `variant` to be able=
to become
<br>>> "disengaged/empty/etc"? Note that I said "need&=
quot;, not "prefer". What=20
<br>>> *actual
<br>>> problems* would such a concept solve for you?
<br>> optionals<Ts...> can be implemented more efficiently than=20
<br>> optional<variants<Ts...>>, but I want it to be a model=
of sum type=20
<br>> nullopt_t + Ts... and be able to visit it all at once. I don't=
want to=20
<br>> have to check if the optional is engaged and only then do visit th=
e=20
<br>> stored value.
<br>I want to be able to visit nullable variants like
<br>
<br>optionals<T1, T2> o =3D ...;
<br>auto x=3D =C2=A0match(o,
<br>=C2=A0 =C2=A0 =C2=A0[](nullopt_t)->U {...},
<br>=C2=A0 =C2=A0 =C2=A0[](T1)->U {...},
<br>=C2=A0 =C2=A0 =C2=A0[](T2)->U {...}
<br>);
<br></blockquote><div><br>... why would you not do:<br><br><div class=3D"pr=
ettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb=
(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-w=
ord;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">variant</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">monostate</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> T1</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> T2</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
v </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</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></div></code>=
</div><br></div>Why do you need a whole new type for something that a never=
-empty variant gives you by design?<br>
<p></p>
-- <br />
<br />
--- <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 />
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_362_2033389678.1443292404432--
------=_Part_361_1945194023.1443292404432--
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 27 Sep 2015 03:17:47 +0800
Raw View
--Apple-Mail=_ECC63F6F-4BD9-4B40-B17E-2AE159288388
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9327, at 2:32 AM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> `not_null` is just an example. Sticking invariants in types has been a pa=
rt of C++ since RAII came along. `not_null` is just a non-behavioral exampl=
e.
>=20
> But if you want something being proposed, there's `observer_ptr`, which r=
epresents the invariant of being unowned (and therefore you shouldn't delet=
e).
observer_ptr is nullable and DefaultConstructible. You can=E2=80=99t pick a=
ny invariant and call that an argument.
> "In the meantime"? Have you not been paying attention to this thread?
>=20
> For the past few days, we've been discussing an implementation strategy f=
or a never-empty/invalid variant <https://groups.google.com/a/isocpp.org/d/=
msg/std-proposals/jtQ_UVkG_Ko/Ixj22Vh2BgAJ> that provides the strong except=
ion guarantee, which:
I think I=E2=80=99d be forgiven for a lapse, but=E2=80=A6
> 2) Only increases the size of `variant` when it absolutely must to meet t=
he strong exception guarantee. In this implementation, it does so only if t=
he type contains two throwing-move types. So if you stick to non-throwing-m=
ove types, you lose nothing in terms of `variant` size.
There you go.
--=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/.
--Apple-Mail=_ECC63F6F-4BD9-4B40-B17E-2AE159288388
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9327, at 2:32 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><div class=3D""><br=
class=3D""><div style=3D"font-family: Helvetica; font-size: 12px; font-sty=
le: normal; font-variant: normal; font-weight: normal; letter-spacing: norm=
al; line-height: normal; orphans: auto; text-align: start; text-indent: 0px=
; text-transform: none; white-space: normal; widows: auto; word-spacing: 0p=
x; -webkit-text-stroke-width: 0px;" class=3D"">`not_null` is just an exampl=
e. Sticking invariants in types has been a part of C++ since RAII came alon=
g. `not_null` is just a non-behavioral example.<br class=3D""><br class=3D"=
">But if you want something being proposed, there's `observer_ptr`, which r=
epresents the invariant of being unowned (and therefore you shouldn't delet=
e).<br class=3D""></div><blockquote class=3D"gmail_quote" style=3D"font-fam=
ily: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; =
font-weight: normal; letter-spacing: normal; line-height: normal; orphans: =
auto; text-align: start; text-indent: 0px; text-transform: none; white-spac=
e: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;=
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 style=3D=
"word-wrap: break-word;" class=3D""><div class=3D""><blockquote type=3D"cit=
e" class=3D""><div class=3D""><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204=
, 204, 204); border-left-style: solid; padding-left: 1ex;"><div style=3D"wo=
rd-wrap: break-word;" class=3D""><div class=3D""></div></div></blockquote><=
/div></blockquote></div></div></blockquote></div></blockquote><div><br clas=
s=3D""></div><div><font face=3D"Courier" class=3D"">observer_ptr</font> is =
nullable and DefaultConstructible. You can=E2=80=99t pick <i class=3D"">any=
</i> invariant and call that an argument.</div><br class=3D""><blockqu=
ote type=3D"cite" class=3D""><div class=3D""><div style=3D"font-family: Hel=
vetica; font-size: 12px; font-style: normal; font-variant: normal; font-wei=
ght: normal; letter-spacing: normal; line-height: normal; orphans: auto; te=
xt-align: start; text-indent: 0px; text-transform: none; white-space: norma=
l; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=
=3D"">"In the meantime"?<span class=3D"Apple-converted-space"> </span>=
<i class=3D"">Have you not been paying attention to this thread?<br class=
=3D""><br class=3D""></i>For the past few days, we've been<span class=3D"Ap=
ple-converted-space"> </span><a href=3D"https://groups.google.com/a/is=
ocpp.org/d/msg/std-proposals/jtQ_UVkG_Ko/Ixj22Vh2BgAJ" class=3D"">discussin=
g an implementation strategy for a never-empty/invalid variant</a><span cla=
ss=3D"Apple-converted-space"> </span>that provides the strong exceptio=
n guarantee, which:<br class=3D""></div></div></blockquote><div><br class=
=3D""></div><div>I think I=E2=80=99d be forgiven for a lapse, but=E2=80=A6<=
/div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><d=
iv style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; fo=
nt-variant: normal; font-weight: normal; letter-spacing: normal; line-heigh=
t: normal; orphans: auto; text-align: start; text-indent: 0px; text-transfo=
rm: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tex=
t-stroke-width: 0px;" class=3D"">2) Only increases the size of `variant` wh=
en it<span class=3D"Apple-converted-space"> </span><i class=3D"">absol=
utely must</i><span class=3D"Apple-converted-space"> </span>to meet th=
e strong exception guarantee. In this implementation, it does so only if th=
e type contains<span class=3D"Apple-converted-space"> </span><i class=
=3D"">two</i><span class=3D"Apple-converted-space"> </span>throwing-mo=
ve types. So if you stick to non-throwing-move types, you lose nothing in t=
erms of `variant` size.<br class=3D""></div></div></blockquote><div><br cla=
ss=3D""></div><div>There you go.</div></div><br class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_ECC63F6F-4BD9-4B40-B17E-2AE159288388--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 12:44:59 -0700 (PDT)
Raw View
------=_Part_3070_1005714099.1443296699186
Content-Type: multipart/alternative;
boundary="----=_Part_3071_64899747.1443296699186"
------=_Part_3071_64899747.1443296699186
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 3:17:54 PM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9327, at 2:32 AM, Nicol Bolas <jmck...@gmail.com=
<javascript:>>=20
> wrote:
>
> `not_null` is just an example. Sticking invariants in types has been a=20
> part of C++ since RAII came along. `not_null` is just a non-behavioral=20
> example.
>
> But if you want something being proposed, there's `observer_ptr`, which=
=20
> represents the invariant of being unowned (and therefore you shouldn't=20
> delete).
>
>>
> observer_ptr is nullable and DefaultConstructible. You can=E2=80=99t pick=
*any* invariant=20
> and call that an argument.
>
.... why not? I said that the guidelines say to ensure invariants via types=
=20
where possible. `not_null` is merely one of the ways to do that, for one=20
specific kind of invariant.
So the same guideline-based argument in favor of `not_null` works for any=
=20
invariant-handling type.
> "In the meantime"?=20
>
> *Have you not been paying attention to this thread?*For the past few=20
> days, we've been discussing an implementation strategy for a=20
> never-empty/invalid variant=20
> <https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jtQ_UVkG_Ko/I=
xj22Vh2BgAJ>
> that provides the strong exception guarantee, which:
>
>
> I think I=E2=80=99d be forgiven for a lapse, but=E2=80=A6
>
> 2) Only increases the size of `variant` when it *absolutely must* to meet=
=20
> the strong exception guarantee. In this implementation, it does so only i=
f=20
> the type contains *two* throwing-move types. So if you stick to=20
> non-throwing-move types, you lose nothing in terms of `variant` size.
>
>
> There you go.
>
"There you go" what? You said "Unless you want to bring Boost=E2=80=99s hea=
p=20
double-buffering back from the dead or to double sizeof(variant).". The=20
requirements he proposed don't do either of those.
You're not going to get something for nothing; everything with C++ variants=
=20
have a cost.
* Possibly-empty requires either uses always checking the empty state in=20
visitors or breaking static type-checking on visitation (by not having to=
=20
check empty states). It also loses you the strong exception guarantee.
* Never empty and the strong guarantee requires some sort of overhead to=20
deal with things. You either use dynamic allocation or carry additional=20
storage, in those specific cases where it is necessary.
* Never empty with invalidity doesn't give you the strong exception=20
guarantee, but some variants can never be invalid, and you never check=20
validity as part of visitation.
I prefer never empty with the strong guarantee. And since I also prefer not=
=20
to use dangerous throwing-move types, I also get this with *zero size=20
overhead*, under the proposed implementation.
That's as close to perfection as C++ can get...
--=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_3071_64899747.1443296699186
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Saturday, September 26, 2015 at 3:17:54 PM UTC-4, David Krauss w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:b=
reak-word"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=
=9327, at 2:32 AM, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank=
" gdf-obfuscated-mailto=3D"yqsSIw4iCQAJ" rel=3D"nofollow" onmousedown=3D"th=
is.href=3D'javascript:';return true;" onclick=3D"this.href=3D'j=
avascript:';return true;">jmck...@gmail.com</a>> wrote:</div><div><b=
r><div style=3D"font-family:Helvetica;font-size:12px;font-style:normal;font=
-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal=
;text-align:start;text-indent:0px;text-transform:none;white-space:normal;wo=
rd-spacing:0px">`not_null` is just an example. Sticking invariants in types=
has been a part of C++ since RAII came along. `not_null` is just a non-beh=
avioral example.<br><br>But if you want something being proposed, there'=
;s `observer_ptr`, which represents the invariant of being unowned (and the=
refore you shouldn't delete).<br></div><blockquote class=3D"gmail_quote=
" style=3D"font-family:Helvetica;font-size:12px;font-style:normal;font-vari=
ant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text=
-align:start;text-indent:0px;text-transform:none;white-space:normal;word-sp=
acing:0px;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 style=3D"wo=
rd-wrap:break-word"><div><blockquote type=3D"cite"><div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div style=3D"word-wrap:break-word"><div></div></div></blockquote></div></b=
lockquote></div></div></blockquote></div></blockquote><div><br></div><div><=
font face=3D"Courier">observer_ptr</font> is nullable and DefaultConstructi=
ble. You can=E2=80=99t pick <i>any</i>=C2=A0invariant and call that an argu=
ment.</div></div></div></blockquote><div><br>... why not? I said that the g=
uidelines say to ensure invariants via types where possible. `not_null` is =
merely one of the ways to do that, for one specific kind of invariant.<br><=
br>So the same guideline-based argument in favor of `not_null` works for an=
y invariant-handling type.<br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div style=3D"word-wrap:break-word"><div><blockquote type=3D"cite"><d=
iv><div style=3D"font-family:Helvetica;font-size:12px;font-style:normal;fon=
t-variant:normal;font-weight:normal;letter-spacing:normal;line-height:norma=
l;text-align:start;text-indent:0px;text-transform:none;white-space:normal;w=
ord-spacing:0px">"In the meantime"?<span>=C2=A0</span><i>Have you=
not been paying attention to this thread?<br><br></i>For the past few days=
, we've been<span>=C2=A0</span><a href=3D"https://groups.google.com/a/i=
socpp.org/d/msg/std-proposals/jtQ_UVkG_Ko/Ixj22Vh2BgAJ" target=3D"_blank" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'https://groups.google.com/a=
/isocpp.org/d/msg/std-proposals/jtQ_UVkG_Ko/Ixj22Vh2BgAJ';return true;"=
onclick=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msg/s=
td-proposals/jtQ_UVkG_Ko/Ixj22Vh2BgAJ';return true;">discussing an impl=
ementation strategy for a never-empty/invalid variant</a><span>=C2=A0</span=
>that provides the strong exception guarantee, which:<br></div></div></bloc=
kquote><div><br></div><div>I think I=E2=80=99d be forgiven for a lapse, but=
=E2=80=A6</div><br><blockquote type=3D"cite"><div><div style=3D"font-family=
:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight=
:normal;letter-spacing:normal;line-height:normal;text-align:start;text-inde=
nt:0px;text-transform:none;white-space:normal;word-spacing:0px">2) Only inc=
reases the size of `variant` when it<span>=C2=A0</span><i>absolutely must</=
i><span>=C2=A0</span>to meet the strong exception guarantee. In this implem=
entation, it does so only if the type contains<span>=C2=A0</span><i>two</i>=
<span>=C2=A0</span>throwing-move types. So if you stick to non-throwing-mov=
e types, you lose nothing in terms of `variant` size.<br></div></div></bloc=
kquote><div><br></div><div>There you go.<br></div></div></div></blockquote>=
<div><br>"There you go" what? You said "Unless you want to b=
ring Boost=E2=80=99s heap double-buffering back from the dead or to double =
<font face=3D"Courier">sizeof(variant)</font>.". The requirements he p=
roposed don't do either of those.<br><br>You're not going to get so=
mething for nothing; everything with C++ variants have a cost.<br><br>* Pos=
sibly-empty requires either uses always checking the empty state in visitor=
s or breaking static type-checking on visitation (by not having to check em=
pty states). It also loses you the strong exception guarantee.<br><br>* Nev=
er empty and the strong guarantee requires some sort of overhead to deal wi=
th things. You either use dynamic allocation or carry additional storage, i=
n those specific cases where it is necessary.<br><br>* Never empty with inv=
alidity doesn't give you the strong exception guarantee, but some varia=
nts can never be invalid, and you never check validity as part of visitatio=
n.<br><br>I prefer never empty with the strong guarantee. And since I also =
prefer not to use dangerous throwing-move types, I also get this with <i>ze=
ro size overhead</i>, under the proposed implementation.<br><br>That's =
as close to perfection as C++ can get...<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_3071_64899747.1443296699186--
------=_Part_3070_1005714099.1443296699186--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Sat, 26 Sep 2015 14:55:08 -0500
Raw View
--001a1143f1c0bbf07e0520abd952
Content-Type: text/plain; charset=UTF-8
On 26 September 2015 at 14:44, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> I prefer never empty with the strong guarantee.
>
None of the proposals give you that, as you'd have to pessimize assignment
to the already engaged type to achieve it. Of the proposals talked about
here, Williams.Variant comes closest to this.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143f1c0bbf07e0520abd952
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 26 September 2015 at 14:44, Nicol Bolas <span dir=3D"lt=
r"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@g=
mail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"=
gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><br></blockquote><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div>I prefer never empty with the strong guarantee. </div=
></blockquote><div><br></div><div>None of the proposals give you that, as y=
ou'd have to pessimize assignment to the already engaged type to achiev=
e it.=C2=A0 Of the proposals talked about here, Williams.Variant comes clos=
est to this.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin &=
quot;:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.=
com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404<=
/div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143f1c0bbf07e0520abd952--
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 27 Sep 2015 03:57:36 +0800
Raw View
--Apple-Mail=_76A1492F-1021-45BB-9CFA-C9DAD12BF3DB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9327, at 3:44 AM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> So the same guideline-based argument in favor of `not_null` works for any=
invariant-handling type.
There is such a thing as a guideline, and some guidelines are good, so your=
proposed guideline must be good?
> "There you go" what? You said "Unless you want to bring Boost=E2=80=99s h=
eap double-buffering back from the dead or to double sizeof(variant).". The=
requirements he proposed don't do either of those.
At a glance, the cost is up to double.
I was being too harsh there, though. I do hope the design space gets explor=
ed. However, =E2=80=9Cdiscussing an implementation strategy=E2=80=9D is som=
ething that comes before advancing =E2=80=9Cthe state of the art.=E2=80=9D
> You're not going to get something for nothing; everything with C++ varian=
ts have a cost.
I don=E2=80=99t want to pay the cost for the feature you=E2=80=99re demandi=
ng.
> I prefer never empty with the strong guarantee. And since I also prefer n=
ot to use dangerous throwing-move types, I also get this with zero size ove=
rhead, under the proposed implementation.
As little as zero.
I=E2=80=99m off to bed=E2=80=A6 too many holes and stale pieces in my big p=
roposal. This lifetime annotation stuff popularized by Rust, it changes eve=
rything. Exciting. About 30 hours left to understand it all, write 5-10 mor=
e pages, proofread and polish=E2=80=A6 yikes.
--=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/.
--Apple-Mail=_76A1492F-1021-45BB-9CFA-C9DAD12BF3DB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9327, at 3:44 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D"">So the same guideline-based argument i=
n favor of `not_null` works for any invariant-handling type.</div></blockqu=
ote><div><br class=3D""></div><div>There is such a thing as a guideline, an=
d some guidelines are good, so your proposed guideline must be good?</div><=
br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div cla=
ss=3D"">"There you go" what? You said "Unless you want to bring Boost=E2=80=
=99s heap double-buffering back from the dead or to double <font face=3D"Co=
urier" class=3D"">sizeof(variant)</font>.". The requirements he proposed do=
n't do either of those.<br class=3D""></div></div></blockquote><div><br cla=
ss=3D""></div><div>At a glance, the cost is up to double.</div><div><br cla=
ss=3D""></div><div>I was being too harsh there, though. I do hope the desig=
n space gets explored. However, =E2=80=9Cdiscussing an implementation strat=
egy=E2=80=9D is something that comes <i class=3D"">before</i> advancin=
g =E2=80=9Cthe state of the art.=E2=80=9D</div><br class=3D""><blockquote t=
ype=3D"cite" class=3D""><div class=3D""><div class=3D"">You're not going to=
get something for nothing; everything with C++ variants have a cost.<br cl=
ass=3D""></div></div></blockquote><div><br class=3D""></div><div>I don=E2=
=80=99t want to pay the cost for the feature you=E2=80=99re demanding.</div=
><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div c=
lass=3D"">I prefer never empty with the strong guarantee. And since I also =
prefer not to use dangerous throwing-move types, I also get this with <i cl=
ass=3D"">zero size overhead</i>, under the proposed implementation.<br clas=
s=3D""></div></div></blockquote></div><br class=3D""><div class=3D"">As lit=
tle as zero.</div><div class=3D""><br class=3D""></div><div class=3D"">I=E2=
=80=99m off to bed=E2=80=A6 too many holes and stale pieces in my big propo=
sal. This lifetime annotation stuff popularized by Rust, it changes everyth=
ing. Exciting. About 30 hours left to understand it all, write 5-10 more pa=
ges, proofread and polish=E2=80=A6 yikes.</div><div class=3D""><br class=3D=
""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_76A1492F-1021-45BB-9CFA-C9DAD12BF3DB--
.
Author: Magnus Fromreide <magfr@lysator.liu.se>
Date: Sat, 26 Sep 2015 23:02:45 +0200
Raw View
On Sat, Sep 26, 2015 at 06:37:27PM +0200, Vicente J. Botet Escriba wrote:
> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
> >On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
> >>Disengagement is different from merely representing a value which is em=
pty
> >>of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the vari=
ant wrapper, not the
> >>wrapped object which is what goes into visitors. The term =E2=80=9Cempt=
y state=E2=80=9D is
> >>confusingly ambiguous in this way. Treating the discriminator as a
> >>user-accessible scalar value adds to the confusion.
> >My concern is that I don't want the types variant<T> and optional<T> to =
be
> >functionally equivalent, regardless of how variant is implemented.
> You mean variant<nullopt_t,T> and optional<T> isn't it?
No, I mean variant<T> and optional<T>.
From my perspective an empty state in variant is similar enough to a nullop=
t
state in optional to make no difference.
> I like to see optional<T> as a specialization of variant<nullopt_t, T>
> providing an interface similar to a smart pointer to T.
That do look like one possible implementation but I am not sure if it is th=
e
best possible one - there are limitations on variant, as discussed at lengt=
h
here - that might not apply to optional.
/MF
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 00:02:13 +0200
Raw View
--047d7b624e9ae42c660520ad9d12
Content-Type: text/plain; charset=UTF-8
On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> `any` has the concept of being "empty", not to be orthogonal with
> `function` does. Both of these are allowed to be empty because C++ users
> need to be able to default-construct types. And since both of these are
> holders of more-or-less any type, they have no reasonable default state
> which could be *valid*. Therefore, the choices are to make them not
> default-constructable at all, or give them an empty state. The latter was
> considered better.
>
An exactly-one variant does not have any reasonable default value.
An exactly-one variant should not have a default constructor.
Default constructing the first type is an absurd idea:
struct L { ... };
struct R { ... };
using V = std::variant<L, R>;
V v1;
V v2(emplace<L>);
V v3(emplace<R>);
Now v1 == v2 but v1 != v3. That's ridiculous.
If you want a default-constructible variant, then you want an at-most-one
variant with an empty value.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b624e9ae42c660520ad9d12
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 S=
at, Sep 26, 2015 at 4:51 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div>`any` has the concept of=
being "empty", not to be orthogonal with `function` does. Both o=
f these are allowed to be empty because C++ users need to be able to defaul=
t-construct types. And since both of these are holders of more-or-less any =
type, they have no reasonable default state which could be <i>valid</i>. Th=
erefore, the choices are to make them not default-constructable at all, or =
give them an empty state. The latter was considered better.<br></div></bloc=
kquote><div>=C2=A0</div><div>An exactly-one variant does not have any reaso=
nable default value.</div><div><br></div><div>An exactly-one variant should=
not have a default constructor.</div><div><br></div><div>Default construct=
ing the first type is an absurd idea:</div><div><br></div><div>=C2=A0 =C2=
=A0struct L { ... };</div><div>=C2=A0 =C2=A0struct R { ... };</div><div><br=
></div><div>=C2=A0 =C2=A0using V =3D std::variant<L, R>;</div><div><b=
r></div><div>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V v2(emplace<L>=
;);</div><div>=C2=A0 =C2=A0V v3(emplace<R>);</div><div><br></div><div=
>Now v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 That's ridiculous.</div><div><b=
r></div><div>If you want a default-constructible variant, then you want an =
at-most-one variant with an empty value.</div><div><br></div></div></div></=
div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b624e9ae42c660520ad9d12--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 27 Sep 2015 00:29:39 +0200
Raw View
Le 26/09/15 20:33, Nicol Bolas a =C3=A9crit :
> On Saturday, September 26, 2015 at 1:21:34 PM UTC-4, Vicente J. Botet
> Escriba wrote:
>> Le 26/09/15 19:10, Vicente J. Botet Escriba a =C3=A9crit :
>>> Lbecome
>>>> "disengaged/empty/etc"? Note that I said "need", not "prefer". What
>>>> *actual
>>>> problems* would such a concept solve for you?
>>> optionals<Ts...> can be implemented more efficiently than
>>> optional<variants<Ts...>>, but I want it to be a model of sum type
>>> nullopt_t + Ts... and be able to visit it all at once. I don't want to
>>> have to check if the optional is engaged and only then do visit the
>>> stored value.
>> I want to be able to visit nullable variants like
>>
>> optionals<T1, T2> o =3D ...;
>> auto x=3D match(o,
>> [](nullopt_t)->U {...},
>> [](T1)->U {...},
>> [](T2)->U {...}
>> );
>>
> ... why would you not do:
>
> variant<monostate, T1, T2> v =3D ...;
>
> Why do you need a whole new type for something that a never-empty variant
> gives you by design?
>
Because variant<monostate, T1, T2> doesn't provides the specif interface=20
of a nullable/probably valued type.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 27 Sep 2015 00:37:21 +0200
Raw View
This is a multi-part message in MIME format.
--------------020501090202070703080103
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 26/09/15 23:02, Magnus Fromreide a =C3=A9crit :
> On Sat, Sep 26, 2015 at 06:37:27PM +0200, Vicente J. Botet Escriba wrote:
>> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
>>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>>> Disengagement is different from merely representing a value which is e=
mpty
>>>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the var=
iant wrapper, not the
>>>> wrapped object which is what goes into visitors. The term =E2=80=9Cemp=
ty state=E2=80=9D is
>>>> confusingly ambiguous in this way. Treating the discriminator as a
>>>> user-accessible scalar value adds to the confusion.
>>> My concern is that I don't want the types variant<T> and optional<T> to=
be
>>> functionally equivalent, regardless of how variant is implemented.
>> You mean variant<nullopt_t,T> and optional<T> isn't it?
> No, I mean variant<T> and optional<T>.
>
> >From my perspective an empty state in variant is similar enough to a nul=
lopt
> state in optional to make no difference.
>
>> I like to see optional<T> as a specialization of variant<nullopt_t, T>
>> providing an interface similar to a smart pointer to T.
> That do look like one possible implementation but I am not sure if it is =
the
> best possible one - there are limitations on variant, as discussed at len=
gth
> here - that might not apply to optional.
>
>
Sorry I should said, it looks like an specialization ...,
I don't see however how
template <class T>
class optional : public variant<nullopt_t, T>
{
};
could be a limitation with the optimizations that have been described in=20
this thread.
Really I would like to see optional to be a specialization of variant.
Vicente
--=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/.
--------------020501090202070703080103
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 26/09/15 23:02, Magnus Fromreide a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote cite=3D"mid:20150926210245.GA28931@noemi" type=3D"cite">
<pre wrap=3D"">On Sat, Sep 26, 2015 at 06:37:27PM +0200, Vicente J. B=
otet Escriba wrote:
</pre>
<blockquote type=3D"cite">
<pre wrap=3D"">Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
</pre>
<blockquote type=3D"cite">
<pre wrap=3D"">On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Kr=
auss wrote:
</pre>
<blockquote type=3D"cite">
<pre wrap=3D"">Disengagement is different from merely represent=
ing a value which is empty
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is
confusingly ambiguous in this way. Treating the discriminator as a
user-accessible scalar value adds to the confusion.
</pre>
</blockquote>
<pre wrap=3D"">My concern is that I don't want the types variant&=
lt;T> and optional<T> to be
functionally equivalent, regardless of how variant is implemented.
</pre>
</blockquote>
<pre wrap=3D"">You mean variant<nullopt_t,T> and optional<=
T> isn't it?
</pre>
</blockquote>
<pre wrap=3D"">
No, I mean variant<T> and optional<T>.
>From my perspective an empty state in variant is similar enough to a nu=
llopt
state in optional to make no difference.
</pre>
<blockquote type=3D"cite">
<pre wrap=3D"">I like to see optional<T> as a specialization =
of variant<nullopt_t, T>
providing an interface similar to a smart pointer to T.
</pre>
</blockquote>
<pre wrap=3D"">
That do look like one possible implementation but I am not sure if it is th=
e
best possible one - there are limitations on variant, as discussed at lengt=
h
here - that might not apply to optional.
</pre>
</blockquote>
Sorry I should said, it looks like an specialization ..., <br>
<br>
I don't see however how <br>
<br>
<font size=3D"+1">template <class T><br>
class optional : public variant<</font><font size=3D"+1">nullopt_t=
,
T> <br>
{<br>
<br>
};<br>
<br>
could be a limitation with the optimizations that have been
described in this thread. <br>
<br>
Really I would like to see optional to be a specialization of
variant.<br>
<br>
</font>Vicente<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--------------020501090202070703080103--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 15:39:16 -0700 (PDT)
Raw View
------=_Part_461_983593201.1443307156601
Content-Type: multipart/alternative;
boundary="----=_Part_462_858718489.1443307156601"
------=_Part_462_858718489.1443307156601
Content-Type: text/plain; charset=UTF-8
On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos wrote:
>
> On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> `any` has the concept of being "empty", not to be orthogonal with
>> `function` does. Both of these are allowed to be empty because C++ users
>> need to be able to default-construct types. And since both of these are
>> holders of more-or-less any type, they have no reasonable default state
>> which could be *valid*. Therefore, the choices are to make them not
>> default-constructable at all, or give them an empty state. The latter was
>> considered better.
>>
>
> An exactly-one variant does not have any reasonable default value.
>
> An exactly-one variant should not have a default constructor.
>
> Default constructing the first type is an absurd idea:
>
> struct L { ... };
> struct R { ... };
>
> using V = std::variant<L, R>;
>
> V v1;
> V v2(emplace<L>);
> V v3(emplace<R>);
>
> Now v1 == v2 but v1 != v3. That's ridiculous.
>
.... how is that ridiculous?
vector<int> t1;
vector<int> t2(0, 0);
vector<int> t3(1, 3);
t1 == t2, but t1 != t3.
Just because you call a construct does not, and has *never* meant that you
will get a different value than the default constructor. And if you've been
writing code under that assumption, then you've been doing it wrong.
> If you want a default-constructible variant, then you want an at-most-one
> variant with an empty value.
>
Just like unions default construct to an empty value. Oh wait, they don't;
they work exactly like N4542 variants.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_462_858718489.1443307156601
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote">On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <span dir=3D=
"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=
=3D"c6RdTQYrCQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascri=
pt:';return true;" onclick=3D"this.href=3D'javascript:';return =
true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div>`any` has the concept of being "empty", not to be orth=
ogonal with `function` does. Both of these are allowed to be empty because =
C++ users need to be able to default-construct types. And since both of the=
se are holders of more-or-less any type, they have no reasonable default st=
ate which could be <i>valid</i>. Therefore, the choices are to make them no=
t default-constructable at all, or give them an empty state. The latter was=
considered better.<br></div></blockquote><div>=C2=A0</div><div>An exactly-=
one variant does not have any reasonable default value.</div><div><br></div=
><div>An exactly-one variant should not have a default constructor.</div><d=
iv><br></div><div>Default constructing the first type is an absurd idea:</d=
iv><div><br></div><div>=C2=A0 =C2=A0struct L { ... };</div><div>=C2=A0 =C2=
=A0struct R { ... };</div><div><br></div><div>=C2=A0 =C2=A0using V =3D std:=
:variant<L, R>;</div><div><br></div><div>=C2=A0 =C2=A0V v1;</div><div=
>=C2=A0 =C2=A0V v2(emplace<L>);</div><div>=C2=A0 =C2=A0V v3(emplace&l=
t;R>);</div><div><br></div><div>Now v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 T=
hat's ridiculous.</div></div></div></div></blockquote><div><br>... how =
is that ridiculous?<br><br><div class=3D"prettyprint" style=3D"background-c=
olor: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: s=
olid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint=
"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"style=
d-by-prettify">vector</span><span style=3D"color: #080;" class=3D"styled-by=
-prettify"><int></span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> t1</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
vector</span><span style=3D"color: #080;" class=3D"styled-by-prettify"><=
int></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> t2=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" =
class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>vector</span><span style=3D"color: #080;" class=3D"styled-b=
y-prettify"><int></span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> t3</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #066;" class=3D"styled-by-prettify">1</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">3</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">);</span></div></code></div><br>t1 =
=3D=3D t2, but t1 !=3D t3.<br><br>Just because you call a construct does no=
t, and has <i>never</i> meant that you will get a different value than the =
default constructor. And if you've been writing code under that assumpt=
ion, then you've been doing it wrong.<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><div class=3D"gmail_quote=
"><div></div><div>If you want a default-constructible variant, then you wan=
t an at-most-one variant with an empty value.</div></div></div></div></bloc=
kquote><div><br>Just like unions default construct to an empty value. Oh wa=
it, they don't; they work exactly like N4542 variants.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_462_858718489.1443307156601--
------=_Part_461_983593201.1443307156601--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 15:43:38 -0700 (PDT)
Raw View
------=_Part_525_1541066404.1443307418831
Content-Type: multipart/alternative;
boundary="----=_Part_526_1816930957.1443307418831"
------=_Part_526_1816930957.1443307418831
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 6:37:23 PM UTC-4, Vicente J. Botet=20
Escriba wrote:
>
> Le 26/09/15 23:02, Magnus Fromreide a =C3=A9crit :
>
> On Sat, Sep 26, 2015 at 06:37:27PM +0200, Vicente J. Botet Escriba wrote:
>
> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
>
> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>
> Disengagement is different from merely representing a value which is empt=
y
> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the varian=
t wrapper, not the
> wrapped object which is what goes into visitors. The term =E2=80=9Cempty =
state=E2=80=9D is
> confusingly ambiguous in this way. Treating the discriminator as a
> user-accessible scalar value adds to the confusion.
>
> My concern is that I don't want the types variant<T> and optional<T> to b=
e
> functionally equivalent, regardless of how variant is implemented.
>
> You mean variant<nullopt_t,T> and optional<T> isn't it?
>
> No, I mean variant<T> and optional<T>.
>
> >From my perspective an empty state in variant is similar enough to a nul=
lopt
> state in optional to make no difference.
>
>
> I like to see optional<T> as a specialization of variant<nullopt_t, T>
> providing an interface similar to a smart pointer to T.
>
> That do look like one possible implementation but I am not sure if it is =
the
> best possible one - there are limitations on variant, as discussed at len=
gth
> here - that might not apply to optional.
>
>
>
> Sorry I should said, it looks like an specialization ...,=20
>
> I don't see however how=20
>
> template <class T>
> class optional : public variant<nullopt_t, T>=20
> {
>
> };
>
> could be a limitation with the optimizations that have been described in=
=20
> this thread.=20
>
> Really I would like to see optional to be a specialization of variant.
>
> Vicente
>
You've said this many times, but you've yet to explain why.
I have never been in a situation where I've modified code that was using an=
=20
`optional` to use a `variant`. Or vice-versa. Nor have I written template=
=20
code that would behave reasonably if it took both.
So besides the fact that it is theoretically possible, what do we have to=
=20
gain from such a specialization?
At best, it would be reasonable to allow a conversion operation which would=
=20
covert an `optional<T>` into any `variant<Ts...>`, so long as (at least)=20
one of those Ts is `monostate` and another (at least) one is `T`.
--=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_526_1816930957.1443307418831
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 6:37:23 PM UTC-4, Vicente J. Botet Escri=
ba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 26/09/15 23:02, Magnus Fromreide a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite">
<pre>On Sat, Sep 26, 2015 at 06:37:27PM +0200, Vicente J. Botet Escri=
ba wrote:
</pre>
<blockquote type=3D"cite">
<pre>Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
</pre>
<blockquote type=3D"cite">
<pre>On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote=
:
</pre>
<blockquote type=3D"cite">
<pre>Disengagement is different from merely representing a valu=
e which is empty
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is
confusingly ambiguous in this way. Treating the discriminator as a
user-accessible scalar value adds to the confusion.
</pre>
</blockquote>
<pre>My concern is that I don't want the types variant<T&g=
t; and optional<T> to be
functionally equivalent, regardless of how variant is implemented.
</pre>
</blockquote>
<pre>You mean variant<nullopt_t,T> and optional<T> isn&=
#39;t it?
</pre>
</blockquote>
<pre>No, I mean variant<T> and optional<T>.
>From my perspective an empty state in variant is similar enough to a nu=
llopt
state in optional to make no difference.
</pre>
<blockquote type=3D"cite">
<pre>I like to see optional<T> as a specialization of variant=
<nullopt_t, T>
providing an interface similar to a smart pointer to T.
</pre>
</blockquote>
<pre>That do look like one possible implementation but I am not sure =
if it is the
best possible one - there are limitations on variant, as discussed at lengt=
h
here - that might not apply to optional.
</pre>
</blockquote>
Sorry I should said, it looks like an specialization ..., <br>
<br>
I don't see however how <br>
<br>
<font size=3D"+1">template <class T><br>
class optional : public variant<</font><font size=3D"+1">nullopt_t=
,
T> <br>
{<br>
<br>
};<br>
<br>
could be a limitation with the optimizations that have been
described in this thread. <br>
<br>
Really I would like to see optional to be a specialization of
variant.<br>
<br>
</font>Vicente<br></div></blockquote><div><br>You've said this many=
times, but you've yet to explain why.<br><br>I have never been in a si=
tuation where I've modified code that was using an `optional` to use a =
`variant`. Or vice-versa. Nor have I written template code that would behav=
e reasonably if it took both.<br><br>So besides the fact that it is theoret=
ically possible, what do we have to gain from such a specialization?<br><br=
>At best, it would be reasonable to allow a conversion operation which woul=
d covert an `optional<T>` into any `variant<Ts...>`, so long as=
(at least) one of those Ts is `monostate` and another (at least) one is `T=
`.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_526_1816930957.1443307418831--
------=_Part_525_1541066404.1443307418831--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 15:45:55 -0700 (PDT)
Raw View
------=_Part_3106_1544618687.1443307555600
Content-Type: multipart/alternative;
boundary="----=_Part_3107_780085855.1443307555601"
------=_Part_3107_780085855.1443307555601
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 6:43:38 PM UTC-4, Nicol Bolas wrote:
>
> On Saturday, September 26, 2015 at 6:37:23 PM UTC-4, Vicente J. Botet=20
> Escriba wrote:
>>
>> Le 26/09/15 23:02, Magnus Fromreide a =C3=A9crit :
>>
>> On Sat, Sep 26, 2015 at 06:37:27PM +0200, Vicente J. Botet Escriba wrote=
:
>>
>> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
>>
>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>
>> Disengagement is different from merely representing a value which is emp=
ty
>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the varia=
nt wrapper, not the
>> wrapped object which is what goes into visitors. The term =E2=80=9Cempty=
state=E2=80=9D is
>> confusingly ambiguous in this way. Treating the discriminator as a
>> user-accessible scalar value adds to the confusion.
>>
>> My concern is that I don't want the types variant<T> and optional<T> to =
be
>> functionally equivalent, regardless of how variant is implemented.
>>
>> You mean variant<nullopt_t,T> and optional<T> isn't it?
>>
>> No, I mean variant<T> and optional<T>.
>>
>> >From my perspective an empty state in variant is similar enough to a nu=
llopt
>> state in optional to make no difference.
>>
>>
>> I like to see optional<T> as a specialization of variant<nullopt_t, T>
>> providing an interface similar to a smart pointer to T.
>>
>> That do look like one possible implementation but I am not sure if it is=
the
>> best possible one - there are limitations on variant, as discussed at le=
ngth
>> here - that might not apply to optional.
>>
>>
>>
>> Sorry I should said, it looks like an specialization ...,=20
>>
>> I don't see however how=20
>>
>> template <class T>
>> class optional : public variant<nullopt_t, T>=20
>> {
>>
>> };
>>
>> could be a limitation with the optimizations that have been described in=
=20
>> this thread.=20
>>
>> Really I would like to see optional to be a specialization of variant.
>>
>> Vicente
>>
>
> You've said this many times, but you've yet to explain why.
>
> I have never been in a situation where I've modified code that was using=
=20
> an `optional` to use a `variant`. Or vice-versa. Nor have I written=20
> template code that would behave reasonably if it took both.
>
> So besides the fact that it is theoretically possible, what do we have to=
=20
> gain from such a specialization?
>
> At best, it would be reasonable to allow a conversion operation which=20
> would covert an `optional<T>` into any `variant<Ts...>`, so long as (at=
=20
> least) one of those Ts is `monostate` and another (at least) one is `T`.
>
Oh, and it might also be reasonable to have a variant "get_opt", which will=
=20
copy the type/index into an `optional`, and if the variant doesn't have=20
that type/index, the `optional` is not engaged. Moving for this operation=
=20
is inappropriate, since you don't want to have the question of "has the=20
value in this variant been moved from" hanging around.
--=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_3107_780085855.1443307555601
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 6:43:38 PM UTC-4, Nicol Bolas wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">On Saturday, September 26, 2015 at=
6:37:23 PM UTC-4, Vicente J. Botet Escriba wrote:<blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 26/09/15 23:02, Magnus Fromreide a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite">
<pre>On Sat, Sep 26, 2015 at 06:37:27PM +0200, Vicente J. Botet Escri=
ba wrote:
</pre>
<blockquote type=3D"cite">
<pre>Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
</pre>
<blockquote type=3D"cite">
<pre>On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote=
:
</pre>
<blockquote type=3D"cite">
<pre>Disengagement is different from merely representing a valu=
e which is empty
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is
confusingly ambiguous in this way. Treating the discriminator as a
user-accessible scalar value adds to the confusion.
</pre>
</blockquote>
<pre>My concern is that I don't want the types variant<T&g=
t; and optional<T> to be
functionally equivalent, regardless of how variant is implemented.
</pre>
</blockquote>
<pre>You mean variant<nullopt_t,T> and optional<T> isn&=
#39;t it?
</pre>
</blockquote>
<pre>No, I mean variant<T> and optional<T>.
>From my perspective an empty state in variant is similar enough to a nu=
llopt
state in optional to make no difference.
</pre>
<blockquote type=3D"cite">
<pre>I like to see optional<T> as a specialization of variant=
<nullopt_t, T>
providing an interface similar to a smart pointer to T.
</pre>
</blockquote>
<pre>That do look like one possible implementation but I am not sure =
if it is the
best possible one - there are limitations on variant, as discussed at lengt=
h
here - that might not apply to optional.
</pre>
</blockquote>
Sorry I should said, it looks like an specialization ..., <br>
<br>
I don't see however how <br>
<br>
<font size=3D"+1">template <class T><br>
class optional : public variant<</font><font size=3D"+1">nullopt_t=
,
T> <br>
{<br>
<br>
};<br>
<br>
could be a limitation with the optimizations that have been
described in this thread. <br>
<br>
Really I would like to see optional to be a specialization of
variant.<br>
<br>
</font>Vicente<br></div></blockquote><div><br>You've said this many=
times, but you've yet to explain why.<br><br>I have never been in a si=
tuation where I've modified code that was using an `optional` to use a =
`variant`. Or vice-versa. Nor have I written template code that would behav=
e reasonably if it took both.<br><br>So besides the fact that it is theoret=
ically possible, what do we have to gain from such a specialization?<br><br=
>At best, it would be reasonable to allow a conversion operation which woul=
d covert an `optional<T>` into any `variant<Ts...>`, so long as=
(at least) one of those Ts is `monostate` and another (at least) one is `T=
`.<br></div></blockquote><div><br>Oh, and it might also be reasonable to ha=
ve a variant "get_opt", which will copy the type/index into an `o=
ptional`, and if the variant doesn't have that type/index, the `optiona=
l` is not engaged. Moving for this operation is inappropriate, since you do=
n't want to have the question of "has the value in this variant be=
en moved from" hanging around.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_3107_780085855.1443307555601--
------=_Part_3106_1544618687.1443307555600--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 01:14:45 +0200
Raw View
--047d7bae45324d479d0520aea1ea
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos wrote:
>>
>> On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> `any` has the concept of being "empty", not to be orthogonal with
>>> `function` does. Both of these are allowed to be empty because C++ users
>>> need to be able to default-construct types. And since both of these are
>>> holders of more-or-less any type, they have no reasonable default state
>>> which could be *valid*. Therefore, the choices are to make them not
>>> default-constructable at all, or give them an empty state. The latter was
>>> considered better.
>>>
>>
>> An exactly-one variant does not have any reasonable default value.
>>
>> An exactly-one variant should not have a default constructor.
>>
>> Default constructing the first type is an absurd idea:
>>
>> struct L { ... };
>> struct R { ... };
>>
>> using V = std::variant<L, R>;
>>
>> V v1;
>> V v2(emplace<L>);
>> V v3(emplace<R>);
>>
>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>
>
> ... how is that ridiculous?
>
> vector<int> t1;
> vector<int> t2(0, 0);
> vector<int> t3(1, 3);
>
> t1 == t2, but t1 != t3.
>
The default constructor of vector produces an empty vector, as you would
expect.
The correct analog would be if the default constructor of std::vector<T>
produced a vector containing one element with a default-constructed 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7bae45324d479d0520aea1ea
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <span dir=3D"ltr"><<a =
href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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">On Saturday, Septemb=
er 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos wrote:<span class=3D""><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote">On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <span dir=3D"ltr">&l=
t;<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<br><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div>`any` has the concept of being "empty",=
not to be orthogonal with `function` does. Both of these are allowed to be=
empty because C++ users need to be able to default-construct types. And si=
nce both of these are holders of more-or-less any type, they have no reason=
able default state which could be <i>valid</i>. Therefore, the choices are =
to make them not default-constructable at all, or give them an empty state.=
The latter was considered better.<br></div></blockquote><div>=C2=A0</div><=
div>An exactly-one variant does not have any reasonable default value.</div=
><div><br></div><div>An exactly-one variant should not have a default const=
ructor.</div><div><br></div><div>Default constructing the first type is an =
absurd idea:</div><div><br></div><div>=C2=A0 =C2=A0struct L { ... };</div><=
div>=C2=A0 =C2=A0struct R { ... };</div><div><br></div><div>=C2=A0 =C2=A0us=
ing V =3D std::variant<L, R>;</div><div><br></div><div>=C2=A0 =C2=A0V=
v1;</div><div>=C2=A0 =C2=A0V v2(emplace<L>);</div><div>=C2=A0 =C2=A0=
V v3(emplace<R>);</div><div><br></div><div>Now v1 =3D=3D v2 but v1 !=
=3D v3.=C2=A0 That's ridiculous.</div></div></div></div></blockquote></=
span><div><br>... how is that ridiculous?<br><br><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#000">ve=
ctor</span><span style=3D"color:#080"><int></span><span style=3D"colo=
r:#000"> t1</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>vector</span><span style=3D"color:#080"><int></span><span st=
yle=3D"color:#000"> t2</span><span style=3D"color:#660">(</span><span style=
=3D"color:#066">0</span><span style=3D"color:#660">,</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#066">0</span><span style=3D"color:=
#660">);</span><span style=3D"color:#000"><br>vector</span><span style=3D"c=
olor:#080"><int></span><span style=3D"color:#000"> t3</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#066">1</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#066">3</span><span style=3D"color:#660">);</span></div></code></div><br>=
t1 =3D=3D t2, but t1 !=3D t3.</div></blockquote><div>=C2=A0</div><div>The d=
efault constructor of vector produces an empty vector, as you would expect.=
</div><div><br></div><div>The correct analog would be if the default constr=
uctor of std::vector<T> produced a vector containing one element with=
a default-constructed T.</div><div><br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bae45324d479d0520aea1ea--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 17:09:20 -0700 (PDT)
Raw View
------=_Part_3093_223881292.1443312560793
Content-Type: multipart/alternative;
boundary="----=_Part_3094_776584757.1443312560794"
------=_Part_3094_776584757.1443312560794
Content-Type: text/plain; charset=UTF-8
On Saturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:
>
> On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos wrote:
>>>
>>> On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> `any` has the concept of being "empty", not to be orthogonal with
>>>> `function` does. Both of these are allowed to be empty because C++ users
>>>> need to be able to default-construct types. And since both of these are
>>>> holders of more-or-less any type, they have no reasonable default state
>>>> which could be *valid*. Therefore, the choices are to make them not
>>>> default-constructable at all, or give them an empty state. The latter was
>>>> considered better.
>>>>
>>>
>>> An exactly-one variant does not have any reasonable default value.
>>>
>>> An exactly-one variant should not have a default constructor.
>>>
>>> Default constructing the first type is an absurd idea:
>>>
>>> struct L { ... };
>>> struct R { ... };
>>>
>>> using V = std::variant<L, R>;
>>>
>>> V v1;
>>> V v2(emplace<L>);
>>> V v3(emplace<R>);
>>>
>>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>>
>>
>> ... how is that ridiculous?
>>
>> vector<int> t1;
>> vector<int> t2(0, 0);
>> vector<int> t3(1, 3);
>>
>> t1 == t2, but t1 != t3.
>>
>
> The default constructor of vector produces an empty vector, as you would
> expect.
>
OK, from my perspective, the point of your example was "calling a
non-default constructor with a certain parameter yielded equality with the
default constructor, but using a different value made a different object."
My example showed why that wasn't "ridiculous"; it is expected that you
might get the default case by using different constructors.
You seem to be arguing *conceptually*, not in terms of constructor calls
specifically. You seem to be saying that a "container" (for want of a
better term) is expected to default to being empty, and if it doesn't,
people will find that odd. A vector can be empty because it's a container.
So the question is this: is `variant` a container?
Like many things, it's all a matter of how you view the type. I don't think
of `variant` as a container; I think of it as a *value*, like an `int` or a
`float`. When I use a `variant`, it has a meaningful value. And it is
therefore meaningless to me to talk about `variant`s that don't have
meaningful values.
A variant which can have no value is like an `int` which can have no value.
That is, *nonsense*. Even the integer 0, while it may have special meaning
in conditional evaluation, is a *perfectly legitimate* integer value.
If you need an integer object that may not have a value, you use
`optional<int>`. Similarly, if you need a variant which may not have a
value, then you use `optional<variant>`. Of course, if you need a variant
which can have the *value* empty (similar to an `int` of 0), you use
`variant<monostate, Ts...>`.
What's wrong with this way of looking at `variant`?
The correct analog would be if the default constructor of std::vector<T>
> produced a vector containing one element with a default-constructed T.
>
That would not be an appropriate analogy, because you would still be able
to call `vector::clear()`. A `vector` represents an array of elements. By
its design, the length of said array can be zero even if the default
constructor makes it 1.
A never-empty variant cannot be empty. That's why we call it "never-empty"
;)
A better analogy would be with a hypothetical never-empty vector. Such a
class would not have `empty`, `clear`, and similar functions.
There would be advantages to such a design. It'd be safer, since its
interface would have none of the precondition restrictions that
std::vector's interface has on not being empty. `begin` would always return
an iterator to an actual item. `data()` would always return a valid
pointer. And so forth.
Now, I'm not saying that we *should* have designed vector to be
never-empty. What I'm saying is that, if we were designing such a type, it
would be *perfectly legitimate* if its default constructor created a
1-element vector of T, if T is default constructible.
Your criticism of a never-empty variant's default construction behavior is
that... it has the behavior that would be expected of a variant that can't
be empty. That seems like rather circular reasoning: you dislike the
never-empty variant because it does never-empty things.
Users are not stupid (all evidence to the contrary). If you tell them it's
a never-empty type, they'll understand that it can't be empty. It won't
take them long at all to understand what the default constructor does.
*Especially* given the fact that this is the the same behavior as unions.
As long as nobody's pretending that `variant` is an empty-able container,
we're fine.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3094_776584757.1443312560794
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote">On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <span dir=
=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailt=
o=3D"92-xnfsuCQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex">On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos =
wrote:<span><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><=
div class=3D"gmail_quote">On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <spa=
n dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div>`any` has the concept of being &q=
uot;empty", not to be orthogonal with `function` does. Both of these a=
re allowed to be empty because C++ users need to be able to default-constru=
ct types. And since both of these are holders of more-or-less any type, the=
y have no reasonable default state which could be <i>valid</i>. Therefore, =
the choices are to make them not default-constructable at all, or give them=
an empty state. The latter was considered better.<br></div></blockquote><d=
iv>=C2=A0</div><div>An exactly-one variant does not have any reasonable def=
ault value.</div><div><br></div><div>An exactly-one variant should not have=
a default constructor.</div><div><br></div><div>Default constructing the f=
irst type is an absurd idea:</div><div><br></div><div>=C2=A0 =C2=A0struct L=
{ ... };</div><div>=C2=A0 =C2=A0struct R { ... };</div><div><br></div><div=
>=C2=A0 =C2=A0using V =3D std::variant<L, R>;</div><div><br></div><di=
v>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V v2(emplace<L>);</div><d=
iv>=C2=A0 =C2=A0V v3(emplace<R>);</div><div><br></div><div>Now v1 =3D=
=3D v2 but v1 !=3D v3.=C2=A0 That's ridiculous.</div></div></div></div>=
</blockquote></span><div><br>... how is that ridiculous?<br><br><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px;word-wrap:break-word"><code><div><span style=
=3D"color:#000">vector</span><span style=3D"color:#080"><int></span><=
span style=3D"color:#000"> t1</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"><br>vector</span><span style=3D"color:#080"><int&=
gt;</span><span style=3D"color:#000"> t2</span><span style=3D"color:#660">(=
</span><span style=3D"color:#066">0</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#066">0</span><sp=
an style=3D"color:#660">);</span><span style=3D"color:#000"><br>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#000"> =
t3</span><span style=3D"color:#660">(</span><span style=3D"color:#066">1</s=
pan><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><=
span style=3D"color:#066">3</span><span style=3D"color:#660">);</span></div=
></code></div><br>t1 =3D=3D t2, but t1 !=3D t3.</div></blockquote><div>=C2=
=A0</div><div>The default constructor of vector produces an empty vector, a=
s you would expect.</div></div></div></div></blockquote><div><br>OK, from m=
y perspective, the point of your example was "calling a non-default co=
nstructor with a certain parameter yielded equality with the default constr=
uctor, but using a different value made a different object." My exampl=
e showed why that wasn't "ridiculous"; it is expected that yo=
u might get the default case by using different constructors.<br><br>You se=
em to be arguing <i>conceptually</i>, not in terms of constructor calls spe=
cifically. You seem to be saying that a "container" (for want of =
a better term) is expected to default to being empty, and if it doesn't=
, people will find that odd. A vector can be empty because it's a conta=
iner.<br><br>So the question is this: is `variant` a container?<br><br>Like=
many things, it's all a matter of how you view the type. I don't t=
hink of `variant` as a container; I think of it as a <i>value</i>, like an =
`int` or a `float`. When I use a `variant`, it has a meaningful value. And =
it is therefore meaningless to me to talk about `variant`s that don't h=
ave meaningful values.<br><br>A variant which can have no value is like an =
`int` which can have no value. That is, <i>nonsense</i>. Even the integer 0=
, while it may have special meaning in conditional evaluation, is a <i>perf=
ectly legitimate</i> integer value.<br><br>If you need an integer object th=
at may not have a value, you use `optional<int>`. Similarly, if you n=
eed a variant which may not have a value, then you use `optional<variant=
>`. Of course, if you need a variant which can have the <i>value</i> emp=
ty (similar to an `int` of 0), you use `variant<monostate, Ts...>`.<b=
r><br>What's wrong with this way of looking at `variant`?<br><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div cla=
ss=3D"gmail_quote"><div>The correct analog would be if the default construc=
tor of std::vector<T> produced a vector containing one element with a=
default-constructed T.</div></div></div></div></blockquote><div><br>That w=
ould not be an appropriate analogy, because you would still be able to call=
`vector::clear()`. A `vector` represents an array of elements. By its desi=
gn, the length of said array can be zero even if the default constructor ma=
kes it 1.<br><br>A never-empty variant cannot be empty. That's why we c=
all it "never-empty" ;)<br><br>A better analogy would be with a h=
ypothetical never-empty vector. Such a class would not have `empty`, `clear=
`, and similar functions.<br><br>There would be advantages to such a design=
.. It'd be safer, since its interface would have none of the preconditio=
n restrictions that std::vector's interface has on not being empty. `be=
gin` would always return an iterator to an actual item. `data()` would alwa=
ys return a valid pointer. And so forth.<br><br>Now, I'm not saying tha=
t we <i>should</i> have designed vector to be never-empty. What I'm say=
ing is that, if we were designing such a type, it would be <i>perfectly leg=
itimate</i> if its default constructor created a 1-element vector of T, if =
T is default constructible.<br><br>Your criticism of a never-empty variant&=
#39;s default construction behavior is that... it has the behavior that wou=
ld be expected of a variant that can't be empty. That seems like rather=
circular reasoning: you dislike the never-empty variant because it does ne=
ver-empty things.<br><br>Users are not stupid (all evidence to the contrary=
). If you tell them it's a never-empty type, they'll understand tha=
t it can't be empty. It won't take them long at all to understand w=
hat the default constructor does. <i>Especially</i> given the fact that thi=
s is the the same behavior as unions.<br><br>As long as nobody's preten=
ding that `variant` is an empty-able container, we're fine.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_3094_776584757.1443312560794--
------=_Part_3093_223881292.1443312560793--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 17:12:54 -0700 (PDT)
Raw View
------=_Part_552_1702247537.1443312774130
Content-Type: multipart/alternative;
boundary="----=_Part_553_278037645.1443312774131"
------=_Part_553_278037645.1443312774131
Content-Type: text/plain; charset=UTF-8
On Saturday, September 26, 2015 at 8:09:21 PM UTC-4, Nicol Bolas wrote:
>
> On Saturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:
>>
>> On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos
>>> wrote:
>>>>
>>>> On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>>
>>>>> `any` has the concept of being "empty", not to be orthogonal with
>>>>> `function` does. Both of these are allowed to be empty because C++ users
>>>>> need to be able to default-construct types. And since both of these are
>>>>> holders of more-or-less any type, they have no reasonable default state
>>>>> which could be *valid*. Therefore, the choices are to make them not
>>>>> default-constructable at all, or give them an empty state. The latter was
>>>>> considered better.
>>>>>
>>>>
>>>> An exactly-one variant does not have any reasonable default value.
>>>>
>>>> An exactly-one variant should not have a default constructor.
>>>>
>>>> Default constructing the first type is an absurd idea:
>>>>
>>>> struct L { ... };
>>>> struct R { ... };
>>>>
>>>> using V = std::variant<L, R>;
>>>>
>>>> V v1;
>>>> V v2(emplace<L>);
>>>> V v3(emplace<R>);
>>>>
>>>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>>>
>>>
>>> ... how is that ridiculous?
>>>
>>> vector<int> t1;
>>> vector<int> t2(0, 0);
>>> vector<int> t3(1, 3);
>>>
>>> t1 == t2, but t1 != t3.
>>>
>>
>> The default constructor of vector produces an empty vector, as you would
>> expect.
>>
>
> OK, from my perspective, the point of your example was "calling a
> non-default constructor with a certain parameter yielded equality with the
> default constructor, but using a different value made a different object."
> My example showed why that wasn't "ridiculous"; it is expected that you
> might get the default case by using different constructors.
>
> You seem to be arguing *conceptually*, not in terms of constructor calls
> specifically. You seem to be saying that a "container" (for want of a
> better term) is expected to default to being empty, and if it doesn't,
> people will find that odd. A vector can be empty because it's a container.
>
> So the question is this: is `variant` a container?
>
> Like many things, it's all a matter of how you view the type. I don't
> think of `variant` as a container; I think of it as a *value*, like an
> `int` or a `float`. When I use a `variant`, it has a meaningful value. And
> it is therefore meaningless to me to talk about `variant`s that don't have
> meaningful values.
>
> A variant which can have no value is like an `int` which can have no
> value. That is, *nonsense*. Even the integer 0, while it may have special
> meaning in conditional evaluation, is a *perfectly legitimate* integer
> value.
>
> If you need an integer object that may not have a value, you use
> `optional<int>`. Similarly, if you need a variant which may not have a
> value, then you use `optional<variant>`. Of course, if you need a variant
> which can have the *value* empty (similar to an `int` of 0), you use
> `variant<monostate, Ts...>`.
>
> What's wrong with this way of looking at `variant`?
>
> The correct analog would be if the default constructor of std::vector<T>
>> produced a vector containing one element with a default-constructed T.
>>
>
> That would not be an appropriate analogy, because you would still be able
> to call `vector::clear()`. A `vector` represents an array of elements. By
> its design, the length of said array can be zero even if the default
> constructor makes it 1.
>
> A never-empty variant cannot be empty. That's why we call it "never-empty"
> ;)
>
> A better analogy would be with a hypothetical never-empty vector. Such a
> class would not have `empty`, `clear`, and similar functions.
>
> There would be advantages to such a design. It'd be safer, since its
> interface would have none of the precondition restrictions that
> std::vector's interface has on not being empty. `begin` would always return
> an iterator to an actual item. `data()` would always return a valid
> pointer. And so forth.
>
> Now, I'm not saying that we *should* have designed vector to be
> never-empty. What I'm saying is that, if we were designing such a type, it
> would be *perfectly legitimate* if its default constructor created a
> 1-element vector of T, if T is default constructible.
>
> Your criticism of a never-empty variant's default construction behavior is
> that... it has the behavior that would be expected of a variant that can't
> be empty. That seems like rather circular reasoning: you dislike the
> never-empty variant because it does never-empty things.
>
> Users are not stupid (all evidence to the contrary). If you tell them it's
> a never-empty type, they'll understand that it can't be empty. It won't
> take them long at all to understand what the default constructor does.
> *Especially* given the fact that this is the the same behavior as unions.
>
> As long as nobody's pretending that `variant` is an empty-able container,
> we're fine.
>
Allow me to put this another way: default construction does not, *and never
has*, meant "create an empty object". It only means create a *default*
object. For types which can be empty, this will probably be an empty object.
For types which cannot, it will be some functional object in a "default"
state by some definition.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_553_278037645.1443312774131
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 8:09:21 PM UTC-4, Nicol Bolas wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">On Saturday, September 26, 2015 at=
7:14:47 PM UTC-4, Andrew Tomazos wrote:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Sun, Sep 27, 2015 =
at 12:39 AM, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@=
gmail.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">On Satur=
day, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos wrote:<span><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gm=
ail_quote">On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <span dir=3D"ltr">&=
lt;<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<br><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><div>`any` has the concept of being "empty"=
, not to be orthogonal with `function` does. Both of these are allowed to b=
e empty because C++ users need to be able to default-construct types. And s=
ince both of these are holders of more-or-less any type, they have no reaso=
nable default state which could be <i>valid</i>. Therefore, the choices are=
to make them not default-constructable at all, or give them an empty state=
.. The latter was considered better.<br></div></blockquote><div>=C2=A0</div>=
<div>An exactly-one variant does not have any reasonable default value.</di=
v><div><br></div><div>An exactly-one variant should not have a default cons=
tructor.</div><div><br></div><div>Default constructing the first type is an=
absurd idea:</div><div><br></div><div>=C2=A0 =C2=A0struct L { ... };</div>=
<div>=C2=A0 =C2=A0struct R { ... };</div><div><br></div><div>=C2=A0 =C2=A0u=
sing V =3D std::variant<L, R>;</div><div><br></div><div>=C2=A0 =C2=A0=
V v1;</div><div>=C2=A0 =C2=A0V v2(emplace<L>);</div><div>=C2=A0 =C2=
=A0V v3(emplace<R>);</div><div><br></div><div>Now v1 =3D=3D v2 but v1=
!=3D v3.=C2=A0 That's ridiculous.</div></div></div></div></blockquote>=
</span><div><br>... how is that ridiculous?<br><br><div style=3D"background=
-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bo=
rder-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#000">=
vector</span><span style=3D"color:#080"><int></span><span style=3D"co=
lor:#000"> t1</span><span style=3D"color:#660">;</span><span style=3D"color=
:#000"><br>vector</span><span style=3D"color:#080"><int></span><span =
style=3D"color:#000"> t2</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#066">0</span><span style=3D"color:#660">,</span><span style=3D=
"color:#000"> </span><span style=3D"color:#066">0</span><span style=3D"colo=
r:#660">);</span><span style=3D"color:#000"><br>vector</span><span style=3D=
"color:#080"><int></span><span style=3D"color:#000"> t3</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#066">1</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#066">3</span><span style=3D"color:#660">);</span></div></code></div><=
br>t1 =3D=3D t2, but t1 !=3D t3.</div></blockquote><div>=C2=A0</div><div>Th=
e default constructor of vector produces an empty vector, as you would expe=
ct.</div></div></div></div></blockquote><div><br>OK, from my perspective, t=
he point of your example was "calling a non-default constructor with a=
certain parameter yielded equality with the default constructor, but using=
a different value made a different object." My example showed why tha=
t wasn't "ridiculous"; it is expected that you might get the =
default case by using different constructors.<br><br>You seem to be arguing=
<i>conceptually</i>, not in terms of constructor calls specifically. You s=
eem to be saying that a "container" (for want of a better term) i=
s expected to default to being empty, and if it doesn't, people will fi=
nd that odd. A vector can be empty because it's a container.<br><br>So =
the question is this: is `variant` a container?<br><br>Like many things, it=
's all a matter of how you view the type. I don't think of `variant=
` as a container; I think of it as a <i>value</i>, like an `int` or a `floa=
t`. When I use a `variant`, it has a meaningful value. And it is therefore =
meaningless to me to talk about `variant`s that don't have meaningful v=
alues.<br><br>A variant which can have no value is like an `int` which can =
have no value. That is, <i>nonsense</i>. Even the integer 0, while it may h=
ave special meaning in conditional evaluation, is a <i>perfectly legitimate=
</i> integer value.<br><br>If you need an integer object that may not have =
a value, you use `optional<int>`. Similarly, if you need a variant wh=
ich may not have a value, then you use `optional<variant>`. Of course=
, if you need a variant which can have the <i>value</i> empty (similar to a=
n `int` of 0), you use `variant<monostate, Ts...>`.<br><br>What's=
wrong with this way of looking at `variant`?<br><br></div><blockquote clas=
s=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 class=3D"gmail_quote"><d=
iv>The correct analog would be if the default constructor of std::vector<=
;T> produced a vector containing one element with a default-constructed =
T.</div></div></div></div></blockquote><div><br>That would not be an approp=
riate analogy, because you would still be able to call `vector::clear()`. A=
`vector` represents an array of elements. By its design, the length of sai=
d array can be zero even if the default constructor makes it 1.<br><br>A ne=
ver-empty variant cannot be empty. That's why we call it "never-em=
pty" ;)<br><br>A better analogy would be with a hypothetical never-emp=
ty vector. Such a class would not have `empty`, `clear`, and similar functi=
ons.<br><br>There would be advantages to such a design. It'd be safer, =
since its interface would have none of the precondition restrictions that s=
td::vector's interface has on not being empty. `begin` would always ret=
urn an iterator to an actual item. `data()` would always return a valid poi=
nter. And so forth.<br><br>Now, I'm not saying that we <i>should</i> ha=
ve designed vector to be never-empty. What I'm saying is that, if we we=
re designing such a type, it would be <i>perfectly legitimate</i> if its de=
fault constructor created a 1-element vector of T, if T is default construc=
tible.<br><br>Your criticism of a never-empty variant's default constru=
ction behavior is that... it has the behavior that would be expected of a v=
ariant that can't be empty. That seems like rather circular reasoning: =
you dislike the never-empty variant because it does never-empty things.<br>=
<br>Users are not stupid (all evidence to the contrary). If you tell them i=
t's a never-empty type, they'll understand that it can't be emp=
ty. It won't take them long at all to understand what the default const=
ructor does. <i>Especially</i> given the fact that this is the the same beh=
avior as unions.<br><br>As long as nobody's pretending that `variant` i=
s an empty-able container, we're fine.<br></div></blockquote><div><br>A=
llow me to put this another way: default construction does not, <i>and neve=
r has</i>, meant "create an empty object". It only means create a=
<i>default</i> object. For types which can be empty, this will probably be=
an empty object.<br><br>For types which cannot, it will be some functional=
object in a "default" state by some definition. <br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_553_278037645.1443312774131--
------=_Part_552_1702247537.1443312774130--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 02:58:42 +0200
Raw View
--047d7bae4532063eeb0520b01513
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 2:09 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Saturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:
>>
>> On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos
>>> wrote:
>>>>
>>>> On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>>
>>>>> `any` has the concept of being "empty", not to be orthogonal with
>>>>> `function` does. Both of these are allowed to be empty because C++ users
>>>>> need to be able to default-construct types. And since both of these are
>>>>> holders of more-or-less any type, they have no reasonable default state
>>>>> which could be *valid*. Therefore, the choices are to make them not
>>>>> default-constructable at all, or give them an empty state. The latter was
>>>>> considered better.
>>>>>
>>>>
>>>> An exactly-one variant does not have any reasonable default value.
>>>>
>>>> An exactly-one variant should not have a default constructor.
>>>>
>>>> Default constructing the first type is an absurd idea:
>>>>
>>>> struct L { ... };
>>>> struct R { ... };
>>>>
>>>> using V = std::variant<L, R>;
>>>>
>>>> V v1;
>>>> V v2(emplace<L>);
>>>> V v3(emplace<R>);
>>>>
>>>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>>>
>>>
>>> ... how is that ridiculous?
>>>
>>> vector<int> t1;
>>> vector<int> t2(0, 0);
>>> vector<int> t3(1, 3);
>>>
>>> t1 == t2, but t1 != t3.
>>>
>>
>> The default constructor of vector produces an empty vector, as you would
>> expect.
>>
>
> OK, from my perspective, the point of your example was "calling a
> non-default constructor with a certain parameter yielded equality with the
> default constructor, but using a different value made a different object."
> My example showed why that wasn't "ridiculous"; it is expected that you
> might get the default case by using different constructors.
>
> You seem to be arguing *conceptually*, not in terms of constructor calls
> specifically. You seem to be saying that a "container" (for want of a
> better term) is expected to default to being empty, and if it doesn't,
> people will find that odd. A vector can be empty because it's a container.
>
> So the question is this: is `variant` a container?
>
Another strawman. A type should be default constructible if and only if it
has an unsurprising default value:
std::any a;
std::function<int(int)> f;
std::thread t;
std::optional<float> i;
std::unique_ptr<Matrix> p;
std::vector<Widget> v;
All of the above variables are empty. If the above code compiles, then
people would expect these variables to be empty or null or void or invalid
or devoid of value, or whatever you want to call it. And they are.
For std::variant<Left,Right>, default constructing to hold a value of type
Left is absurd. Most would consider it extremely surprising. Most would
(rightfully) not expect the first listed type to have any special meaning
or behavior. That is so, irrespective of whether std::variant<Right,Left>
is the same type. (Most understand there is implementation-difficultly in
making std::variant<Left,Right> formally the same type as
std::variant<Right,Left>, but we shouldn't exacerbate that by giving the
first type in the list special-meaning.)
An exactly-one variant should not be default constructible. It has no
sensible default value.
An at-most-one variant should default construct to the empty value.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7bae4532063eeb0520b01513
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sun, Sep 27, 2015 at 2:09 AM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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">On Saturday, Septembe=
r 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:<span class=3D""><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmai=
l_quote">On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <span dir=3D"ltr">&l=
t;<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<br><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex">On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, A=
ndrew Tomazos wrote:<span><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><div class=3D"gmail_quote">On Sat, Sep 26, 2015 at 4:51 PM, N=
icol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>`any` has the conc=
ept of being "empty", not to be orthogonal with `function` does. =
Both of these are allowed to be empty because C++ users need to be able to =
default-construct types. And since both of these are holders of more-or-les=
s any type, they have no reasonable default state which could be <i>valid</=
i>. Therefore, the choices are to make them not default-constructable at al=
l, or give them an empty state. The latter was considered better.<br></div>=
</blockquote><div>=C2=A0</div><div>An exactly-one variant does not have any=
reasonable default value.</div><div><br></div><div>An exactly-one variant =
should not have a default constructor.</div><div><br></div><div>Default con=
structing the first type is an absurd idea:</div><div><br></div><div>=C2=A0=
=C2=A0struct L { ... };</div><div>=C2=A0 =C2=A0struct R { ... };</div><div=
><br></div><div>=C2=A0 =C2=A0using V =3D std::variant<L, R>;</div><di=
v><br></div><div>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V v2(emplace<=
L>);</div><div>=C2=A0 =C2=A0V v3(emplace<R>);</div><div><br></div>=
<div>Now v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 That's ridiculous.</div></d=
iv></div></div></blockquote></span><div><br>... how is that ridiculous?<br>=
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#000">vector</span><span style=3D"color:#080"><int=
></span><span style=3D"color:#000"> t1</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"><br>vector</span><span style=3D"color:#0=
80"><int></span><span style=3D"color:#000"> t2</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#066">0</span><span style=3D"color:=
#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>0</span><span style=3D"color:#660">);</span><span style=3D"color:#000"><br=
>vector</span><span style=3D"color:#080"><int></span><span style=3D"c=
olor:#000"> t3</span><span style=3D"color:#660">(</span><span style=3D"colo=
r:#066">1</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#066">3</span><span style=3D"color:#660">);=
</span></div></code></div><br>t1 =3D=3D t2, but t1 !=3D t3.</div></blockquo=
te><div>=C2=A0</div><div>The default constructor of vector produces an empt=
y vector, as you would expect.</div></div></div></div></blockquote></span><=
div><br>OK, from my perspective, the point of your example was "callin=
g a non-default constructor with a certain parameter yielded equality with =
the default constructor, but using a different value made a different objec=
t." My example showed why that wasn't "ridiculous"; it i=
s expected that you might get the default case by using different construct=
ors.<br><br>You seem to be arguing <i>conceptually</i>, not in terms of con=
structor calls specifically. You seem to be saying that a "container&q=
uot; (for want of a better term) is expected to default to being empty, and=
if it doesn't, people will find that odd. A vector can be empty becaus=
e it's a container.<br><br>So the question is this: is `variant` a cont=
ainer?<br></div></blockquote><div><br></div><div>Another strawman.=C2=A0 A =
type should be default constructible if and only if it has an unsurprising =
default value:</div><div><br></div><div>=C2=A0 =C2=A0std::any a;=C2=A0</div=
><div>=C2=A0 =C2=A0std::function<int(int)> f;</div><div>=C2=A0 =C2=A0=
std::thread t;</div><div>=C2=A0 =C2=A0std::optional<float> i;</div><d=
iv>=C2=A0 =C2=A0std::unique_ptr<Matrix> p;</div><div>=C2=A0 =C2=A0std=
::vector<Widget> v;</div><div><br></div><div>All of the above variabl=
es are empty.=C2=A0 If the above code compiles, then people would expect th=
ese variables to be empty or null or void or invalid or devoid of value, or=
whatever you want to call it.=C2=A0 And they are.</div><div><br></div><div=
>For std::variant<Left,Right>, default constructing to hold a value o=
f type Left is absurd.=C2=A0 Most would consider it extremely surprising.=
=C2=A0 Most would (rightfully) not expect the first listed type to have any=
special meaning or behavior.=C2=A0 That is so, irrespective of whether std=
::variant<Right,Left> is the same type. =C2=A0 (Most understand there=
is implementation-difficultly in making std::variant<Left,Right> for=
mally the same type as std::variant<Right,Left>, but we shouldn't=
exacerbate that by giving the first type in the list special-meaning.)</di=
v><div><br></div><div>An exactly-one variant should not be default construc=
tible.=C2=A0 It has no sensible default value.</div><div><br></div><div>An =
at-most-one variant should default construct to the empty value.</div><div>=
<br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bae4532063eeb0520b01513--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sat, 26 Sep 2015 22:18:15 -0300
Raw View
On 9/26/2015 7:39 PM, Nicol Bolas wrote:
> Just like unions default construct to an empty value. Oh wait, they
> don't; they work exactly like N4542 variants.
I believe you are talking value-initialization, not=20
default-initialization. A default-initialized union with an=20
implicitly-defined default constructor has no active members, it's not=20
even fully-initialized. Actually it's a bit more complex than that, as=20
that requires all members of the union to be trivially-constructible,=20
and according to the standard then the lifetime of *all* members has=20
began. To keep things simple consider `union U {};`, it cannot be non-empty=
..
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 03:20:02 +0200
Raw View
--f46d0418270c55a8150520b06154
Content-Type: text/plain; charset=UTF-8
Furthermore...
While it is fine if std::variant<Left, Right> and std::variant<Right,Left>
are not the same type (as comparing type lists as unordered sets is
prohibitively expensive, and we lose the ability to index the type list,
etc) I could easily imagine equality (but not comparison) being defined
across variants as follows:
bool operator==(const std::variant<T...>& a, const std::variant<U...>&
b) {
if (variants can be empty, and both a and b are empty)
return true;
else if (a and b hold a value of the same type X)
return X(a) == X(b);
else
return false;
}
In this case:
std::variant<Left, Right> v1;
std::variant<Right, Left> v2;
Is v1 == v2 ?
It would be expected that they are equal.
In the case of an exactly-one variant that surprisingly constructed a value
of the first type, they would not be.
In the case of an at-most-one variant that default constructed to empty,
they would be, as expected.
On Sun, Sep 27, 2015 at 2:58 AM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
>
>
> On Sun, Sep 27, 2015 at 2:09 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> On Saturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:
>>>
>>> On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos
>>>> wrote:
>>>>>
>>>>> On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmck...@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> `any` has the concept of being "empty", not to be orthogonal with
>>>>>> `function` does. Both of these are allowed to be empty because C++ users
>>>>>> need to be able to default-construct types. And since both of these are
>>>>>> holders of more-or-less any type, they have no reasonable default state
>>>>>> which could be *valid*. Therefore, the choices are to make them not
>>>>>> default-constructable at all, or give them an empty state. The latter was
>>>>>> considered better.
>>>>>>
>>>>>
>>>>> An exactly-one variant does not have any reasonable default value.
>>>>>
>>>>> An exactly-one variant should not have a default constructor.
>>>>>
>>>>> Default constructing the first type is an absurd idea:
>>>>>
>>>>> struct L { ... };
>>>>> struct R { ... };
>>>>>
>>>>> using V = std::variant<L, R>;
>>>>>
>>>>> V v1;
>>>>> V v2(emplace<L>);
>>>>> V v3(emplace<R>);
>>>>>
>>>>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>>>>
>>>>
>>>> ... how is that ridiculous?
>>>>
>>>> vector<int> t1;
>>>> vector<int> t2(0, 0);
>>>> vector<int> t3(1, 3);
>>>>
>>>> t1 == t2, but t1 != t3.
>>>>
>>>
>>> The default constructor of vector produces an empty vector, as you would
>>> expect.
>>>
>>
>> OK, from my perspective, the point of your example was "calling a
>> non-default constructor with a certain parameter yielded equality with the
>> default constructor, but using a different value made a different object."
>> My example showed why that wasn't "ridiculous"; it is expected that you
>> might get the default case by using different constructors.
>>
>> You seem to be arguing *conceptually*, not in terms of constructor calls
>> specifically. You seem to be saying that a "container" (for want of a
>> better term) is expected to default to being empty, and if it doesn't,
>> people will find that odd. A vector can be empty because it's a container.
>>
>> So the question is this: is `variant` a container?
>>
>
> Another strawman. A type should be default constructible if and only if
> it has an unsurprising default value:
>
> std::any a;
> std::function<int(int)> f;
> std::thread t;
> std::optional<float> i;
> std::unique_ptr<Matrix> p;
> std::vector<Widget> v;
>
> All of the above variables are empty. If the above code compiles, then
> people would expect these variables to be empty or null or void or invalid
> or devoid of value, or whatever you want to call it. And they are.
>
> For std::variant<Left,Right>, default constructing to hold a value of type
> Left is absurd. Most would consider it extremely surprising. Most would
> (rightfully) not expect the first listed type to have any special meaning
> or behavior. That is so, irrespective of whether std::variant<Right,Left>
> is the same type. (Most understand there is implementation-difficultly in
> making std::variant<Left,Right> formally the same type as
> std::variant<Right,Left>, but we shouldn't exacerbate that by giving the
> first type in the list special-meaning.)
>
> An exactly-one variant should not be default constructible. It has no
> sensible default value.
>
> An at-most-one variant should default construct to the empty value.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--f46d0418270c55a8150520b06154
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Furthermore...<div><br></div><div>While it is fine if std:=
:variant<Left, Right> and std::variant<Right,Left> are not the =
same type (as comparing type lists as unordered sets is prohibitively expen=
sive, and we lose the ability to index the type list, etc) I could easily i=
magine equality (but not comparison) being defined across variants as follo=
ws:<div><br></div><div>=C2=A0 =C2=A0 bool operator=3D=3D(const std::variant=
<T...>& a, const std::variant<U...>& b) {</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0if (variants can be empty, and both a and b are emp=
ty)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return true;</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0else if (a and b hold a value of the same type X)<b=
r></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return X(a) =3D=3D X(b);</di=
v><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0else<br></div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0return false;</div><div>=C2=A0 =C2=A0 }</div><div><br></div><d=
iv>In this case:</div><div><br></div><div>=C2=A0 =C2=A0 std::variant<Lef=
t, Right> v1;</div><div>=C2=A0 =C2=A0 std::variant<Right, Left> v2=
;</div><div><br></div><div>=C2=A0 =C2=A0 Is v1 =3D=3D v2 ?</div><div><br></=
div><div>It would be expected that they are equal.</div><div><br></div><div=
>In the case of an exactly-one variant that surprisingly constructed a valu=
e of the first type, they would not be.</div><div><br></div></div><div>In t=
he case of an at-most-one variant that default constructed to empty, they w=
ould be, as expected.</div><div><br></div></div><div class=3D"gmail_extra">=
<br><div class=3D"gmail_quote">On Sun, Sep 27, 2015 at 2:58 AM, Andrew Toma=
zos <span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=
=3D"_blank">andrewtomazos@gmail.com</a>></span> wrote:<br><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div c=
lass=3D"gmail_quote">On Sun, Sep 27, 2015 at 2:09 AM, Nicol Bolas <span dir=
=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmcke=
sson@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On S=
aturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:<span=
><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote">On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <span dir=3D=
"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<br><b=
lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px =
#ccc solid;padding-left:1ex">On Saturday, September 26, 2015 at 6:02:15 PM =
UTC-4, Andrew Tomazos wrote:<span><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><div class=3D"gmail_quote">On Sat, Sep 26, 2015 at 4=
:51 PM, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail=
..com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>`any` has=
the concept of being "empty", not to be orthogonal with `functio=
n` does. Both of these are allowed to be empty because C++ users need to be=
able to default-construct types. And since both of these are holders of mo=
re-or-less any type, they have no reasonable default state which could be <=
i>valid</i>. Therefore, the choices are to make them not default-constructa=
ble at all, or give them an empty state. The latter was considered better.<=
br></div></blockquote><div>=C2=A0</div><div>An exactly-one variant does not=
have any reasonable default value.</div><div><br></div><div>An exactly-one=
variant should not have a default constructor.</div><div><br></div><div>De=
fault constructing the first type is an absurd idea:</div><div><br></div><d=
iv>=C2=A0 =C2=A0struct L { ... };</div><div>=C2=A0 =C2=A0struct R { ... };<=
/div><div><br></div><div>=C2=A0 =C2=A0using V =3D std::variant<L, R>;=
</div><div><br></div><div>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V v2(em=
place<L>);</div><div>=C2=A0 =C2=A0V v3(emplace<R>);</div><div><=
br></div><div>Now v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 That's ridiculous.=
</div></div></div></div></blockquote></span><div><br>... how is that ridicu=
lous?<br><br><div style=3D"background-color:rgb(250,250,250);border-color:r=
gb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><=
code><div><span style=3D"color:#000">vector</span><span style=3D"color:#080=
"><int></span><span style=3D"color:#000"> t1</span><span style=3D"col=
or:#660">;</span><span style=3D"color:#000"><br>vector</span><span style=3D=
"color:#080"><int></span><span style=3D"color:#000"> t2</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#066">0</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#066">0</span><span style=3D"color:#660">);</span><span style=3D"color=
:#000"><br>vector</span><span style=3D"color:#080"><int></span><span =
style=3D"color:#000"> t3</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#066">1</span><span style=3D"color:#660">,</span><span style=3D=
"color:#000"> </span><span style=3D"color:#066">3</span><span style=3D"colo=
r:#660">);</span></div></code></div><br>t1 =3D=3D t2, but t1 !=3D t3.</div>=
</blockquote><div>=C2=A0</div><div>The default constructor of vector produc=
es an empty vector, as you would expect.</div></div></div></div></blockquot=
e></span><div><br>OK, from my perspective, the point of your example was &q=
uot;calling a non-default constructor with a certain parameter yielded equa=
lity with the default constructor, but using a different value made a diffe=
rent object." My example showed why that wasn't "ridiculous&q=
uot;; it is expected that you might get the default case by using different=
constructors.<br><br>You seem to be arguing <i>conceptually</i>, not in te=
rms of constructor calls specifically. You seem to be saying that a "c=
ontainer" (for want of a better term) is expected to default to being =
empty, and if it doesn't, people will find that odd. A vector can be em=
pty because it's a container.<br><br>So the question is this: is `varia=
nt` a container?<br></div></blockquote><div><br></div><div>Another strawman=
..=C2=A0 A type should be default constructible if and only if it has an uns=
urprising default value:</div><div><br></div><div>=C2=A0 =C2=A0std::any a;=
=C2=A0</div><div>=C2=A0 =C2=A0std::function<int(int)> f;</div><div>=
=C2=A0 =C2=A0std::thread t;</div><div>=C2=A0 =C2=A0std::optional<float&g=
t; i;</div><div>=C2=A0 =C2=A0std::unique_ptr<Matrix> p;</div><div>=C2=
=A0 =C2=A0std::vector<Widget> v;</div><div><br></div><div>All of the =
above variables are empty.=C2=A0 If the above code compiles, then people wo=
uld expect these variables to be empty or null or void or invalid or devoid=
of value, or whatever you want to call it.=C2=A0 And they are.</div><div><=
br></div><div>For std::variant<Left,Right>, default constructing to h=
old a value of type Left is absurd.=C2=A0 Most would consider it extremely =
surprising.=C2=A0 Most would (rightfully) not expect the first listed type =
to have any special meaning or behavior.=C2=A0 That is so, irrespective of =
whether std::variant<Right,Left> is the same type. =C2=A0 (Most under=
stand there is implementation-difficultly in making std::variant<Left,Ri=
ght> formally the same type as std::variant<Right,Left>, but we sh=
ouldn't exacerbate that by giving the first type in the list special-me=
aning.)</div><div><br></div><div>An exactly-one variant should not be defau=
lt constructible.=C2=A0 It has no sensible default value.</div><div><br></d=
iv><div>An at-most-one variant should default construct to the empty value.=
</div><span class=3D"HOEnZb"><font color=3D"#888888"><div><br></div></font>=
</span></div></div></div><span class=3D"HOEnZb"><font color=3D"#888888">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--f46d0418270c55a8150520b06154--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sat, 26 Sep 2015 22:56:43 -0300
Raw View
On 9/26/2015 10:20 PM, Andrew Tomazos wrote:
> Furthermore...
>
> While it is fine if std::variant<Left, Right> and
> std::variant<Right,Left> are not the same type (as comparing type lists
> as unordered sets is prohibitively expensive, and we lose the ability to
> index the type list, etc)
I believe there is no discussion that a pure implementation of a sum=20
type is simply not possible with the language as currently specified.
> In this case:
>
> std::variant<Left, Right> v1;
> std::variant<Right, Left> v2;
>
> Is v1 =3D=3D v2 ?
>
> It would be expected that they are equal.
I would not expect `bool operator=3D=3D(variant<Ts...> const&,=20
variant<Us...> const&)` to exist at all.
> In the case of an exactly-one variant that surprisingly constructed a
> value of the first type, they would not be.
For a pure sum type, `variant<T, U>` and `variant<U, T>` are the exact=20
same type, so no mixed comparison is needed. But a pure sum type would=20
not be default constructible either, there is no sensible member to pick=20
for default construction as they are all equal, there is no sensible=20
expectation for that snippet.
But pure sum types are unimplementable in C++, we are talking about=20
C++'s approximation to sum types. If you buy that such approximation=20
ought to be default constructible (for no good reason), then I would=20
expect those two to be non-equal, conceptually. I'm not sure I would=20
define that mixed comparison operator still. While those types=20
theoretically represent the same set of values, pretending they are=20
interchangeable only goes so far before breaking.
> In the case of an at-most-one variant that default constructed to empty,
> they would be, as expected.
For a discriminated union, I would not expect them to be equal. Those=20
are simply two distinct `U1` and `U2` types, there's no relation between=20
them.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 04:34:30 +0200
Raw View
--f46d0418270ca7c9f50520b16bae
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sun, Sep 27, 2015 at 3:56 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
> On 9/26/2015 10:20 PM, Andrew Tomazos wrote:
>
>> Furthermore...
>>
>> While it is fine if std::variant<Left, Right> and
>> std::variant<Right,Left> are not the same type (as comparing type lists
>> as unordered sets is prohibitively expensive, and we lose the ability to
>> index the type list, etc)
>>
>
> I believe there is no discussion that a pure implementation of a sum type
> is simply not possible with the language as currently specified.
>
> In this case:
>>
>> std::variant<Left, Right> v1;
>> std::variant<Right, Left> v2;
>>
>> Is v1 =3D=3D v2 ?
>>
>> It would be expected that they are equal.
>>
>
> I would not expect `bool operator=3D=3D(variant<Ts...> const&, variant<Us=
....>
> const&)` to exist at all.
>
> In the case of an exactly-one variant that surprisingly constructed a
>> value of the first type, they would not be.
>>
>
> For a pure sum type, `variant<T, U>` and `variant<U, T>` are the exact
> same type, so no mixed comparison is needed. But a pure sum type would no=
t
> be default constructible either, there is no sensible member to pick for
> default construction as they are all equal, there is no sensible
> expectation for that snippet.
>
> But pure sum types are unimplementable in C++, we are talking about C++'s
> approximation to sum types. If you buy that such approximation ought to b=
e
> default constructible (for no good reason), then I would expect those two
> to be non-equal, conceptually. I'm not sure I would define that mixed
> comparison operator still. While those types theoretically represent the
> same set of values, pretending they are interchangeable only goes so far
> before breaking.
>
> In the case of an at-most-one variant that default constructed to empty,
>> they would be, as expected.
>>
>
> For a discriminated union, I would not expect them to be equal. Those are
> simply two distinct `U1` and `U2` types, there's no relation between them=
..
>
> I mostly agree with your comments.
I would be careful to draw a distinction between equality being undefined
between two objects, and the two objects being unequal. In the first case
`a =3D=3D b` won't compile. In the second case `a =3D=3D b` compiles and i=
s
evaluated to false.
I'm actually fine with equality being undefined across different variant
types. I'm just using the above example to illustrate why an exactly-one
variant default constructing the first type is surprising. An exactly-one
variant shouldn't be default-constructible, as it has no sensible default
value.
--=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/.
--f46d0418270ca7c9f50520b16bae
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 S=
un, Sep 27, 2015 at 3:56 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <span dir=3D"l=
tr"><<a href=3D"mailto:kaballo86@hotmail.com" target=3D"_blank">kaballo8=
6@hotmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span=
class=3D"">On 9/26/2015 10:20 PM, Andrew Tomazos wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Furthermore...<br>
<br>
While it is fine if std::variant<Left, Right> and<br>
std::variant<Right,Left> are not the same type (as comparing type lis=
ts<br>
as unordered sets is prohibitively expensive, and we lose the ability to<br=
>
index the type list, etc)<br>
</blockquote>
<br></span>
I believe there is no discussion that a pure implementation of a sum type i=
s simply not possible with the language as currently specified.<span class=
=3D""><br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
In this case:<br>
<br>
=C2=A0 =C2=A0 =C2=A0std::variant<Left, Right> v1;<br>
=C2=A0 =C2=A0 =C2=A0std::variant<Right, Left> v2;<br>
<br>
=C2=A0 =C2=A0 =C2=A0Is v1 =3D=3D v2 ?<br>
<br>
It would be expected that they are equal.<br>
</blockquote>
<br></span>
I would not expect `bool operator=3D=3D(variant<Ts...> const&, va=
riant<Us...> const&)` to exist at all.<span class=3D""><br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
In the case of an exactly-one variant that surprisingly constructed a<br>
value of the first type, they would not be.<br>
</blockquote>
<br></span>
For a pure sum type, `variant<T, U>` and `variant<U, T>` are th=
e exact same type, so no mixed comparison is needed. But a pure sum type wo=
uld not be default constructible either, there is no sensible member to pic=
k for default construction as they are all equal, there is no sensible expe=
ctation for that snippet.<br>
<br>
But pure sum types are unimplementable in C++, we are talking about C++'=
;s approximation to sum types. If you buy that such approximation ought to =
be default constructible (for no good reason), then I would expect those tw=
o to be non-equal, conceptually. I'm not sure I would define that mixed=
comparison operator still. While those types theoretically represent the s=
ame set of values, pretending they are interchangeable only goes so far bef=
ore breaking.<span class=3D""><br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
In the case of an at-most-one variant that default constructed to empty,<br=
>
they would be, as expected.<br>
</blockquote>
<br></span>
For a discriminated union, I would not expect them to be equal. Those are s=
imply two distinct `U1` and `U2` types, there's no relation between the=
m.<br><span class=3D"im HOEnZb"><br></span></blockquote><div>I mostly agree=
with your comments.</div><div><br></div><div>I would be careful to draw a =
distinction between equality being undefined between two objects, and the t=
wo objects being unequal.=C2=A0 In the first case `a =3D=3D b` won't co=
mpile.=C2=A0 In the second case `a =3D=3D b` compiles and is evaluated to f=
alse.</div></div><br></div><div class=3D"gmail_extra">I'm actually fine=
with equality being undefined across different variant types.=C2=A0 I'=
m just using the above example to illustrate why an exactly-one variant def=
ault constructing the first type is surprising.=C2=A0 An exactly-one varian=
t shouldn't be default-constructible, as it has no sensible default val=
ue.<br></div><div class=3D"gmail_extra"><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--f46d0418270ca7c9f50520b16bae--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 19:44:52 -0700 (PDT)
Raw View
------=_Part_2989_1263845744.1443321893019
Content-Type: multipart/alternative;
boundary="----=_Part_2990_496338966.1443321893019"
------=_Part_2990_496338966.1443321893019
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 10:34:32 PM UTC-4, Andrew Tomazos wrote:
>
> On Sun, Sep 27, 2015 at 3:56 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
> kaba...@hotmail.com <javascript:>> wrote:
>
>> On 9/26/2015 10:20 PM, Andrew Tomazos wrote:
>>
>>> Furthermore...
>>>
>>> While it is fine if std::variant<Left, Right> and
>>> std::variant<Right,Left> are not the same type (as comparing type lists
>>> as unordered sets is prohibitively expensive, and we lose the ability t=
o
>>> index the type list, etc)
>>>
>>
>> I believe there is no discussion that a pure implementation of a sum typ=
e=20
>> is simply not possible with the language as currently specified.
>>
>> In this case:
>>>
>>> std::variant<Left, Right> v1;
>>> std::variant<Right, Left> v2;
>>>
>>> Is v1 =3D=3D v2 ?
>>>
>>> It would be expected that they are equal.
>>>
>>
>> I would not expect `bool operator=3D=3D(variant<Ts...> const&, variant<U=
s...>=20
>> const&)` to exist at all.
>>
>> In the case of an exactly-one variant that surprisingly constructed a
>>> value of the first type, they would not be.
>>>
>>
>> For a pure sum type, `variant<T, U>` and `variant<U, T>` are the exact=
=20
>> same type, so no mixed comparison is needed. But a pure sum type would n=
ot=20
>> be default constructible either, there is no sensible member to pick for=
=20
>> default construction as they are all equal, there is no sensible=20
>> expectation for that snippet.
>>
>> But pure sum types are unimplementable in C++, we are talking about C++'=
s=20
>> approximation to sum types. If you buy that such approximation ought to =
be=20
>> default constructible (for no good reason), then I would expect those tw=
o=20
>> to be non-equal, conceptually. I'm not sure I would define that mixed=20
>> comparison operator still. While those types theoretically represent the=
=20
>> same set of values, pretending they are interchangeable only goes so far=
=20
>> before breaking.
>>
>> In the case of an at-most-one variant that default constructed to empty,
>>> they would be, as expected.
>>>
>>
>> For a discriminated union, I would not expect them to be equal. Those ar=
e=20
>> simply two distinct `U1` and `U2` types, there's no relation between the=
m.
>>
>> I mostly agree with your comments.
>
> I would be careful to draw a distinction between equality being undefined=
=20
> between two objects, and the two objects being unequal. In the first cas=
e=20
> `a =3D=3D b` won't compile. In the second case `a =3D=3D b` compiles and=
is=20
> evaluated to false.
>
> I'm actually fine with equality being undefined across different variant=
=20
> types. I'm just using the above example to illustrate why an exactly-one=
=20
> variant default constructing the first type is surprising. An exactly-on=
e=20
> variant shouldn't be default-constructible, as it has no sensible default=
=20
> value.
>
But that doesn't illustrate your point.
By your own statements, you're "fine" with different variant types being=20
different even if they have the same typelist.
So why would a user be surprised by this:
T1 t1;
T2 t2;
t1 =3D=3D t2; //being false.
It doesn't matter that `T1` and `T2` happen to be variants with reversed=20
typelists. They are two different types. And, as different types, it is=20
entirely reasonable for them to default construct into different values.
--=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_2990_496338966.1443321893019
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Saturday, September 26, 2015 at 10:34:32 PM UTC-4, Andrew Tomazo=
s 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"><div>=
<div class=3D"gmail_quote">On Sun, Sep 27, 2015 at 3:56 AM, Agust=C3=ADn K-=
ballo Berg=C3=A9 <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_b=
lank" gdf-obfuscated-mailto=3D"nRU89eE5CQAJ" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D=
'javascript:';return true;">kaba...@hotmail.com</a>></span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><span>On 9/26/2015 10:20 PM, Andrew To=
mazos wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Furthermore...<br>
<br>
While it is fine if std::variant<Left, Right> and<br>
std::variant<Right,Left> are not the same type (as comparing type lis=
ts<br>
as unordered sets is prohibitively expensive, and we lose the ability to<br=
>
index the type list, etc)<br>
</blockquote>
<br></span>
I believe there is no discussion that a pure implementation of a sum type i=
s simply not possible with the language as currently specified.<span><br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
In this case:<br>
<br>
=C2=A0 =C2=A0 =C2=A0std::variant<Left, Right> v1;<br>
=C2=A0 =C2=A0 =C2=A0std::variant<Right, Left> v2;<br>
<br>
=C2=A0 =C2=A0 =C2=A0Is v1 =3D=3D v2 ?<br>
<br>
It would be expected that they are equal.<br>
</blockquote>
<br></span>
I would not expect `bool operator=3D=3D(variant<Ts...> const&, va=
riant<Us...> const&)` to exist at all.<span><br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
In the case of an exactly-one variant that surprisingly constructed a<br>
value of the first type, they would not be.<br>
</blockquote>
<br></span>
For a pure sum type, `variant<T, U>` and `variant<U, T>` are th=
e exact same type, so no mixed comparison is needed. But a pure sum type wo=
uld not be default constructible either, there is no sensible member to pic=
k for default construction as they are all equal, there is no sensible expe=
ctation for that snippet.<br>
<br>
But pure sum types are unimplementable in C++, we are talking about C++'=
;s approximation to sum types. If you buy that such approximation ought to =
be default constructible (for no good reason), then I would expect those tw=
o to be non-equal, conceptually. I'm not sure I would define that mixed=
comparison operator still. While those types theoretically represent the s=
ame set of values, pretending they are interchangeable only goes so far bef=
ore breaking.<span><br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
In the case of an at-most-one variant that default constructed to empty,<br=
>
they would be, as expected.<br>
</blockquote>
<br></span>
For a discriminated union, I would not expect them to be equal. Those are s=
imply two distinct `U1` and `U2` types, there's no relation between the=
m.<br><span><br></span></blockquote><div>I mostly agree with your comments.=
</div><div><br></div><div>I would be careful to draw a distinction between =
equality being undefined between two objects, and the two objects being une=
qual.=C2=A0 In the first case `a =3D=3D b` won't compile.=C2=A0 In the =
second case `a =3D=3D b` compiles and is evaluated to false.</div></div><br=
></div><div>I'm actually fine with equality being undefined across diff=
erent variant types.=C2=A0 I'm just using the above example to illustra=
te why an exactly-one variant default constructing the first type is surpri=
sing.=C2=A0 An exactly-one variant shouldn't be default-constructible, =
as it has no sensible default value.</div></div></blockquote><div><br>But t=
hat doesn't illustrate your point.<br><br>By your own statements, you&#=
39;re "fine" with different variant types being different even if=
they have the same typelist.<br><br>So why would a user be surprised by th=
is:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">T=
1 t1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>T2 t2</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>t1 </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> t2</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">//being false.</span></div></code></div><br>It doesn'=
t matter that `T1` and `T2` happen to be variants with reversed typelists. =
They are two different types. And, as different types, it is entirely reaso=
nable for them to default construct into different values.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_2990_496338966.1443321893019--
------=_Part_2989_1263845744.1443321893019--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Sat, 26 Sep 2015 21:45:29 -0500
Raw View
--001a11459a404339b60520b195a2
Content-Type: text/plain; charset=UTF-8
On 26 September 2015 at 21:34, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> I'm just using the above example to illustrate why an exactly-one variant
> default constructing the first type is surprising.
In other words, you don't want it default constructible because of a
feature that is not being proposed in any of the current variant proposals
and got rejected from earlier versions of N4542.
I'm glad I'm not smart enough to understand that line of reasoning...
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11459a404339b60520b195a2
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On 26 September 2015 at 21:34, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I'm just usi=
ng the above example to illustrate why an exactly-one variant default const=
ructing the first type is surprising.</blockquote></div><br>In other words,=
you don't want it default constructible because of a feature that is n=
ot being proposed in any of the current variant proposals and got rejected =
from earlier versions of N4542.</div><div class=3D"gmail_extra"><br></div><=
div class=3D"gmail_extra">I'm glad I'm not smart enough to understa=
nd that line of reasoning...<br>-- <br><div class=3D"gmail_signature">=C2=
=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@evi=
loverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847)=
691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11459a404339b60520b195a2--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 26 Sep 2015 19:48:51 -0700 (PDT)
Raw View
------=_Part_939_2124991660.1443322131389
Content-Type: multipart/alternative;
boundary="----=_Part_940_1115329763.1443322131390"
------=_Part_940_1115329763.1443322131390
Content-Type: text/plain; charset=UTF-8
On Saturday, September 26, 2015 at 8:58:44 PM UTC-4, Andrew Tomazos wrote:
>
> On Sun, Sep 27, 2015 at 2:09 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Saturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos wrote:
>>>
>>> On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> On Saturday, September 26, 2015 at 6:02:15 PM UTC-4, Andrew Tomazos
>>>> wrote:
>>>>>
>>>>> On Sat, Sep 26, 2015 at 4:51 PM, Nicol Bolas <jmck...@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> `any` has the concept of being "empty", not to be orthogonal with
>>>>>> `function` does. Both of these are allowed to be empty because C++ users
>>>>>> need to be able to default-construct types. And since both of these are
>>>>>> holders of more-or-less any type, they have no reasonable default state
>>>>>> which could be *valid*. Therefore, the choices are to make them not
>>>>>> default-constructable at all, or give them an empty state. The latter was
>>>>>> considered better.
>>>>>>
>>>>>
>>>>> An exactly-one variant does not have any reasonable default value.
>>>>>
>>>>> An exactly-one variant should not have a default constructor.
>>>>>
>>>>> Default constructing the first type is an absurd idea:
>>>>>
>>>>> struct L { ... };
>>>>> struct R { ... };
>>>>>
>>>>> using V = std::variant<L, R>;
>>>>>
>>>>> V v1;
>>>>> V v2(emplace<L>);
>>>>> V v3(emplace<R>);
>>>>>
>>>>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>>>>
>>>>
>>>> ... how is that ridiculous?
>>>>
>>>> vector<int> t1;
>>>> vector<int> t2(0, 0);
>>>> vector<int> t3(1, 3);
>>>>
>>>> t1 == t2, but t1 != t3.
>>>>
>>>
>>> The default constructor of vector produces an empty vector, as you would
>>> expect.
>>>
>>
>> OK, from my perspective, the point of your example was "calling a
>> non-default constructor with a certain parameter yielded equality with the
>> default constructor, but using a different value made a different object."
>> My example showed why that wasn't "ridiculous"; it is expected that you
>> might get the default case by using different constructors.
>>
>> You seem to be arguing *conceptually*, not in terms of constructor calls
>> specifically. You seem to be saying that a "container" (for want of a
>> better term) is expected to default to being empty, and if it doesn't,
>> people will find that odd. A vector can be empty because it's a container.
>>
>> So the question is this: is `variant` a container?
>>
>
> Another strawman.
>
*NO! NO IT ISN'T!*A strawman <https://en.wikipedia.org/wiki/Straw_man> is
an *example*, one that does not represent the original position and is
designed to fail as an attempt to disprove the original position.
Asking whether a `variant` is a container is not an example of anything;
it's a *question*. And yes, it very much does matter if you see `variant`
as a container, because that means you see it as something which could be
empty. If you see it as a value, then it makes no sense for it to be empty,
no matter how default construction works.
"Strawman" does not mean "thing I don't agree with" or "argument I don't
think works".
std::any a;
> std::function<int(int)> f;
> std::thread t;
> std::optional<float> i;
> std::unique_ptr<Matrix> p;
> std::vector<Widget> v;
>
> All of the above variables are empty. If the above code compiles, then
> people would expect these variables to be empty or null or void or invalid
> or devoid of value, or whatever you want to call it. And they are.
>
That's because they represent types *which can be empty*. If they were
types which *couldn't* be empty, users would not expect default
construction to yield an empty state.
They would expect default construction to yield a reasonable, non-empty
state, as appropriate to their types.
Most would (rightfully) not expect the first listed type to have any
> special meaning or behavior. That is so, irrespective of whether
> std::variant<Right,Left> is the same type. (Most understand there is
> implementation-difficultly in making std::variant<Left,Right> formally the
> same type as std::variant<Right,Left>, but we shouldn't exacerbate that by
> giving the first type in the list special-meaning.)
>
That's an assumption. You're assuming that C++ users *want* variant<Left,
Right> to behave the same as variant<Right, Left>. That they will only see
them as distinct types as a consequence of language limitations, not as an
actual *design feature* of the type.
On what basis do you make that claim?
An exactly-one variant should not be default constructible. It has no
> sensible default value.
>
See, that's where crux of where your argument fails for me. You say that
the first type in the list is not "sensible".
Why? According to whom is it not "sensible"?
This is the behavior of boost::variant. A type that is in use. By actual
people. Probably quite a bit of use. I don't know if it's the most popular
variant type. But it's certainly one of the most available, as its
distributed with a fairly popular C++ package. Indeed, a couple of Boost
libraries make use of it; Boost.Spirit would be lost without it.
If you're going to say that Boost is wrong for doing it that way, you're
going to have to do better than simply appealing to what "people" would
obviously find "sensible". Because boost::variant proves that "people" are
able to use it just fine.
Does everyone agree with this design? Certainly not. But many people are
able to use it well enough. So that's evidence from the real world refuting
your claims.
Do you have anything besides your personal notion of what "people" would
find "sensible" to argue that a never-empty `variant` should not be default
constructible?
`variant` to me is not a sum type. It is a discriminated union value. Being
default constructible is, to be honest, not important to me. I prefer to be
explicit about such things, to reduce static ambiguity as much as possible.
So personally, I won't make much use out of that even if it's available.
However, C++ as a language makes it difficult to use types that have no
default constructor in several ways. It would non-trivially restrict the
utility of `variant` to make it non-default constructible. And allowing it
to be empty is basically off the table, as far as I'm concerned.
So you have to pick one of the types in the list and default construct
that. And `union` already picks the first one (in value-initialization). So
that makes it a "sensible default value".
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_940_1115329763.1443322131390
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 26, 2015 at 8:58:44 PM UTC-4, Andrew Tomazos wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote">On Sun, Sep 27, 2015 at 2:09 AM, Nicol Bolas <span dir=3D=
"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=
=3D"bz8mnac0CQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascri=
pt:';return true;" onclick=3D"this.href=3D'javascript:';return =
true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex">On Saturday, September 26, 2015 at 7:14:47 PM UTC-4, Andrew Tomazos w=
rote:<span><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><d=
iv class=3D"gmail_quote">On Sun, Sep 27, 2015 at 12:39 AM, Nicol Bolas <spa=
n dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex">On Saturday, September 26, 2015 at 6:0=
2:15 PM UTC-4, Andrew Tomazos wrote:<span><blockquote class=3D"gmail_quote"=
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Sat, Sep 26, 201=
5 at 4:51 PM, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...=
@gmail.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>`an=
y` has the concept of being "empty", not to be orthogonal with `f=
unction` does. Both of these are allowed to be empty because C++ users need=
to be able to default-construct types. And since both of these are holders=
of more-or-less any type, they have no reasonable default state which coul=
d be <i>valid</i>. Therefore, the choices are to make them not default-cons=
tructable at all, or give them an empty state. The latter was considered be=
tter.<br></div></blockquote><div>=C2=A0</div><div>An exactly-one variant do=
es not have any reasonable default value.</div><div><br></div><div>An exact=
ly-one variant should not have a default constructor.</div><div><br></div><=
div>Default constructing the first type is an absurd idea:</div><div><br></=
div><div>=C2=A0 =C2=A0struct L { ... };</div><div>=C2=A0 =C2=A0struct R { .=
... };</div><div><br></div><div>=C2=A0 =C2=A0using V =3D std::variant<L, =
R>;</div><div><br></div><div>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V=
v2(emplace<L>);</div><div>=C2=A0 =C2=A0V v3(emplace<R>);</div>=
<div><br></div><div>Now v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 That's ridic=
ulous.</div></div></div></div></blockquote></span><div><br>... how is that =
ridiculous?<br><br><div style=3D"background-color:rgb(250,250,250);border-c=
olor:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-w=
ord"><code><div><span style=3D"color:#000">vector</span><span style=3D"colo=
r:#080"><int></span><span style=3D"color:#000"> t1</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>vector</span><span s=
tyle=3D"color:#080"><int></span><span style=3D"color:#000"> t2</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#066">0</span><span=
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#066">0</span><span style=3D"color:#660">);</span><span style=3D=
"color:#000"><br>vector</span><span style=3D"color:#080"><int></span>=
<span style=3D"color:#000"> t3</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#066">1</span><span style=3D"color:#660">,</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#066">3</span><span style=
=3D"color:#660">);</span></div></code></div><br>t1 =3D=3D t2, but t1 !=3D t=
3.</div></blockquote><div>=C2=A0</div><div>The default constructor of vecto=
r produces an empty vector, as you would expect.</div></div></div></div></b=
lockquote></span><div><br>OK, from my perspective, the point of your exampl=
e was "calling a non-default constructor with a certain parameter yiel=
ded equality with the default constructor, but using a different value made=
a different object." My example showed why that wasn't "ridi=
culous"; it is expected that you might get the default case by using d=
ifferent constructors.<br><br>You seem to be arguing <i>conceptually</i>, n=
ot in terms of constructor calls specifically. You seem to be saying that a=
"container" (for want of a better term) is expected to default t=
o being empty, and if it doesn't, people will find that odd. A vector c=
an be empty because it's a container.<br><br>So the question is this: i=
s `variant` a container?<br></div></blockquote><div><br></div><div>Another =
strawman.</div></div></div></div></blockquote><div><br><b><u><i>NO! NO IT I=
SN'T!<br><br></i></u></b><a href=3D"https://en.wikipedia.org/wiki/Straw=
_man">A strawman</a> is an <i>example</i>, one that does not represent the =
original position and is designed to fail as an attempt to disprove the ori=
ginal position.<br><br>Asking whether a `variant` is a container is not an =
example of anything; it's a <i>question</i>. And yes, it very much does=
matter if you see `variant` as a container, because that means you see it =
as something which could be empty. If you see it as a value, then it makes =
no sense for it to be empty, no matter how default construction works.<br><=
br>"Strawman" does not mean "thing I don't agree with&qu=
ot; or "argument I don't think works".<br></div><div><br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"><div></div><div>=C2=A0 =C2=A0std::any a;=C2=A0</div><d=
iv>=C2=A0 =C2=A0std::function<int(int)> f;</div><div>=C2=A0 =C2=A0std=
::thread t;</div><div>=C2=A0 =C2=A0std::optional<float> i;</div><div>=
=C2=A0 =C2=A0std::unique_ptr<Matrix> p;</div><div>=C2=A0 =C2=A0std::v=
ector<Widget> v;</div><div><br></div><div>All of the above variables =
are empty. If the above code compiles, then people would expect these varia=
bles to be empty or null or void or invalid or devoid of value, or whatever=
you want to call it.=C2=A0 And they are.</div></div></div></div></blockquo=
te><div><br>That's because they represent types <i>which can be empty</=
i>. If they were types which <i>couldn't</i> be empty, users would not =
expect default construction to yield an empty state.<br><br>They would expe=
ct default construction to yield a reasonable, non-empty state, as appropri=
ate to their types.<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><div class=3D"gmail_quote"><div>Most would (rightf=
ully) not expect the first listed type to have any special meaning or behav=
ior.=C2=A0 That is so, irrespective of whether std::variant<Right,Left&g=
t; is the same type.=C2=A0 (Most understand there is implementation-difficu=
ltly in making std::variant<Left,Right> formally the same type as std=
::variant<Right,Left>, but we shouldn't exacerbate that by giving=
the first type in the list special-meaning.)</div></div></div></div></bloc=
kquote><div><br>That's an assumption. You're assuming that C++ user=
s <i>want</i> variant<Left, Right> to behave the same as variant<R=
ight, Left>. That they will only see them as distinct types as a consequ=
ence of language limitations, not as an actual <i>design feature</i> of the=
type.<br><br>On what basis do you make that claim?<br><br></div><blockquot=
e 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><div class=3D"gmai=
l_quote"><div></div><div>An exactly-one variant should not be default const=
ructible.=C2=A0 It has no sensible default value.</div></div></div></div></=
blockquote><div><br>See, that's where crux of where your argument fails=
for me. You say that the first type in the list is not "sensible"=
;.<br><br>Why? According to whom is it not "sensible"?<br><br>Thi=
s is the behavior of boost::variant. A type that is in use. By actual peopl=
e. Probably quite a bit of use. I don't know if it's the most popul=
ar variant type. But it's certainly one of the most available, as its d=
istributed with a fairly popular C++ package. Indeed, a couple of Boost lib=
raries make use of it; Boost.Spirit would be lost without it.<br><br>If you=
're going to say that Boost is wrong for doing it that way, you're =
going to have to do better than simply appealing to what "people"=
would obviously find "sensible". Because boost::variant proves t=
hat "people" are able to use it just fine.<br><br>Does everyone a=
gree with this design? Certainly not. But many people are able to use it we=
ll enough. So that's evidence from the real world refuting your claims.=
<br><br>Do you have anything besides your personal notion of what "peo=
ple" would find "sensible" to argue that a never-empty `vari=
ant` should not be default constructible?<br><br>`variant` to me is not a s=
um type. It is a discriminated union value. Being default constructible is,=
to be honest, not important to me. I prefer to be explicit about such thin=
gs, to reduce static ambiguity as much as possible. So personally, I won=
9;t make much use out of that even if it's available.<br><br>However, C=
++ as a language makes it difficult to use types that have no default const=
ructor in several ways. It would non-trivially restrict the utility of `var=
iant` to make it non-default constructible. And allowing it to be empty is =
basically off the table, as far as I'm concerned.<br><br>So you have to=
pick one of the types in the list and default construct that. And `union` =
already picks the first one (in value-initialization). So that makes it a &=
quot;sensible default value".<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_940_1115329763.1443322131390--
------=_Part_939_2124991660.1443322131389--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 04:58:53 +0200
Raw View
--089e0103009cd017cb0520b1c272
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 4:45 AM, Nevin Liber <nevin@eviloverlord.com> wrote:
>
> On 26 September 2015 at 21:34, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> I'm just using the above example to illustrate why an exactly-one variant
>> default constructing the first type is surprising.
>
>
> In other words, you don't want it default constructible because of a
> feature that is not being proposed in any of the current variant proposals
> and got rejected from earlier versions of N4542.
>
>
Let me clarify my claim.
*IF* the following code compiles:
struct L { ... };
struct R { ... };
using V = std::variant<L, R>;
V v1;
V v2(emplace<L>);
V v3(emplace<R>);
*THEN* most programmers will expect that v1, v2 and v3 have three distinct
values.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0103009cd017cb0520b1c272
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 S=
un, Sep 27, 2015 at 4:45 AM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord=
er-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_=
extra"><span class=3D""><br><div class=3D"gmail_quote">On 26 September 2015=
at 21:34, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andrewtom=
azos@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a>></span> wr=
ote:<br><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">I'm just using the above example to illustrate=
why an exactly-one variant default constructing the first type is surprisi=
ng.</blockquote></div><br></span>In other words, you don't want it defa=
ult constructible because of a feature that is not being proposed in any of=
the current variant proposals and got rejected from earlier versions of N4=
542.</div><div class=3D"gmail_extra"><br></div></div></blockquote><div><br>=
</div><div>Let me clarify my claim.</div><div><br></div><div>*IF* the follo=
wing code compiles:</div><div><br></div><div><div style=3D"font-size:12.8px=
">=C2=A0 =C2=A0struct L { ... };</div><div style=3D"font-size:12.8px">=C2=
=A0 =C2=A0struct R { ... };</div><div style=3D"font-size:12.8px"><br></div>=
<div style=3D"font-size:12.8px">=C2=A0 =C2=A0using V =3D std::variant<L,=
R>;</div><div style=3D"font-size:12.8px"><br></div><div style=3D"font-s=
ize:12.8px">=C2=A0 =C2=A0V v1;</div><div style=3D"font-size:12.8px">=C2=A0 =
=C2=A0V v2(emplace<L>);</div><div style=3D"font-size:12.8px">=C2=A0 =
=C2=A0V v3(emplace<R>);</div><div style=3D"font-size:12.8px"></div></=
div><div style=3D"font-size:12.8px"><br></div><div style=3D"font-size:12.8p=
x">*THEN* most programmers will expect that v1, v2 and v3 have three distin=
ct values.</div><div style=3D"font-size:12.8px"><br></div></div></div></div=
>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0103009cd017cb0520b1c272--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sun, 27 Sep 2015 00:03:26 -0300
Raw View
On 9/26/2015 11:45 PM, Nevin Liber wrote:
>
> On 26 September 2015 at 21:34, Andrew Tomazos <andrewtomazos@gmail.com
> <mailto:andrewtomazos@gmail.com>> wrote:
>
> I'm just using the above example to illustrate why an exactly-one
> variant default constructing the first type is surprising.
>
>
> In other words, you don't want it default constructible because of a
> feature that is not being proposed in any of the current variant
> proposals and got rejected from earlier versions of N4542.
That sounds like a misrepresentation. I for once said I believe=20
mixed-equality the concept should exist for a sum type while=20
mixed-equality the operator should not. Think of iostreams, we can=20
define two of them as being equal if they have the same contents, but=20
that's not something you'd want to call `operator=3D=3D`.
Conceptually, you have two types that share a single set of values,=20
using slightly different underlying representation. The fact that the=20
same operation on types that represent the same notion yields different=20
results is surprising, regardless of whether you can express that in=20
code via `operator=3D=3D`. The trap in the reasoning is in believing that=
=20
`variant` models a sum type, while a sum type cannot be modeled in C++.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 05:09:03 +0200
Raw View
--001a11c2b90c3081470520b1e7ee
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sun, Sep 27, 2015 at 5:03 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
> On 9/26/2015 11:45 PM, Nevin Liber wrote:
>
>>
>> On 26 September 2015 at 21:34, Andrew Tomazos <andrewtomazos@gmail.com
>> <mailto:andrewtomazos@gmail.com>> wrote:
>>
>> I'm just using the above example to illustrate why an exactly-one
>> variant default constructing the first type is surprising.
>>
>>
>> In other words, you don't want it default constructible because of a
>> feature that is not being proposed in any of the current variant
>> proposals and got rejected from earlier versions of N4542.
>>
>
> That sounds like a misrepresentation. I for once said I believe
> mixed-equality the concept should exist for a sum type while mixed-equali=
ty
> the operator should not. Think of iostreams, we can define two of them as
> being equal if they have the same contents, but that's not something you'=
d
> want to call `operator=3D=3D`.
>
> Conceptually, you have two types that share a single set of values, using
> slightly different underlying representation. The fact that the same
> operation on types that represent the same notion yields different result=
s
> is surprising, regardless of whether you can express that in code via
> `operator=3D=3D`. The trap in the reasoning is in believing that `variant=
`
> models a sum type, while a sum type cannot be modeled in C++.
+1
--=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/.
--001a11c2b90c3081470520b1e7ee
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sun, Sep 27, 2015 at 5:03 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <span =
dir=3D"ltr"><<a href=3D"mailto:kaballo86@hotmail.com" target=3D"_blank">=
kaballo86@hotmail.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"><span class=3D"">On 9/26/2015 11:45 PM, Nevin Liber wrote:<br>
</span><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-=
left:1px #ccc solid;padding-left:1ex"><span class=3D"">
<br>
On 26 September 2015 at 21:34, Andrew Tomazos <<a href=3D"mailto:andrewt=
omazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a><br></span><=
span class=3D"">
<mailto:<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">and=
rewtomazos@gmail.com</a>>> wrote:<br>
<br>
=C2=A0 =C2=A0 I'm just using the above example to illustrate why an exa=
ctly-one<br>
=C2=A0 =C2=A0 variant default constructing the first type is surprising.<br=
>
<br>
<br>
In other words, you don't want it default constructible because of a<br=
>
feature that is not being proposed in any of the current variant<br>
proposals and got rejected from earlier versions of N4542.<br>
</span></blockquote>
<br>
That sounds like a misrepresentation. I for once said I believe mixed-equal=
ity the concept should exist for a sum type while mixed-equality the operat=
or should not. Think of iostreams, we can define two of them as being equal=
if they have the same contents, but that's not something you'd wan=
t to call `operator=3D=3D`.<br>
<br>
Conceptually, you have two types that share a single set of values, using s=
lightly different underlying representation. The fact that the same operati=
on on types that represent the same notion yields different results is surp=
rising, regardless of whether you can express that in code via `operator=3D=
=3D`. The trap in the reasoning is in believing that `variant` models a sum=
type, while a sum type cannot be modeled in C++.</blockquote><div><br></di=
v><div>+1</div><div>=C2=A0<br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2b90c3081470520b1e7ee--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 27 Sep 2015 05:20:36 +0200
Raw View
--f46d04462e6a85b98b0520b21079
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 4:48 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> std::any a;
>> std::function<int(int)> f;
>> std::thread t;
>> std::optional<float> i;
>> std::unique_ptr<Matrix> p;
>> std::vector<Widget> v;
>>
>> All of the above variables are empty. If the above code compiles, then
>> people would expect these variables to be empty or null or void or invalid
>> or devoid of value, or whatever you want to call it. And they are.
>>
>
> That's because they represent types *which can be empty*.
>
A variant can be empty too. Set the discriminator to -1, and leave the
storage uninitialized. Voila, an empty variant.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--f46d04462e6a85b98b0520b21079
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 S=
un, Sep 27, 2015 at 4:48 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><span class=3D""><blockquote clas=
s=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 class=3D"gmail_quote"><d=
iv></div><div>=C2=A0 =C2=A0std::any a;=C2=A0</div><div>=C2=A0 =C2=A0std::fu=
nction<int(int)> f;</div><div>=C2=A0 =C2=A0std::thread t;</div><div>=
=C2=A0 =C2=A0std::optional<float> i;</div><div>=C2=A0 =C2=A0std::uniq=
ue_ptr<Matrix> p;</div><div>=C2=A0 =C2=A0std::vector<Widget> v;=
</div><div><br></div><div>All of the above variables are empty. If the abov=
e code compiles, then people would expect these variables to be empty or nu=
ll or void or invalid or devoid of value, or whatever you want to call it.=
=C2=A0 And they are.</div></div></div></div></blockquote></span><div><br>Th=
at's because they represent types <i>which can be empty</i>.</div></blo=
ckquote><div></div></div><br></div><div class=3D"gmail_extra">A variant can=
be empty too.=C2=A0 Set the discriminator to -1, and leave the storage uni=
nitialized.=C2=A0 Voila, an empty variant.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--f46d04462e6a85b98b0520b21079--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 27 Sep 2015 14:48:02 -0700
Raw View
--001a1134e2120c48a20520c18916
Content-Type: text/plain; charset=UTF-8
On Sat, Sep 26, 2015 at 12:55 PM, Nevin Liber <nevin@eviloverlord.com>
wrote:
> On 26 September 2015 at 14:44, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>>
>> I prefer never empty with the strong guarantee.
>>
>
> None of the proposals give you that, as you'd have to pessimize assignment
> to the already engaged type to achieve it. Of the proposals talked about
> here, Williams.Variant comes closest to this.
>
This. If you want the strong guarantee and you need it to work even when
emplacement/move-construction throw an exception, then you pretty much need
some kind of backup storage and users effectively need to pay for that in
some fashion even in the non-exceptional case. Also, if you do have backup
storage, then you generally do not need/want an "invalid" state (I
personally would argue that you don't need the invalid state in any case,
but that's another story).
The basis of my suggestion is the following: instead of trying to decide on
and specify the trade-off in the library (partial double-storage or dynamic
backup, or invalid state, etc.), we instead just constrain the assignment
operator to those sets of field types for which there is no serious
trade-off. Further, we should not be afraid to use one of the fields as a
fallback. If the library itself doesn't make the trade-off, but users have
one in mind, there is nothing stopping them from using the library-provided
solution as a building block. On the other hand, if we try to pick one of
these trade-offs and it is not satisfactory for a given application, then
the user's only option is to build something completely from scratch, which
is much more difficult to do correctly.
I really want to dispel the myth that we need an invalid state in the event
that an exception is thrown. It has been claimed in this thread and
elsewhere that we shouldn't use a "fallback" type (Boost uses a fallback
field when possible), since then you don't know that you got there by way
of exception. This is irrelevant and also not true in practice. Any time
that you have a function that operates on an object of any type and that
function only provides the basic exception guarantee, the object in
question is left in some unspecified state for which the type's invariants
are still maintained. This is nothing unique to variant and does not imply
the introduction of an invalid state. All that we'd be doing by introducing
an invalid state is weaken our invariants and complicate contracts of
associated functions. If an exception is thrown, you just leave the object
in a state that doesn't violate the type's invariants. That's exactly what
the basic guarantee is. Users know that they cannot rely on the object
being in any one specific state at that point because an exception has
propagated. It would be great if all functions could easily be nothrow or
have the strong exception guarantee, but that is not reality and it has
never been the intent since the exception guarantees were first introduced
for functions to try to force the strong exception guarantee when it is not
a natural fit.
The reason why it's tough to even satisfy the basic guarantee in this case
is that in the intermediate state between destruction of a field and the
re-construction of a new field, an exception may be thrown, and there may
not be any way to get back to a sensible state in a way that cannot throw.
If there is some field type that is no-except default constructible, you
can use that, and there is nothing wrong with that (this is precisely what
Boost does, though voting in the committee unfortunately decided this is
not a good idea, and I think that is a huge mistake). Similarly, if there
is no no-except default constructible field and you have a field with a
move-constructor that can throw, you can just say that's a violation of the
requirements of assignment, leaving the rest of the type perfectly usable.
This is fine first because not all uses require that operation and also
because there are a couple of simple ways to get around this: A) the user
adds some monostate field that is noexcept default-constructible -or- (if
you accept my suggestions regarding optional) B) just use an
optional<variant<T...>> in that specific case. Both of these solutions
avoid having to make any changes to existing field types and produce a
solution that is assignable, meets the strong guarantee, and has no
intrinsic invalid state. Alternatively, you can also just deal with the
offending non-noexcept-move-constructible field via indirection (I.E. make
the field it a unique_ptr instead, which doesn't even require it using
dynamic memory allocation, though even if you did use dynamic memory
allocation, understand that frequently the reason why a move-constructor is
not noexcept to begin with is because it needs to do dynamic memory
allocation, so the rationale of avoiding dynamic memory allocation is
questionable).
Regarding the strong exception guarantee, as people have said, the strong
guarantee is easier to deal with than the basic guarantee, and I agree.
Understand though that if you need that guarantee you can get it by
building on top of a simpler variant that only has the basic guarantee --
for instance you can implement a double-storage solution in something that
encapsulates the more basic variant, and users of the more basic variant do
not need to pay for it. Also realize that even when handling an exception
that is thrown, you do not always have to get back to the original state.
People get by with functions that offer only the basic guarantee and they
do not always do so by making backups. Frequently this is the case when you
handle the exception at some higher level in the stack.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134e2120c48a20520c18916
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 S=
at, Sep 26, 2015 at 12:55 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"=
mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.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"">On 26 September 2015 at 14:44, Nicol Bolas <span dir=3D"ltr">&l=
t;<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.=
com</a>></span> wrote:<br></span><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><span class=3D""><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br></bl=
ockquote><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div>I prefer never empty with the =
strong guarantee. </div></blockquote><div><br></div></span><div>None of the=
proposals give you that, as you'd have to pessimize assignment to the =
already engaged type to achieve it.=C2=A0 Of the proposals talked about her=
e, Williams.Variant comes closest to this.</div></div></div></div></blockqu=
ote><div><br></div><div>This. If you want the strong guarantee and you need=
it to work even when emplacement/move-construction throw an exception, the=
n you pretty much need some kind of backup storage and users effectively ne=
ed to pay for that in some fashion even in the non-exceptional case. Also, =
if you do have backup storage, then you generally do not need/want an "=
;invalid" state (I personally would argue that you don't need the =
invalid state in any case, but that's another story).</div><div><br></d=
iv><div>The basis of my suggestion is the following: instead of trying to d=
ecide on and specify the trade-off in the library (partial double-storage o=
r dynamic backup, or invalid state, etc.), we instead just constrain the as=
signment operator to those sets of field types for which there is no seriou=
s trade-off. Further, we should not be afraid to use one of the fields as a=
fallback. If the library itself doesn't make the trade-off, but users =
have one in mind, there is nothing stopping them from using the library-pro=
vided solution as a building block. On the other hand, if we try to pick on=
e of these trade-offs and it is not satisfactory for a given application, t=
hen the user's only option is to build something completely from scratc=
h, which is much more difficult to do correctly.</div><div><br></div><div>I=
really want to dispel the myth that we need an invalid state in the event =
that an exception is thrown. It has been claimed in this thread and elsewhe=
re that we shouldn't use a "fallback" type (Boost uses a fall=
back field when possible), since then you don't know that you got there=
by way of exception. This is irrelevant and also not true in practice. Any=
time that you have a function that operates on an object of any type and t=
hat function only provides the basic exception guarantee, the object in que=
stion is left in some unspecified state for which the type's invariants=
are still maintained. This is nothing unique to variant and does not imply=
the introduction of an invalid state. All that we'd be doing by introd=
ucing an invalid state is weaken our invariants and complicate contracts of=
associated functions. If an exception is thrown, you just leave the object=
in a state that doesn't violate the type's invariants. That's =
exactly what the basic guarantee is. Users know that they cannot rely on th=
e object being in any one specific state at that point because an exception=
has propagated. It would be great if all functions could easily be nothrow=
or have the strong exception guarantee, but that is not reality and it has=
never been the intent since the exception guarantees were first introduced=
for functions to try to force the strong exception guarantee when it is no=
t a natural fit.</div><div><br></div><div>The reason why it's tough to =
even satisfy the basic guarantee in this case is that in the intermediate s=
tate between destruction of a field and the re-construction of a new field,=
an exception may be thrown, and there may not be any way to get back to a =
sensible state in a way that cannot throw. If there is some field type that=
is no-except default constructible, you can use that, and there is nothing=
wrong with that (this is precisely what Boost does, though voting in the c=
ommittee unfortunately decided this is not a good idea, and I think that is=
a huge mistake). Similarly, if there is no no-except default constructible=
field and you have a field with a move-constructor that can throw, you can=
just say that's a violation of the requirements of assignment, leaving=
the rest of the type perfectly usable. This is fine first because not all =
uses require that operation and also because there are a couple of simple w=
ays to get around this: A) the user adds some monostate field that is noexc=
ept default-constructible -or- (if you accept my suggestions regarding opti=
onal) B) just use an optional<variant<T...>> in that specific c=
ase. Both of these solutions avoid having to make any changes to existing f=
ield types and produce a solution that is assignable, meets the strong guar=
antee, and has no intrinsic invalid state. Alternatively, you can also just=
deal with the offending non-noexcept-move-constructible field via indirect=
ion (I.E. make the field it a unique_ptr instead, which doesn't even re=
quire it using dynamic memory allocation, though even if you did use dynami=
c memory allocation, understand that frequently the reason why a move-const=
ructor is not noexcept to begin with is because it needs to do dynamic memo=
ry allocation, so the rationale of avoiding dynamic memory allocation is qu=
estionable).</div><div><br></div><div>Regarding the strong exception guaran=
tee, as people have said, the strong guarantee is easier to deal with than =
the basic guarantee, and I agree. Understand though that if you need that g=
uarantee you can get it by building on top of a simpler variant that only h=
as the basic guarantee -- for instance you can implement a double-storage s=
olution in something that encapsulates the more basic variant, and users of=
the more basic variant do not need to pay for it. Also realize that even w=
hen handling an exception that is thrown, you do not always have to get bac=
k to the original state. People get by with functions that offer only the b=
asic guarantee and they do not always do so by making backups. Frequently t=
his is the case when you handle the exception at some higher level in the s=
tack.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134e2120c48a20520c18916--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 27 Sep 2015 14:54:20 -0700
Raw View
--089e015366088fa5d90520c19f86
Content-Type: text/plain; charset=UTF-8
On Sat, Sep 26, 2015 at 3:02 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
>
> Default constructing the first type is an absurd idea:
>
> struct L { ... };
> struct R { ... };
>
> using V = std::variant<L, R>;
>
> V v1;
> V v2(emplace<L>);
> V v3(emplace<R>);
>
> Now v1 == v2 but v1 != v3. That's ridiculous.
>
Why is that at all ridiculous? Most decisions regarding what the
default-constructed state of a type is are somewhat arbitrary and
usage-specific. That doesn't matter. If you make a square matrix type, for
example, should you initialize all values to 0? Should you initialize the
matrix to an identity matrix? It ultimately doesn't matter which you decide
on and it is not ridiculous to choose one over the other. You just have to
document it. If people don't want to use that default then they simply do
not default-construct their object. What is much more ridiculous, in my
opinion, is introducing an entirely new "invalid" state just because you
don't want to decide on a default (or simply make it not
default-constructible). By introducing some invalid state, you're just
complicated the contracts of functions that need to deal with instances of
the 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e015366088fa5d90520c19f86
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 S=
at, Sep 26, 2015 at 3:02 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Default constructin=
g the first type is an absurd idea:</div><div><br></div><div>=C2=A0 =C2=A0s=
truct L { ... };</div><div>=C2=A0 =C2=A0struct R { ... };</div><div><br></d=
iv><div>=C2=A0 =C2=A0using V =3D std::variant<L, R>;</div><div><br></=
div><div>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V v2(emplace<L>);<=
/div><div>=C2=A0 =C2=A0V v3(emplace<R>);</div><div><br></div><div>Now=
v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 That's ridiculous.</div></div></div=
></div></blockquote><div><br></div><div>Why is that at all ridiculous? Most=
decisions regarding what the default-constructed state of a type is are so=
mewhat arbitrary and usage-specific. That doesn't matter. If you make a=
square matrix type, for example, should you initialize all values to 0? Sh=
ould you initialize the matrix to an identity matrix? It ultimately doesn&#=
39;t matter which you decide on and it is not ridiculous to choose one over=
the other. You just have to document it. If people don't want to use t=
hat default then they simply do not default-construct their object. What is=
much more ridiculous, in my opinion, is introducing an entirely new "=
invalid" state just because you don't want to decide on a default =
(or simply make it not default-constructible). By introducing some invalid =
state, you're just complicated the contracts of functions that need to =
deal with instances of the type.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e015366088fa5d90520c19f86--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 27 Sep 2015 15:01:57 -0700
Raw View
--047d7b33956dc905350520c1bab3
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 2:48 PM, Matt Calabrese <calabrese@google.com>
wrote:
> A) the user adds some monostate field that is noexcept
> default-constructible -or- (if you accept my suggestions regarding
> optional) B) just use an optional<variant<T...>> in that specific case.
> Both of these solutions avoid having to make any changes to existing field
> types and produce a solution that is assignable, meets the strong
> guarantee, and has no intrinsic invalid state.
>
Sorry, meant to say "basic" guarantee.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b33956dc905350520c1bab3
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 S=
un, Sep 27, 2015 at 2:48 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.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"><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><div>A) the user adds some=
monostate field that is noexcept default-constructible -or- (if you accept=
my suggestions regarding optional) B) just use an optional<variant<T=
....>> in that specific case. Both of these solutions avoid having to =
make any changes to existing field types and produce a solution that is ass=
ignable, meets the strong guarantee, and has no intrinsic invalid state. </=
div></div></div></div></blockquote><div><br></div><div>Sorry, meant to say =
"basic" guarantee.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b33956dc905350520c1bab3--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Mon, 28 Sep 2015 00:25:10 +0200
Raw View
--001a11c2b90cd0b1d00520c20ded
Content-Type: text/plain; charset=UTF-8
What is wrong with the following reasoning:
Suppose, I have an integer-like type that has an invariant that it is
always divisible by 2.
In the event that someone attempts to assign it an odd number, the object
sets itself to a random even number.
Thus, its invariant is maintained.
Producing garbage to maintain an invariant is much worse than violating an
invariant. It leads to the worst kind of bugs where the garbage travels
long distances through the system and is caught late, or worse not caught
at all and leads to externally-visible system misbehaviours.
For example (using V from earlier):
void f(V v) {
if (v.isa<L>) {
launch_missiles_leftward();
} else if (v.isa<R>) {
launch_missles_rightward();
} else {
emergency_shutdown();
}
}
V v;
{
R v;
...
v = R(); // oops, set inner v, outer v intended.
}
f(v); // oops, attacked wrong country.
Using an at-most-one variant the system would safely shutdown as a
consequence of this bug.
Using an exactly-one variant that default-constructs to the first type, the
missiles would be launched in the wrong direction.
On Sun, Sep 27, 2015 at 11:54 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Sat, Sep 26, 2015 at 3:02 PM, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>>
>> Default constructing the first type is an absurd idea:
>>
>> struct L { ... };
>> struct R { ... };
>>
>> using V = std::variant<L, R>;
>>
>> V v1;
>> V v2(emplace<L>);
>> V v3(emplace<R>);
>>
>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>
>
> Why is that at all ridiculous? Most decisions regarding what the
> default-constructed state of a type is are somewhat arbitrary and
> usage-specific. That doesn't matter. If you make a square matrix type, for
> example, should you initialize all values to 0? Should you initialize the
> matrix to an identity matrix? It ultimately doesn't matter which you decide
> on and it is not ridiculous to choose one over the other. You just have to
> document it. If people don't want to use that default then they simply do
> not default-construct their object. What is much more ridiculous, in my
> opinion, is introducing an entirely new "invalid" state just because you
> don't want to decide on a default (or simply make it not
> default-constructible). By introducing some invalid state, you're just
> complicated the contracts of functions that need to deal with instances of
> the 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2b90cd0b1d00520c20ded
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">What is wrong with the following reasoning:<div><br></div>=
<div>Suppose, I have an integer-like type that has an invariant that it is =
always divisible by 2.</div><div><br></div><div>In the event that someone a=
ttempts to assign it an odd number, the object sets itself to a random even=
number.</div><div><br></div><div>Thus, its invariant is maintained.</div><=
div><br></div><div>Producing garbage to maintain an invariant is much worse=
than violating an invariant.=C2=A0 It leads to the worst kind of bugs wher=
e the garbage travels long distances through the system and is caught late,=
or worse not caught at all and leads to externally-visible system misbehav=
iours.</div><div><br></div><div>For example (using V from earlier):</div><d=
iv><br></div><div>=C2=A0 =C2=A0void f(V v) {</div><div>=C2=A0 =C2=A0 =C2=A0=
if (v.isa<L>) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_missiles_=
leftward();</div><div>=C2=A0 =C2=A0 =C2=A0} else if (v.isa<R>) {</div=
><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_missles_rightward();</div><div>=C2=
=A0 =C2=A0 =C2=A0} else {<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0emergenc=
y_shutdown();</div><div>=C2=A0 =C2=A0 =C2=A0}</div><div>=C2=A0 =C2=A0}</div=
><div><br></div><div>V v;</div><div>{</div><div>=C2=A0 =C2=A0R v;</div><div=
>=C2=A0 =C2=A0...</div><div>=C2=A0 =C2=A0v =3D R(); // oops, set inner v, o=
uter v intended.</div><div>}</div><div>f(v); // oops, attacked wrong countr=
y.</div><div><br></div><div>Using an at-most-one variant the system would s=
afely shutdown as a consequence of this bug.</div><div><br></div><div>Using=
an exactly-one variant that default-constructs to the first type, the miss=
iles would be launched in the wrong direction.</div><div><br></div><div cla=
ss=3D"gmail_extra"><div class=3D"gmail_quote">On Sun, Sep 27, 2015 at 11:54=
PM, 'Matt Calabrese' via ISO C++ Standard - Future Proposals <span=
dir=3D"ltr"><<a href=3D"mailto:std-proposals@isocpp.org" target=3D"_bla=
nk">std-proposals@isocpp.org</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"><div class=3D"gmail_extra"><div class=3D"gmail_q=
uote">On Sat, Sep 26, 2015 at 3:02 PM, Andrew Tomazos <span dir=3D"ltr"><=
;<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos=
@gmail.com</a>></span> wrote:<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 class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Default con=
structing the first type is an absurd idea:</div><span class=3D""><div><br>=
</div><div>=C2=A0 =C2=A0struct L { ... };</div><div>=C2=A0 =C2=A0struct R {=
... };</div><div><br></div><div>=C2=A0 =C2=A0using V =3D std::variant<L=
, R>;</div><div><br></div><div>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=
=A0V v2(emplace<L>);</div><div>=C2=A0 =C2=A0V v3(emplace<R>);</=
div><div><br></div></span><span class=3D""><div>Now v1 =3D=3D v2 but v1 !=
=3D v3.=C2=A0 That's ridiculous.</div></span></div></div></div></blockq=
uote><div><br></div><div>Why is that at all ridiculous? Most decisions rega=
rding what the default-constructed state of a type is are somewhat arbitrar=
y and usage-specific. That doesn't matter. If you make a square matrix =
type, for example, should you initialize all values to 0? Should you initia=
lize the matrix to an identity matrix? It ultimately doesn't matter whi=
ch you decide on and it is not ridiculous to choose one over the other. You=
just have to document it. If people don't want to use that default the=
n they simply do not default-construct their object. What is much more ridi=
culous, in my opinion, is introducing an entirely new "invalid" s=
tate just because you don't want to decide on a default (or simply make=
it not default-constructible). By introducing some invalid state, you'=
re just complicated the contracts of functions that need to deal with insta=
nces of the type.</div></div></div></div><div class=3D"HOEnZb"><div class=
=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2b90cd0b1d00520c20ded--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 27 Sep 2015 16:55:59 -0700
Raw View
--047d7b33956d8d81280520c35227
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> What is wrong with the following reasoning:
>
> Suppose, I have an integer-like type that has an invariant that it is
> always divisible by 2.
>
> In the event that someone attempts to assign it an odd number, the object
> sets itself to a random even number.
>
> Thus, its invariant is maintained.
>
What? Why would you do this? The user violated a contract (namely that they
shouldn't assign an odd object in this case). You do not get around this by
doing something random, you instead have the implication of undefined
behavior.
On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> Producing garbage to maintain an invariant is much worse than violating an
> invariant.
>
No one has suggested this, nor does what you're saying have anything to do
with default construction as far as I can tell.
On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> It leads to the worst kind of bugs where the garbage travels long
> distances through the system and is caught late, or worse not caught at all
> and leads to externally-visible system misbehaviours.
>
> For example (using V from earlier):
>
> void f(V v) {
> if (v.isa<L>) {
> launch_missiles_leftward();
> } else if (v.isa<R>) {
> launch_missles_rightward();
> } else {
> emergency_shutdown();
> }
> }
>
> V v;
> {
> R v;
> ...
> v = R(); // oops, set inner v, outer v intended.
> }
> f(v); // oops, attacked wrong country.
>
> Using an at-most-one variant the system would safely shutdown as a
> consequence of this bug.
>
> Using an exactly-one variant that default-constructs to the first type,
> the missiles would be launched in the wrong direction.
>
That sounds much more like an argument against default construction as
opposed to an argument for an invalid state. The same can be said about any
default-constructible type that is not a mono-state. I will note that I'm
not even opposed to types that aren't default-constructible. I am only
against introducing an invalid state simply because one cannot decide on or
is unable to provide an appropriate default.
On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> What is wrong with the following reasoning:
>
> Suppose, I have an integer-like type that has an invariant that it is
> always divisible by 2.
>
> In the event that someone attempts to assign it an odd number, the object
> sets itself to a random even number.
>
> Thus, its invariant is maintained.
>
> Producing garbage to maintain an invariant is much worse than violating an
> invariant. It leads to the worst kind of bugs where the garbage travels
> long distances through the system and is caught late, or worse not caught
> at all and leads to externally-visible system misbehaviours.
>
> For example (using V from earlier):
>
> void f(V v) {
> if (v.isa<L>) {
> launch_missiles_leftward();
> } else if (v.isa<R>) {
> launch_missles_rightward();
> } else {
> emergency_shutdown();
> }
> }
>
> V v;
> {
> R v;
> ...
> v = R(); // oops, set inner v, outer v intended.
> }
> f(v); // oops, attacked wrong country.
>
> Using an at-most-one variant the system would safely shutdown as a
> consequence of this bug.
>
> Using an exactly-one variant that default-constructs to the first type,
> the missiles would be launched in the wrong direction.
>
> On Sun, Sep 27, 2015 at 11:54 PM, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> On Sat, Sep 26, 2015 at 3:02 PM, Andrew Tomazos <andrewtomazos@gmail.com>
>> wrote:
>>>
>>> Default constructing the first type is an absurd idea:
>>>
>>> struct L { ... };
>>> struct R { ... };
>>>
>>> using V = std::variant<L, R>;
>>>
>>> V v1;
>>> V v2(emplace<L>);
>>> V v3(emplace<R>);
>>>
>>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>>
>>
>> Why is that at all ridiculous? Most decisions regarding what the
>> default-constructed state of a type is are somewhat arbitrary and
>> usage-specific. That doesn't matter. If you make a square matrix type, for
>> example, should you initialize all values to 0? Should you initialize the
>> matrix to an identity matrix? It ultimately doesn't matter which you decide
>> on and it is not ridiculous to choose one over the other. You just have to
>> document it. If people don't want to use that default then they simply do
>> not default-construct their object. What is much more ridiculous, in my
>> opinion, is introducing an entirely new "invalid" state just because you
>> don't want to decide on a default (or simply make it not
>> default-constructible). By introducing some invalid state, you're just
>> complicated the contracts of functions that need to deal with instances of
>> the 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.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b33956d8d81280520c35227
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 S=
un, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,20=
4);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr">What is wrong=
with the following reasoning:<div><br></div><div>Suppose, I have an intege=
r-like type that has an invariant that it is always divisible by 2.</div><d=
iv><br></div><div>In the event that someone attempts to assign it an odd nu=
mber, the object sets itself to a random even number.</div><div><br></div><=
div>Thus, its invariant is maintained.</div></div></blockquote><div><br></d=
iv><div>What? Why would you do this? The user violated a contract (namely t=
hat they shouldn't assign an odd object in this case). You do not get a=
round this by doing something random, you instead have the implication of u=
ndefined behavior.</div><div><br></div><div>On Sun, Sep 27, 2015 at 3:25 PM=
, Andrew Tomazos=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos=
@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a>></span>=C2=A0w=
rote:</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-st=
yle:solid;padding-left:1ex"><div dir=3D"ltr"><div>Producing garbage to main=
tain an invariant is much worse than violating an invariant.=C2=A0</div></d=
iv></blockquote><div><br></div><div>No one has suggested this, nor does wha=
t you're saying have anything to do with default construction as far as=
I can tell.</div><div><br></div><div>On Sun, Sep 27, 2015 at 3:25 PM, Andr=
ew Tomazos=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail=
..com" target=3D"_blank">andrewtomazos@gmail.com</a>></span>=C2=A0wrote:=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-le=
ft-style:solid;padding-left:1ex"><div dir=3D"ltr"><div> It leads to the wor=
st kind of bugs where the garbage travels long distances through the system=
and is caught late, or worse not caught at all and leads to externally-vis=
ible system misbehaviours.</div></div></blockquote><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div di=
r=3D"ltr"><div></div><div><br></div><div>For example (using V from earlier)=
:</div><div><br></div><div>=C2=A0 =C2=A0void f(V v) {</div><div>=C2=A0 =C2=
=A0 =C2=A0if (v.isa<L>) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch=
_missiles_leftward();</div><div>=C2=A0 =C2=A0 =C2=A0} else if (v.isa<R&g=
t;) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_missles_rightward();</div=
><div>=C2=A0 =C2=A0 =C2=A0} else {<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0emergency_shutdown();</div><div>=C2=A0 =C2=A0 =C2=A0}</div><div>=C2=A0 =
=C2=A0}</div><div><br></div><div>V v;</div><div>{</div><div>=C2=A0 =C2=A0R =
v;</div><div>=C2=A0 =C2=A0...</div><div>=C2=A0 =C2=A0v =3D R(); // oops, se=
t inner v, outer v intended.</div><div>}</div><div>f(v); // oops, attacked =
wrong country.</div><div><br></div><div>Using an at-most-one variant the sy=
stem would safely shutdown as a consequence of this bug.</div><div><br></di=
v><div>Using an exactly-one variant that default-constructs to the first ty=
pe, the missiles would be launched in the wrong direction.</div></div></blo=
ckquote><div><br></div><div>That sounds much more like an argument against =
default construction as opposed to an argument for an invalid state. The sa=
me can be said about any default-constructible type that is not a mono-stat=
e. I will note that I'm not even opposed to types that aren't defau=
lt-constructible. I am only against introducing an invalid state simply bec=
ause one cannot decide on or is unable to provide an appropriate default.</=
div></div></div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_qu=
ote">On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <span dir=3D"ltr"><=
<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@=
gmail.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">What is wrong with the following reasoning:<div><br></div><div>Sup=
pose, I have an integer-like type that has an invariant that it is always d=
ivisible by 2.</div><div><br></div><div>In the event that someone attempts =
to assign it an odd number, the object sets itself to a random even number.=
</div><div><br></div><div>Thus, its invariant is maintained.</div><div><br>=
</div><div>Producing garbage to maintain an invariant is much worse than vi=
olating an invariant.=C2=A0 It leads to the worst kind of bugs where the ga=
rbage travels long distances through the system and is caught late, or wors=
e not caught at all and leads to externally-visible system misbehaviours.</=
div><div><br></div><div>For example (using V from earlier):</div><div><br><=
/div><div>=C2=A0 =C2=A0void f(V v) {</div><div>=C2=A0 =C2=A0 =C2=A0if (v.is=
a<L>) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_missiles_leftward=
();</div><div>=C2=A0 =C2=A0 =C2=A0} else if (v.isa<R>) {</div><div>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_missles_rightward();</div><div>=C2=A0 =C2=
=A0 =C2=A0} else {<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0emergency_shutd=
own();</div><div>=C2=A0 =C2=A0 =C2=A0}</div><div>=C2=A0 =C2=A0}</div><div><=
br></div><div>V v;</div><div>{</div><div>=C2=A0 =C2=A0R v;</div><div>=C2=A0=
=C2=A0...</div><div>=C2=A0 =C2=A0v =3D R(); // oops, set inner v, outer v =
intended.</div><div>}</div><div>f(v); // oops, attacked wrong country.</div=
><div><br></div><div>Using an at-most-one variant the system would safely s=
hutdown as a consequence of this bug.</div><div><br></div><div>Using an exa=
ctly-one variant that default-constructs to the first type, the missiles wo=
uld be launched in the wrong direction.</div><div><br></div><div class=3D"g=
mail_extra"><div class=3D"gmail_quote"><div><div class=3D"h5">On Sun, Sep 2=
7, 2015 at 11:54 PM, 'Matt Calabrese' via ISO C++ Standard - Future=
Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@isocpp.org=
" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<br></div=
></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div><div class=3D"h5"><div dir=3D"lt=
r"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On Sat, Sep 26, 20=
15 at 3:02 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andre=
wtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a>></span=
> wrote:<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 class=3D"gmail=
_extra"><div class=3D"gmail_quote"><div>Default constructing the first type=
is an absurd idea:</div><span><div><br></div><div>=C2=A0 =C2=A0struct L { =
.... };</div><div>=C2=A0 =C2=A0struct R { ... };</div><div><br></div><div>=
=C2=A0 =C2=A0using V =3D std::variant<L, R>;</div><div><br></div><div=
>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V v2(emplace<L>);</div><di=
v>=C2=A0 =C2=A0V v3(emplace<R>);</div><div><br></div></span><span><di=
v>Now v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 That's ridiculous.</div></span=
></div></div></div></blockquote><div><br></div><div>Why is that at all ridi=
culous? Most decisions regarding what the default-constructed state of a ty=
pe is are somewhat arbitrary and usage-specific. That doesn't matter. I=
f you make a square matrix type, for example, should you initialize all val=
ues to 0? Should you initialize the matrix to an identity matrix? It ultima=
tely doesn't matter which you decide on and it is not ridiculous to cho=
ose one over the other. You just have to document it. If people don't w=
ant to use that default then they simply do not default-construct their obj=
ect. What is much more ridiculous, in my opinion, is introducing an entirel=
y new "invalid" state just because you don't want to decide o=
n a default (or simply make it not default-constructible). By introducing s=
ome invalid state, you're just complicated the contracts of functions t=
hat need to deal with instances of the type.</div></div></div></div></div><=
/div><div><div>
<p></p>
-- <br><span class=3D"">
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</span></div></div></blockquote></div><br></div></div><div class=3D"HOEnZb"=
><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--047d7b33956d8d81280520c35227--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Mon, 28 Sep 2015 02:29:48 +0200
Raw View
--047d7b624e9a82c46f0520c3cbbd
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 1:55 AM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> What is wrong with the following reasoning:
>>
>> Suppose, I have an integer-like type that has an invariant that it is
>> always divisible by 2.
>>
>> In the event that someone attempts to assign it an odd number, the object
>> sets itself to a random even number.
>>
>> Thus, its invariant is maintained.
>>
>
> What? Why would you do this? The user violated a contract (namely that
> they shouldn't assign an odd object in this case). You do not get around
> this by doing something random, you instead have the implication of
> undefined behavior.
>
It is analogous to default-constructing to a value of the first type, just
to maintain the invariant that an exactly-one variant has an invariant that
it always holds a value of one of the types. The "garbage" is the
"made-up" value of the first type that results from default construction.
On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> Producing garbage to maintain an invariant is much worse than violating
>> an invariant.
>>
>
> No one has suggested this, nor does what you're saying have anything to do
> with default construction as far as I can tell.
>
> On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> It leads to the worst kind of bugs where the garbage travels long
>> distances through the system and is caught late, or worse not caught at all
>> and leads to externally-visible system misbehaviours.
>>
>
>> For example (using V from earlier):
>>
>> void f(V v) {
>> if (v.isa<L>) {
>> launch_missiles_leftward();
>> } else if (v.isa<R>) {
>> launch_missles_rightward();
>> } else {
>> emergency_shutdown();
>> }
>> }
>>
>> V v;
>> {
>> R v;
>> ...
>> v = R(); // oops, set inner v, outer v intended.
>> }
>> f(v); // oops, attacked wrong country.
>>
>> Using an at-most-one variant the system would safely shutdown as a
>> consequence of this bug.
>>
>> Using an exactly-one variant that default-constructs to the first type,
>> the missiles would be launched in the wrong direction.
>>
>
> That sounds much more like an argument against default construction as
> opposed to an argument for an invalid state. The same can be said about any
> default-constructible type that is not a mono-state. I will note that I'm
> not even opposed to types that aren't default-constructible. I am only
> against introducing an invalid state simply because one cannot decide on or
> is unable to provide an appropriate default.
>
As I said before, my claim is that if a variant can default-construct, it
should have an empty value (aka invalid state).
An at-most-one variant should default construct to empty.
An exactly-one variant should not be default-constructable.
The example above demonstrates why both of these are true.
On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> What is wrong with the following reasoning:
>>
>> Suppose, I have an integer-like type that has an invariant that it is
>> always divisible by 2.
>>
>> In the event that someone attempts to assign it an odd number, the object
>> sets itself to a random even number.
>>
>> Thus, its invariant is maintained.
>>
>> Producing garbage to maintain an invariant is much worse than violating
>> an invariant. It leads to the worst kind of bugs where the garbage travels
>> long distances through the system and is caught late, or worse not caught
>> at all and leads to externally-visible system misbehaviours.
>>
>> For example (using V from earlier):
>>
>> void f(V v) {
>> if (v.isa<L>) {
>> launch_missiles_leftward();
>> } else if (v.isa<R>) {
>> launch_missles_rightward();
>> } else {
>> emergency_shutdown();
>> }
>> }
>>
>> V v;
>> {
>> R v;
>> ...
>> v = R(); // oops, set inner v, outer v intended.
>> }
>> f(v); // oops, attacked wrong country.
>>
>> Using an at-most-one variant the system would safely shutdown as a
>> consequence of this bug.
>>
>> Using an exactly-one variant that default-constructs to the first type,
>> the missiles would be launched in the wrong direction.
>>
>> On Sun, Sep 27, 2015 at 11:54 PM, 'Matt Calabrese' via ISO C++ Standard -
>> Future Proposals <std-proposals@isocpp.org> wrote:
>>
>>> On Sat, Sep 26, 2015 at 3:02 PM, Andrew Tomazos <andrewtomazos@gmail.com
>>> > wrote:
>>>>
>>>> Default constructing the first type is an absurd idea:
>>>>
>>>> struct L { ... };
>>>> struct R { ... };
>>>>
>>>> using V = std::variant<L, R>;
>>>>
>>>> V v1;
>>>> V v2(emplace<L>);
>>>> V v3(emplace<R>);
>>>>
>>>> Now v1 == v2 but v1 != v3. That's ridiculous.
>>>>
>>>
>>> Why is that at all ridiculous? Most decisions regarding what the
>>> default-constructed state of a type is are somewhat arbitrary and
>>> usage-specific. That doesn't matter. If you make a square matrix type, for
>>> example, should you initialize all values to 0? Should you initialize the
>>> matrix to an identity matrix? It ultimately doesn't matter which you decide
>>> on and it is not ridiculous to choose one over the other. You just have to
>>> document it. If people don't want to use that default then they simply do
>>> not default-construct their object. What is much more ridiculous, in my
>>> opinion, is introducing an entirely new "invalid" state just because you
>>> don't want to decide on a default (or simply make it not
>>> default-constructible). By introducing some invalid state, you're just
>>> complicated the contracts of functions that need to deal with instances of
>>> the 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.
>>> Visit this group at
>>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>>
>>
>> --
>>
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b624e9a82c46f0520c3cbbd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 1:55 AM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Sun, Sep 27, 2015=
at 3:25 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andrewt=
omazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a>></span> =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr">What is wrong with the followin=
g reasoning:<div><br></div><div>Suppose, I have an integer-like type that h=
as an invariant that it is always divisible by 2.</div><div><br></div><div>=
In the event that someone attempts to assign it an odd number, the object s=
ets itself to a random even number.</div><div><br></div><div>Thus, its inva=
riant is maintained.</div></div></blockquote><div><br></div></span><div>Wha=
t? Why would you do this? The user violated a contract (namely that they sh=
ouldn't assign an odd object in this case). You do not get around this =
by doing something random, you instead have the implication of undefined be=
havior.</div></div></div></div></blockquote><div>=C2=A0</div><div>It is ana=
logous to default-constructing to a value of the first type, just to mainta=
in the invariant that an exactly-one variant has an invariant that it alway=
s holds a value of one of the types.=C2=A0 The "garbage" is the &=
quot;made-up" value of the first type that results from default constr=
uction.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D""><di=
v></div><div>On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos=C2=A0<span dir=
=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">a=
ndrewtomazos@gmail.com</a>></span>=C2=A0wrote:</div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;borde=
r-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><di=
v dir=3D"ltr"><div>Producing garbage to maintain an invariant is much worse=
than violating an invariant.=C2=A0</div></div></blockquote><div><br></div>=
</span><div>No one has suggested this, nor does what you're saying have=
anything to do with default construction as far as I can tell.</div><span =
class=3D""><div><br></div><div>On Sun, Sep 27, 2015 at 3:25 PM, Andrew Toma=
zos=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" t=
arget=3D"_blank">andrewtomazos@gmail.com</a>></span>=C2=A0wrote:=C2=A0<b=
r></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"><div dir=3D"ltr"><div> It leads to the worst kind =
of bugs where the garbage travels long distances through the system and is =
caught late, or worse not caught at all and leads to externally-visible sys=
tem misbehaviours.</div></div></blockquote><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></div><div><br></div><div>For example (using V from earlier):</div><=
div><br></div><div>=C2=A0 =C2=A0void f(V v) {</div><div>=C2=A0 =C2=A0 =C2=
=A0if (v.isa<L>) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_missil=
es_leftward();</div><div>=C2=A0 =C2=A0 =C2=A0} else if (v.isa<R>) {</=
div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_missles_rightward();</div><div>=
=C2=A0 =C2=A0 =C2=A0} else {<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0emerg=
ency_shutdown();</div><div>=C2=A0 =C2=A0 =C2=A0}</div><div>=C2=A0 =C2=A0}</=
div><div><br></div><div>V v;</div><div>{</div><div>=C2=A0 =C2=A0R v;</div><=
div>=C2=A0 =C2=A0...</div><div>=C2=A0 =C2=A0v =3D R(); // oops, set inner v=
, outer v intended.</div><div>}</div><div>f(v); // oops, attacked wrong cou=
ntry.</div><div><br></div><div>Using an at-most-one variant the system woul=
d safely shutdown as a consequence of this bug.</div><div><br></div><div>Us=
ing an exactly-one variant that default-constructs to the first type, the m=
issiles would be launched in the wrong direction.</div></div></blockquote><=
div><br></div></span><div>That sounds much more like an argument against de=
fault construction as opposed to an argument for an invalid state. The same=
can be said about any default-constructible type that is not a mono-state.=
I will note that I'm not even opposed to types that aren't default=
-constructible. I am only against introducing an invalid state simply becau=
se one cannot decide on or is unable to provide an appropriate default.</di=
v></div></div></div></blockquote><div><br></div><div>As I said before, my c=
laim is that if a variant can default-construct, it should have an empty va=
lue (aka invalid state).</div><div><br></div><div>An at-most-one variant sh=
ould default construct to empty.</div><div><br></div><div>An exactly-one va=
riant should not be default-constructable.</div><div><br></div><div>The exa=
mple above demonstrates why both of these are true.</div><div><br></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5"><div cl=
ass=3D"gmail_extra"><div class=3D"gmail_quote">On Sun, Sep 27, 2015 at 3:25=
PM, Andrew Tomazos <span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@g=
mail.com" target=3D"_blank">andrewtomazos@gmail.com</a>></span> wrote:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">What is wrong with the fo=
llowing reasoning:<div><br></div><div>Suppose, I have an integer-like type =
that has an invariant that it is always divisible by 2.</div><div><br></div=
><div>In the event that someone attempts to assign it an odd number, the ob=
ject sets itself to a random even number.</div><div><br></div><div>Thus, it=
s invariant is maintained.</div><div><br></div><div>Producing garbage to ma=
intain an invariant is much worse than violating an invariant.=C2=A0 It lea=
ds to the worst kind of bugs where the garbage travels long distances throu=
gh the system and is caught late, or worse not caught at all and leads to e=
xternally-visible system misbehaviours.</div><div><br></div><div>For exampl=
e (using V from earlier):</div><div><br></div><div>=C2=A0 =C2=A0void f(V v)=
{</div><div>=C2=A0 =C2=A0 =C2=A0if (v.isa<L>) {</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0launch_missiles_leftward();</div><div>=C2=A0 =C2=A0 =C2=A0=
} else if (v.isa<R>) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0launch_mi=
ssles_rightward();</div><div>=C2=A0 =C2=A0 =C2=A0} else {<br></div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0emergency_shutdown();</div><div>=C2=A0 =C2=A0 =C2=
=A0}</div><div>=C2=A0 =C2=A0}</div><div><br></div><div>V v;</div><div>{</di=
v><div>=C2=A0 =C2=A0R v;</div><div>=C2=A0 =C2=A0...</div><div>=C2=A0 =C2=A0=
v =3D R(); // oops, set inner v, outer v intended.</div><div>}</div><div>f(=
v); // oops, attacked wrong country.</div><div><br></div><div>Using an at-m=
ost-one variant the system would safely shutdown as a consequence of this b=
ug.</div><div><br></div><div>Using an exactly-one variant that default-cons=
tructs to the first type, the missiles would be launched in the wrong direc=
tion.</div><div><br></div><div class=3D"gmail_extra"><div class=3D"gmail_qu=
ote"><div><div>On Sun, Sep 27, 2015 at 11:54 PM, 'Matt Calabrese' v=
ia ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mai=
lto:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a=
>></span> wrote:<br></div></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><di=
v><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On=
Sat, Sep 26, 2015 at 3:02 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Default constructin=
g the first type is an absurd idea:</div><span><div><br></div><div>=C2=A0 =
=C2=A0struct L { ... };</div><div>=C2=A0 =C2=A0struct R { ... };</div><div>=
<br></div><div>=C2=A0 =C2=A0using V =3D std::variant<L, R>;</div><div=
><br></div><div>=C2=A0 =C2=A0V v1;</div><div>=C2=A0 =C2=A0V v2(emplace<L=
>);</div><div>=C2=A0 =C2=A0V v3(emplace<R>);</div><div><br></div><=
/span><span><div>Now v1 =3D=3D v2 but v1 !=3D v3.=C2=A0 That's ridiculo=
us.</div></span></div></div></div></blockquote><div><br></div><div>Why is t=
hat at all ridiculous? Most decisions regarding what the default-constructe=
d state of a type is are somewhat arbitrary and usage-specific. That doesn&=
#39;t matter. If you make a square matrix type, for example, should you ini=
tialize all values to 0? Should you initialize the matrix to an identity ma=
trix? It ultimately doesn't matter which you decide on and it is not ri=
diculous to choose one over the other. You just have to document it. If peo=
ple don't want to use that default then they simply do not default-cons=
truct their object. What is much more ridiculous, in my opinion, is introdu=
cing an entirely new "invalid" state just because you don't w=
ant to decide on a default (or simply make it not default-constructible). B=
y introducing some invalid state, you're just complicated the contracts=
of functions that need to deal with instances of the type.</div></div></di=
v></div></div></div><div><div>
<p></p>
-- <br><span>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</span></div></div></blockquote></div><br></div></div><div><div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b624e9a82c46f0520c3cbbd--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 27 Sep 2015 17:51:50 -0700
Raw View
--089e013d0a4c53168f0520c41a75
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 5:29 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
>
> It is analogous to default-constructing to a value of the first type, just
> to maintain the invariant that an exactly-one variant has an invariant that
> it always holds a value of one of the types. The "garbage" is the
> "made-up" value of the first type that results from default construction.
>
I do not see how this is the conclusion you'd come to. A specific default
is frequently somewhat arbitrary and dependent on a specific usage, not
necessarily intrinsic to the type. The matrix example (all 0, or identity,
or something else) is a good example of that, but it's true for plenty of
types. If I have a type representing a playing card, do I have a default
constructor that makes it ace of spades? Two of clubs? Does it not have a
default constructor at all? It ultimately is subjective and doesn't matter.
If the default doesn't make sense for a user, then they don't use a
default-constructed object (or they default-construct and initialize
later). That a default doesn't apply to every single situation does not
mean that it is "garbage" or that you need to weaken the invariants of the
type. All it means is either that a user wouldn't use that default in the
places that it doesn't make sense, or the developer of the type would just
choose to not give the type a default constructor. Why is weakening the
invariants of the type and giving it an *actual* garbage value (by garbage
I mean something for which nearly all functions have a precondition that
disallows it) somehow better? All that does is complicate contracts
involved.
On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
>> wrote:
>>
> As I said before, my claim is that if a variant can default-construct, it
> should have an empty value (aka invalid state).
>
> An at-most-one variant should default construct to empty.
>
> An exactly-one variant should not be default-constructable.
>
> The example above demonstrates why both of these are true.
>
Again, I don't see how you are coming to any of these conclusions from your
example, but rather, you just seem to be asserting them. In either case
(default-to-invalid or default-to-something-else) you have a bug in
user-land code if the user inappropriately used the default... and? How is
this different from a programmer misusing any other function? I would
understand if your conclusion was that no default constructor should exist
at all, though that same logic can be used for any type that is not a
monostate and not just a variant. Weakening the invariants of the type to
introduce "invalid" just makes things worse because now all or most
standard and user-land contracts are necessarily more complicated. This
because you don't want to choose a specific default value? That's a pretty
drastic penalty. If the default doesn't make sense for your use, then just
don't default construct your object, or don't define the default
constructor.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e013d0a4c53168f0520c41a75
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 S=
un, Sep 27, 2015 at 5:29 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><div>It is analogous to =
default-constructing to a value of the first type, just to maintain the inv=
ariant that an exactly-one variant has an invariant that it always holds a =
value of one of the types.=C2=A0 The "garbage" is the "made-=
up" value of the first type that results from default construction.</d=
iv></div></div></div></blockquote><div><br></div><div>I do not see how this=
is the conclusion you'd come to. A specific default is frequently some=
what arbitrary and dependent on a specific usage, not necessarily intrinsic=
to the type. The matrix example (all 0, or identity, or something else) is=
a good example of that, but it's true for plenty of types. If I have a=
type representing a playing card, do I have a default constructor that mak=
es it ace of spades? Two of clubs? Does it not have a default constructor a=
t all? It ultimately is subjective and doesn't matter. If the default d=
oesn't make sense for a user, then they don't use a default-constru=
cted object (or they default-construct and initialize later). That a defaul=
t doesn't apply to every single situation does not mean that it is &quo=
t;garbage" or that you need to weaken the invariants of the type. All =
it means is either that a user wouldn't use that default in the places =
that it doesn't make sense, or the developer of the type would just cho=
ose to not give the type a default constructor. Why is weakening the invari=
ants of the type and giving it an <i>actual</i>=C2=A0garbage value (by garb=
age I mean something for which nearly all functions have a precondition tha=
t disallows it) somehow better? All that does is complicate contracts invol=
ved.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><d=
iv class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D""><block=
quote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div c=
lass=3D"gmail_quote"><span><div>On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tom=
azos=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" =
target=3D"_blank">andrewtomazos@gmail.com</a>></span>=C2=A0wrote:</div><=
/span></div></div></div></blockquote></span><div>As I said before, my claim=
is that if a variant can default-construct, it should have an empty value =
(aka invalid state).</div><div><br></div><div>An at-most-one variant should=
default construct to empty.</div><div><br></div><div>An exactly-one varian=
t should not be default-constructable.</div><div><br></div><div>The example=
above demonstrates why both of these are true.</div></div></div></div></bl=
ockquote><div><br></div><div>Again, I don't see how you are coming to a=
ny of these conclusions from your example, but rather, you just seem to be =
asserting them. In either case (default-to-invalid or default-to-something-=
else) you have a bug in user-land code if the user inappropriately used the=
default... and? How is this different from a programmer misusing any other=
function? I would understand if your conclusion was that no default constr=
uctor should exist at all, though that same logic can be used for any type =
that is not a monostate and not just a variant. Weakening the invariants of=
the type to introduce "invalid" just makes things worse because =
now all or most standard and user-land contracts are necessarily more compl=
icated. This because you don't want to choose a specific default value?=
That's a pretty drastic penalty. If the default doesn't make sense=
for your use, then just don't default construct your object, or don=
9;t define the default constructor.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e013d0a4c53168f0520c41a75--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 27 Sep 2015 18:19:56 -0700
Raw View
--001a11c2e462d01d0a0520c47e9e
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 5:51 PM, Matt Calabrese <calabrese@google.com>
wrote:
> If I have a type representing a playing card, do I have a default
> constructor that makes it ace of spades? Two of clubs? Does it not have a
> default constructor at all? It ultimately is subjective and doesn't matter.
> If the default doesn't make sense for a user, then they don't use a
> default-constructed object (or they default-construct and initialize later).
>
I wonder if this is the part that's not clear. The idea isn't that it's
some *unspecified* value (though that is the case after an exception is
thrown from a function with the basic exception guarantee). In the case of
a default constructor you have a fully specified and documented default
value. It's perfectly fine for someone to use and rely on that value. If
they don't want it, then they simply don't use it. Think about it like a
default comparator for an algorithm, such as std::sort. Maybe "less than"
isn't the notion you want as a default, but that doesn't mean it's somehow
illogical to have a default. All it means is that you'd be explicit in that
case.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2e462d01d0a0520c47e9e
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 S=
un, Sep 27, 2015 at 5:51 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.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"><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><div>If I have a type repr=
esenting a playing card, do I have a default constructor that makes it ace =
of spades? Two of clubs? Does it not have a default constructor at all? It =
ultimately is subjective and doesn't matter. If the default doesn't=
make sense for a user, then they don't use a default-constructed objec=
t (or they default-construct and initialize later).</div></div></div></div>=
</blockquote><div><br></div><div>I wonder if this is the part that's no=
t clear. The idea isn't that it's some <i>unspecified</i>=C2=A0valu=
e (though that is the case after an exception is thrown from a function wit=
h the basic exception guarantee). In the case of a default constructor you =
have a fully specified and documented default value. It's perfectly fin=
e for someone to use and rely on that value. If they don't want it, the=
n they simply don't use it. Think about it like a default comparator fo=
r an algorithm, such as std::sort. Maybe "less than" isn't th=
e notion you want as a default, but that doesn't mean it's somehow =
illogical to have a default. All it means is that you'd be explicit in =
that case.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2e462d01d0a0520c47e9e--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Mon, 28 Sep 2015 03:59:23 +0200
Raw View
--047d7b874e50ea0aab0520c50b9f
Content-Type: text/plain; charset=UTF-8
If a type is default constructible, the default value that results is
important and does matter.
If it is a surprising value, bugs will result. It is a common logic error
to implicitly default construct an object (for example data members, array
elements, etc) with the intention of assigning to them later, but not doing
so. When coming to read such an object the default value will be observed
instead of the intended value. If the default value is surprising, then it
will likely be treated as a correctly-set value, leading to an expensive
disaster. If it is unsurprising the fact that it is in default state is
more likely to be branched on.
(Sometimes this risk is worth it for performance reasons, but that does not
apply to the variant case, because the empty value is performant.
Potentially even more so than the default constructor of the first type.)
In the matrix case, dynamically-sized matrixes (if they default construct)
default construct to the empty matrix:
For real world examples:
boost::numeric::ublas::matrix m; // empty
libarmadillo::Mat m; // empty
Eigen::MatrixXd m; // empty
For a fixed-sized matrix, the default constructor generally does nothing
for performance reasons (leaves memory uninitialized). If anything this
argues for default constructing variant to empty (with -1 discriminator and
*unintialized* storage).
As for a PlayingCard type, it should either (1) not be
default-constructible; (2) default construct to a special empty value (suit
= -1); or (3) default construct uninitialized for performance (suppose you
have large arrays of them in some simulation). In no case should it
default construct specifically to Ace of Spades (except accidentally as a
result of 3).
Default constructing PlayingCard to Ace of Spades is exactly like default
constructing a variant to hold a value of the first type.
On Mon, Sep 28, 2015 at 2:51 AM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Sun, Sep 27, 2015 at 5:29 PM, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>>
>> It is analogous to default-constructing to a value of the first type,
>> just to maintain the invariant that an exactly-one variant has an invariant
>> that it always holds a value of one of the types. The "garbage" is the
>> "made-up" value of the first type that results from default construction.
>>
>
> I do not see how this is the conclusion you'd come to. A specific default
> is frequently somewhat arbitrary and dependent on a specific usage, not
> necessarily intrinsic to the type. The matrix example (all 0, or identity,
> or something else) is a good example of that, but it's true for plenty of
> types. If I have a type representing a playing card, do I have a default
> constructor that makes it ace of spades? Two of clubs? Does it not have a
> default constructor at all? It ultimately is subjective and doesn't matter.
> If the default doesn't make sense for a user, then they don't use a
> default-constructed object (or they default-construct and initialize
> later). That a default doesn't apply to every single situation does not
> mean that it is "garbage" or that you need to weaken the invariants of the
> type. All it means is either that a user wouldn't use that default in the
> places that it doesn't make sense, or the developer of the type would just
> choose to not give the type a default constructor. Why is weakening the
> invariants of the type and giving it an *actual* garbage value (by
> garbage I mean something for which nearly all functions have a precondition
> that disallows it) somehow better? All that does is complicate contracts
> involved.
>
> On Sun, Sep 27, 2015 at 3:25 PM, Andrew Tomazos <andrewtomazos@gmail.com>
>>> wrote:
>>>
>> As I said before, my claim is that if a variant can default-construct, it
>> should have an empty value (aka invalid state).
>>
>> An at-most-one variant should default construct to empty.
>>
>> An exactly-one variant should not be default-constructable.
>>
>> The example above demonstrates why both of these are true.
>>
>
> Again, I don't see how you are coming to any of these conclusions from
> your example, but rather, you just seem to be asserting them. In either
> case (default-to-invalid or default-to-something-else) you have a bug in
> user-land code if the user inappropriately used the default... and? How is
> this different from a programmer misusing any other function? I would
> understand if your conclusion was that no default constructor should exist
> at all, though that same logic can be used for any type that is not a
> monostate and not just a variant. Weakening the invariants of the type to
> introduce "invalid" just makes things worse because now all or most
> standard and user-land contracts are necessarily more complicated. This
> because you don't want to choose a specific default value? That's a pretty
> drastic penalty. If the default doesn't make sense for your use, then just
> don't default construct your object, or don't define the default
> constructor.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b874e50ea0aab0520c50b9f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">If a type is default constructible, the default value that=
results is important and does matter.<div><br></div><div>If it is a surpri=
sing value, bugs will result.=C2=A0 It is a common logic error to implicitl=
y default construct an object (for example data members, array elements, et=
c) with the intention of assigning to them later, but not doing so.=C2=A0 W=
hen coming to read such an object the default value will be observed instea=
d of the intended value.=C2=A0 If the default value is surprising, then it =
will likely be treated as a correctly-set value, leading to an expensive di=
saster.=C2=A0 If it is unsurprising the fact that it is in default state is=
more likely to be branched on.</div><div><br></div><div>(Sometimes this ri=
sk is worth it for performance reasons, but that does not apply to the vari=
ant case, because the empty value is performant.=C2=A0 Potentially even mor=
e so than the default constructor of the first type.)</div><div><br></div><=
div>In the matrix case, dynamically-sized matrixes (if they default constru=
ct) default construct to the empty matrix:</div><div><br></div><div>For rea=
l world examples:</div><div><br></div><div>=C2=A0 =C2=A0 boost::numeric::ub=
las::matrix m; =C2=A0// empty</div><div>=C2=A0 =C2=A0 libarmadillo::Mat m; =
// empty</div><div>=C2=A0 =C2=A0 Eigen::MatrixXd m; // empty</div><div><br>=
</div><div>For a fixed-sized matrix, the default constructor generally does=
nothing for performance reasons (leaves memory uninitialized).=C2=A0 If an=
ything this argues for default constructing variant to empty (with -1 discr=
iminator and *unintialized* storage).</div><div><br></div><div>As for a Pla=
yingCard type, it should either (1) not be default-constructible; (2) defau=
lt construct to a special empty value (suit =3D -1); or (3) default constru=
ct uninitialized for performance (suppose you have large arrays of them in =
some simulation).=C2=A0 In no case should it default construct specifically=
to Ace of Spades (except accidentally as a result of 3).</div><div><br></d=
iv><div>Default constructing PlayingCard to Ace of Spades is exactly like d=
efault constructing a variant to hold a value of the first type.</div><div>=
<br></div><div class=3D"gmail_extra"><div class=3D"gmail_quote">On Mon, Sep=
28, 2015 at 2:51 AM, 'Matt Calabrese' via ISO C++ Standard - Futur=
e Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@isocpp.or=
g" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<br><blo=
ckquote 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;paddi=
ng-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmai=
l_quote"><span class=3D"">On Sun, Sep 27, 2015 at 5:29 PM, Andrew Tomazos <=
span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_=
blank">andrewtomazos@gmail.com</a>></span> wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div d=
ir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>It is=
analogous to default-constructing to a value of the first type, just to ma=
intain the invariant that an exactly-one variant has an invariant that it a=
lways holds a value of one of the types.=C2=A0 The "garbage" is t=
he "made-up" value of the first type that results from default co=
nstruction.</div></div></div></div></blockquote><div><br></div></span><div>=
I do not see how this is the conclusion you'd come to. A specific defau=
lt is frequently somewhat arbitrary and dependent on a specific usage, not =
necessarily intrinsic to the type. The matrix example (all 0, or identity, =
or something else) is a good example of that, but it's true for plenty =
of types. If I have a type representing a playing card, do I have a default=
constructor that makes it ace of spades? Two of clubs? Does it not have a =
default constructor at all? It ultimately is subjective and doesn't mat=
ter. If the default doesn't make sense for a user, then they don't =
use a default-constructed object (or they default-construct and initialize =
later). That a default doesn't apply to every single situation does not=
mean that it is "garbage" or that you need to weaken the invaria=
nts of the type. All it means is either that a user wouldn't use that d=
efault in the places that it doesn't make sense, or the developer of th=
e type would just choose to not give the type a default constructor. Why is=
weakening the invariants of the type and giving it an <i>actual</i>=C2=A0g=
arbage value (by garbage I mean something for which nearly all functions ha=
ve a precondition that disallows it) somehow better? All that does is compl=
icate contracts involved.</div><div><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"=
ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D""=
><span><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 cl=
ass=3D"gmail_quote"><span><div>On Sun, Sep 27, 2015 at 3:25 PM, Andrew Toma=
zos=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" t=
arget=3D"_blank">andrewtomazos@gmail.com</a>></span>=C2=A0wrote:</div></=
span></div></div></div></blockquote></span></span><span class=3D""><div>As =
I said before, my claim is that if a variant can default-construct, it shou=
ld have an empty value (aka invalid state).</div><div><br></div><div>An at-=
most-one variant should default construct to empty.</div><div><br></div><di=
v>An exactly-one variant should not be default-constructable.</div><div><br=
></div><div>The example above demonstrates why both of these are true.</div=
></span></div></div></div></blockquote><div><br></div><div>Again, I don'=
;t see how you are coming to any of these conclusions from your example, bu=
t rather, you just seem to be asserting them. In either case (default-to-in=
valid or default-to-something-else) you have a bug in user-land code if the=
user inappropriately used the default... and? How is this different from a=
programmer misusing any other function? I would understand if your conclus=
ion was that no default constructor should exist at all, though that same l=
ogic can be used for any type that is not a monostate and not just a varian=
t. Weakening the invariants of the type to introduce "invalid" ju=
st makes things worse because now all or most standard and user-land contra=
cts are necessarily more complicated. This because you don't want to ch=
oose a specific default value? That's a pretty drastic penalty. If the =
default doesn't make sense for your use, then just don't default co=
nstruct your object, or don't define the default constructor.</div></di=
v></div></div><div class=3D""><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b874e50ea0aab0520c50b9f--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 05:51:00 +0300
Raw View
On 28 September 2015 at 04:59, Andrew Tomazos <andrewtomazos@gmail.com> wrote:
> As for a PlayingCard type, it should either (1) not be
> default-constructible; (2) default construct to a special empty value (suit
> = -1); or (3) default construct uninitialized for performance (suppose you
> have large arrays of them in some simulation). In no case should it default
> construct specifically to Ace of Spades (except accidentally as a result of
> 3).
Why? The case of default constructing it to a valid value can be made just
as easily as yours.
> Default constructing PlayingCard to Ace of Spades is exactly like default
> constructing a variant to hold a value of the first type.
In the sense that whether it should default construct to a valid value or not,
yes, indeed, it's exactly like that - and which is right is somewhat
domain-specific.
Neither approach is "absurd" - what _is_ absurd is making the claim that one
of the approaches is "absurd", and seems to be heavily biased by the domains
various people work in. Either approach can be, perhaps somewhat suboptimally,
be built on top of the other, so I have a fairly hard time understanding why
people insinuate this decision being so significant to the point that if one's
preferred approach isn't chosen, we shouldn't have a standard variant at all.
We have plenty of evidence that, for the case of default construction,
both constructing
to a somewhat arbitrary state and to an empty state have reasonably motivated
uses in the wild. If that's the trench you want to dig yourself in,
it's somewhat
unlikely that we can make progress by discussing it on this forum.
For what it's worth, there's exactly two approaches that I find unacceptable:
1) dynamic allocation.
2) constraining variant to outright reject types with throwing moves.
Everything else is negotiable. I can deal with whichever alternatives
that follow,
and so can my users, after the education that needs to be performed anyway
regardless of which exact approach gets chosen. The problem we face
is the apparent inability of people to compromise on anything related
to variant.
We will likely have a large-crowd discussion about variant in Kona. I
hope and expect
that we can put a variant of some sort into a Technical Specification
some time after
Kona. Once we do, it's up to the users to provide feedback on whether
that variant
is acceptable, but if it isn't, and any other approach isn't either,
we'll get the "blissful"
state of status quo, which is that C++ doesn't have a standard
variant. So, the ultimate
question to everybody discussing variant is this: what are you willing
to sacrifice
to get a type spelled std::variant? The other question is this: what
are the approaches
that are truly over-your-dead-body to the point that a variant using
such approaches
is worse than not having a variant at all?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Sun, 27 Sep 2015 20:01:05 -0700 (PDT)
Raw View
------=_Part_282_624089581.1443409265299
Content-Type: multipart/alternative;
boundary="----=_Part_283_569578491.1443409265300"
------=_Part_283_569578491.1443409265300
Content-Type: text/plain; charset=UTF-8
On Sunday, September 27, 2015 at 7:51:02 PM UTC-7, Ville Voutilainen wrote:
>
> For what it's worth, there's exactly two approaches that I find
> unacceptable:
> 1) dynamic allocation.
> 2) constraining variant to outright reject types with throwing moves.
>
> Everything else is negotiable. I can deal with whichever alternatives
> that follow,
>
FWIW, keep in mind that users who disable exceptions basically never ever
have to deal with (2) so all that's left is just making sure dynamic
allocation is avoided.
So if your "over my dead body" objection is related to overheads from
exceptions, ask yourself if that's _really_ a problem in your domain.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_283_569578491.1443409265300
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, September 27, 2015 at 7:51:02 PM UTC-7, Ville V=
outilainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">For what it&#=
39;s worth, there's exactly two approaches that I find unacceptable:
<br>1) dynamic allocation.
<br>2) constraining variant to outright reject types with throwing moves.
<br>
<br>Everything else is negotiable. I can deal with whichever alternatives
<br>that follow,
<br></blockquote><div><br></div><div>FWIW, keep in mind that users who disa=
ble exceptions basically never ever have to deal with (2) so all that's=
left is just making sure dynamic allocation is avoided.</div><div><br></di=
v><div>So if your "over my dead body" objection is related to ove=
rheads from exceptions, ask yourself if that's _really_ a problem in yo=
ur domain.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_283_569578491.1443409265300--
------=_Part_282_624089581.1443409265299--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Sun, 27 Sep 2015 23:07:52 -0500
Raw View
--001a114363acb89df30520c6d99e
Content-Type: text/plain; charset=UTF-8
On 27 September 2015 at 22:01, Sean Middleditch <sean.middleditch@gmail.com>
wrote:
> On Sunday, September 27, 2015 at 7:51:02 PM UTC-7, Ville Voutilainen wrote:
>>
>> For what it's worth, there's exactly two approaches that I find
>> unacceptable:
>> 1) dynamic allocation.
>> 2) constraining variant to outright reject types with throwing moves.
>>
>> Everything else is negotiable. I can deal with whichever alternatives
>> that follow,
>>
>
> FWIW, keep in mind that users who disable exceptions basically never ever
> have to deal with (2) so all that's left is just making sure dynamic
> allocation is avoided.
>
FWIW keep in mind that is only a subset of C++ users. We have popular
implementations of the standard library that have throwing moves.
> So if your "over my dead body" objection is related to overheads from
> exceptions, ask yourself if that's _really_ a problem in your domain.
>
The C++ Standards Committee is supposed to take into account the language
and library as a whole and not just small subsets of it. While we
certainly should and do listen to the representatives of those domains,
ultimately we try and do what is right for C++. Not that any two of us
agree on what that is...
I'm not trying to solve it for what is best for my domain (heck, my
"domain" changes at least as often as I change jobs); I'm trying to solve
it for what is best for the language. If that doesn't match my domain well
enough, then I'll design and implement a domain-specific one. And if I
think that has general appeal, then I'll propose it, and the cycle of life
continues. :-)
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a114363acb89df30520c6d99e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 27 September 2015 at 22:01, Sean Middleditch <span dir=
=3D"ltr"><<a href=3D"mailto:sean.middleditch@gmail.com" target=3D"_blank=
">sean.middleditch@gmail.com</a>></span> wrote:<br><div class=3D"gmail_e=
xtra"><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,2=
04,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span cl=
ass=3D"">On Sunday, September 27, 2015 at 7:51:02 PM UTC-7, Ville Voutilain=
en wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex">For what it's worth, there's exactly two =
approaches that I find unacceptable:
<br>1) dynamic allocation.
<br>2) constraining variant to outright reject types with throwing moves.
<br>
<br>Everything else is negotiable. I can deal with whichever alternatives
<br>that follow,
<br></blockquote><div><br></div></span><div>FWIW, keep in mind that users w=
ho disable exceptions basically never ever have to deal with (2) so all tha=
t's left is just making sure dynamic allocation is avoided.</div></div>=
</blockquote><div><br></div>FWIW keep in mind that is only a subset of C++ =
users.=C2=A0 We have popular implementations of the standard library that h=
ave throwing moves.<br><div>=C2=A0</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rg=
b(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><=
div>So if your "over my dead body" objection is related to overhe=
ads from exceptions, ask yourself if that's _really_ a problem in your =
domain.</div></div></blockquote><div><br></div><div>The C++ Standards Commi=
ttee is supposed to take into account the language and library as a whole a=
nd not just small subsets of it. =C2=A0 While we certainly should and do li=
sten to the representatives of those domains, ultimately we try and do what=
is right for C++.=C2=A0 Not that any two of us agree on what that is...</d=
iv><div><br></div><div>I'm not trying to solve it for what is best for =
my domain (heck, my "domain" changes at least as often as I chang=
e jobs); I'm trying to solve it for what is best for the language.=C2=
=A0 If that doesn't match my domain well enough, then I'll design a=
nd implement a domain-specific one.=C2=A0 And if I think that has general a=
ppeal, then I'll propose it, and the cycle of life continues. :-)</div>=
<div>--=C2=A0</div></div><div class=3D"gmail_signature">=C2=A0Nevin ":=
-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" t=
arget=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a114363acb89df30520c6d99e--
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Sun, 27 Sep 2015 21:14:45 -0700 (PDT)
Raw View
------=_Part_235_480745032.1443413685743
Content-Type: multipart/alternative;
boundary="----=_Part_236_82335611.1443413685752"
------=_Part_236_82335611.1443413685752
Content-Type: text/plain; charset=UTF-8
On Sunday, September 27, 2015 at 9:08:34 PM UTC-7, Nevin ":-)" Liber wrote:
>
>
>
>> So if your "over my dead body" objection is related to overheads from
>> exceptions, ask yourself if that's _really_ a problem in your domain.
>>
>
> The C++ Standards Committee is supposed to take into account the language
> and library as a whole and not just small subsets of it.
>
I said nothing to the contrary. :)
My point was that if one's only concern is throwing moves but also one
ignores exceptions anyway then one shouldn't get up in arms about
concessions that can be elided when exceptions are disabled.
I don't know if that's true for everyone involved, but some of the posts
I've seen so far seems to fall into that classification.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_236_82335611.1443413685752
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, September 27, 2015 at 9:08:34 PM UTC-7, Nevin &=
quot;:-)" Liber 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"><div><div class=3D"gmail_quote"><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex"><div dir=3D"ltr"><div>So if your "over my dead body" objecti=
on is related to overheads from exceptions, ask yourself if that's _rea=
lly_ a problem in your domain.</div></div></blockquote><div><br></div><div>=
The C++ Standards Committee is supposed to take into account the language a=
nd library as a whole and not just small subsets of it.</div></div></div></=
div></blockquote><div><br></div><div>I said nothing to the contrary. :)</di=
v><div><br></div><div>My point was that if one's only concern is throwi=
ng moves but also one ignores exceptions anyway then one shouldn't get =
up in arms about concessions that can be elided when exceptions are disable=
d.</div><div><br></div><div>I don't know if that's true for everyon=
e involved, but some of the posts I've seen so far seems to fall into t=
hat classification.</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>
</div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_236_82335611.1443413685752--
------=_Part_235_480745032.1443413685743--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 27 Sep 2015 22:02:44 -0700
Raw View
--001a11c30caa991bd50520c79b45
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 6:59 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
>
> If it is a surprising value, bugs will result. It is a common logic error
> to implicitly default construct an object (for example data members, array
> elements, etc) with the intention of assigning to them later, but not doing
> so.
>
That is a bug that exists whether you initialize to "invalid" or any other
value, equally. The only way to prevent that is to either make the type not
default constructible, thereby disallowing people from using such a
create/init later pattern (though in practice people would still do this
anyway, only they'd now be explicit about their initial dummy value), or,
preferably IMO, users avoid doing error-prone initialization like that in
their code because there are existing alternatives that make it unnecessary
(I.E. you don't create an default constructed value of that type and then
initialize later, you initialize it directly, often via ternary operator or
the result of a function call, which in modern C++ can simply be a lambda,
and these solutions are also just as efficient because of RVO). Making some
invalid value doesn't prevent such classes of bug. They arguably might help
diagnose when such a mistake occurs, but they do not prevent those
mistakes. You can only prevent them by better programming practices.
On Sun, Sep 27, 2015 at 6:59 PM, Andrew Tomazos
<andrewtomazos@gmail.com> wrote:
s.
> As for a PlayingCard type, it should either (1) not be
> default-constructible; (2) default construct to a special empty value (suit
> = -1); or (3) default construct uninitialized for performance (suppose you
> have large arrays of them in some simulation). In no case should it
> default construct specifically to Ace of Spades (except accidentally as a
> result of 3).
>
If you want performance for something like an array of them, instead of
introducing an invalid state, just don't have the object constructed (I.E.
the equivalent to only reserving in a vector rather than resizing it). It
sounds like your main concern is that you want to create an instance of
some type and then initialize it later, and you don't want overhead of the
original, default initialization. Instead of doing that, initialize it
properly on creation and don't construct it before you need it. It's simply
not true that you have to have this uninitialized state as a part of the
object type. When it's uninitialized, it's simply raw storage and not
constructed at all. It is not an instance of the type.
On Sun, Sep 27, 2015 at 6:59 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> Default constructing PlayingCard to Ace of Spades is exactly like default
> constructing a variant to hold a value of the first type.
>
Yes, in that they are both perfectly fine, just as a vector with a default
constructor that initializes to size 0 is fine (and is what we do in the
standard). You aren't arguing that a vector should be uninitialized or
"invalid" on default construction instead of empty. Why? After all, your
rationale could be applied there as well -- you should be able to
default-initialize and then *actually* initialize it later, because you
want initialization to be essentially a no-op as in the card example.
Again, instead of doing that and complicating your type and its invariants,
just initialize your object properly and immediately when you construct.
You don't need to use a default constructor to do this. Invalid states only
complicate all of your contracts, since functions now have to have
preconditions disallowing the "invalid" state for their operation.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c30caa991bd50520c79b45
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 S=
un, Sep 27, 2015 at 6:59 PM, Andrew Tomazos <span dir=3D"ltr"><<a href=
=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.c=
om</a>></span> wrote:<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>If it is a s=
urprising value, bugs will result.=C2=A0 It is a common logic error to impl=
icitly default construct an object (for example data members, array element=
s, etc) with the intention of assigning to them later, but not doing so.=C2=
=A0</div></div></blockquote><div><br></div><div>That is a bug that exists w=
hether you initialize to "invalid" or any other value, equally. T=
he only way to prevent that is to either make the type not default construc=
tible, thereby disallowing people from using such a create/init later patte=
rn (though in practice people would still do this anyway, only they'd n=
ow be explicit about their initial dummy value), or, preferably IMO, users =
avoid doing error-prone initialization like that in their code because ther=
e are existing alternatives that make it unnecessary (I.E. you don't cr=
eate an default constructed value of that type and then initialize later, y=
ou initialize it directly, often via ternary operator or the result of a fu=
nction call, which in modern C++ can simply be a lambda, and these solution=
s are also just as efficient because of RVO). Making some invalid value doe=
sn't prevent such classes of bug. They arguably might help diagnose whe=
n such a mistake occurs, but they do not prevent those mistakes. You can on=
ly prevent them by better programming practices.</div><div><br></div><div>O=
n Sun, Sep 27, 2015 at 6:59 PM, Andrew Tomazos=C2=A0<span dir=3D"ltr"><<=
a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@g=
mail.com</a>></span>=C2=A0wrote: s.</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"lt=
r"><div>As for a PlayingCard type, it should either (1) not be default-cons=
tructible; (2) default construct to a special empty value (suit =3D -1); or=
(3) default construct uninitialized for performance (suppose you have larg=
e arrays of them in some simulation).=C2=A0 In no case should it default co=
nstruct specifically to Ace of Spades (except accidentally as a result of 3=
).</div></div></blockquote><div><br></div><div>If you want performance for =
something like an array of them, instead of introducing an invalid state, j=
ust don't have the object constructed (I.E. the equivalent to only rese=
rving in a vector rather than resizing it). It sounds like your main concer=
n is that you want to create an instance of some type and then initialize i=
t later, and you don't want overhead of the original, default initializ=
ation. Instead of doing that, initialize it properly on creation and don=
9;t construct it before you need it. It's simply not true that you have=
to have this uninitialized state as a part of the object type. When it'=
;s uninitialized, it's simply raw storage and not constructed at all. I=
t is not an instance of the type.</div><div><br></div><div>On Sun, Sep 27, =
2015 at 6:59 PM, Andrew Tomazos=C2=A0<span dir=3D"ltr"><<a href=3D"mailt=
o:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@gmail.com</a>>=
;</span>=C2=A0wrote:</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"><div dir=3D"ltr"><div>Default co=
nstructing PlayingCard to Ace of Spades is exactly like default constructin=
g a variant to hold a value of the first type.</div></div></blockquote><div=
><br></div><div>Yes, in that they are both perfectly fine, just as a vector=
with a default constructor that initializes to size 0 is fine (and is what=
we do in the standard). You aren't arguing that a vector should be uni=
nitialized or "invalid" on default construction instead of empty.=
Why? After all, your rationale could be applied there as well -- you shoul=
d be able to default-initialize and then *actually* initialize it later, be=
cause you want initialization to be essentially a no-op as in the card exam=
ple. Again, instead of doing that and complicating your type and its invari=
ants, just initialize your object properly and immediately when you constru=
ct. You don't need to use a default constructor to do this. Invalid sta=
tes only complicate all of your contracts, since functions now have to have=
preconditions disallowing the "invalid" state for their operatio=
n.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c30caa991bd50520c79b45--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Mon, 28 Sep 2015 07:05:15 +0200
Raw View
--047d7b874e509ad4d00520c7a4e5
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 4:51 AM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:
> On 28 September 2015 at 04:59, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
> > As for a PlayingCard type, it should either (1) not be
> > default-constructible; (2) default construct to a special empty value
> (suit
> > = -1); or (3) default construct uninitialized for performance (suppose
> you
> > have large arrays of them in some simulation). In no case should it
> default
> > construct specifically to Ace of Spades (except accidentally as a result
> of
> > 3).
>
> Why? The case of default constructing it to a valid value can be made just
> as easily as yours.
>
I am yet to hear that case. The Williams paper (see "Default
Construction") comes to exactly the same conclusion I have on the issue.
As has, last I heard, Stroustrup. Where is the paper that argues default
constructing to the first type is better than default constructing to empty?
All the Lenexa paper says is "[the 10 guys present eventually] opted
against a variant default-initialized into its empty state, to limit the
paths of getting an empty variant to a throwing construction during an
assignment or call to emplace()."
The entire rationale is "to limit the paths of getting an empty variant".
That's not a case. It's 9 words.
> > Default constructing PlayingCard to Ace of Spades is exactly like default
> > constructing a variant to hold a value of the first type.
>
> In the sense that whether it should default construct to a valid value or
> not,
> yes, indeed, it's exactly like that - and which is right is somewhat
> domain-specific.
> Neither approach is "absurd"
Sure, I got a bit salty with the language. :) Withdrawn. My claim is that
default constructing to empty is better than default constructing to the
first type.
> - what _is_ absurd is making the claim that one
> of the approaches is "absurd", and seems to be heavily biased by the
> domains
> various people work in. Either approach can be, perhaps somewhat
> suboptimally,
> be built on top of the other, so I have a fairly hard time understanding
> why
> people insinuate this decision being so significant to the point that if
> one's
> preferred approach isn't chosen, we shouldn't have a standard variant at
> all.
> We have plenty of evidence that, for the case of default construction,
> both constructing
> to a somewhat arbitrary state and to an empty state have reasonably
> motivated
> uses in the wild. If that's the trench you want to dig yourself in,
> it's somewhat
> unlikely that we can make progress by discussing it on this forum.
>
> For what it's worth, there's exactly two approaches that I find
> unacceptable:
> 1) dynamic allocation.
> 2) constraining variant to outright reject types with throwing moves.
>
I would add to this:
3) std::variant<A,B,C> is larger than
struct {
union { A a; B b; C c; } storage;
uint8 discriminator;
};
(Perhaps that went without saying for you?)
> Everything else is negotiable.
If the empty / default construction issue is discussed in the Kona large
group, and the decision is to go with default constructing to the first
type, I would accept the decision. As you say it is more-or-less easy to
write an adapter around such a variant to hide the not-aburd-but-suboptimal
behaviour. :)
(Even if it isn't easy, it takes all of 2 seconds to fork std::variant from
the stdlib code into a local namespace and make modifications to the
internals.)
I can deal with whichever alternatives
> that follow,
> and so can my users, after the education that needs to be performed anyway
> regardless of which exact approach gets chosen. The problem we face
> is the apparent inability of people to compromise on anything related
> to variant.
>
> We will likely have a large-crowd discussion about variant in Kona. I
> hope and expect
> that we can put a variant of some sort into a Technical Specification
> some time after
> Kona. Once we do, it's up to the users to provide feedback on whether
> that variant
> is acceptable, but if it isn't, and any other approach isn't either,
> we'll get the "blissful"
> state of status quo, which is that C++ doesn't have a standard
> variant. So, the ultimate
> question to everybody discussing variant is this: what are you willing
> to sacrifice
> to get a type spelled std::variant? The other question is this: what
> are the approaches
> that are truly over-your-dead-body to the point that a variant using
> such approaches
> is worse than not having a variant at all?
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b874e509ad4d00520c7a4e5
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 M=
on, Sep 28, 2015 at 4:51 AM, Ville Voutilainen <span dir=3D"ltr"><<a hre=
f=3D"mailto:ville.voutilainen@gmail.com" target=3D"_blank">ville.voutilaine=
n@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><span>On 28 September=
2015 at 04:59, Andrew Tomazos <<a href=3D"mailto:andrewtomazos@gmail.co=
m" target=3D"_blank">andrewtomazos@gmail.com</a>> wrote:<br>
> As for a PlayingCard type, it should either (1) not be<br>
> default-constructible; (2) default construct to a special empty value =
(suit<br>
> =3D -1); or (3) default construct uninitialized for performance (suppo=
se you<br>
> have large arrays of them in some simulation).=C2=A0 In no case should=
it default<br>
> construct specifically to Ace of Spades (except accidentally as a resu=
lt of<br>
> 3).<br>
<br>
</span>Why? The case of default constructing it to a valid value can be mad=
e just<br>
as easily as yours.<br></blockquote><div><br></div><div>I am yet to hear th=
at case.=C2=A0 The Williams paper (see "Default Construction") co=
mes to exactly the same conclusion I have on the issue.=C2=A0 As has, last =
I heard, Stroustrup.=C2=A0 Where is the paper that argues default construct=
ing to the first type is better than default constructing to empty?</div><d=
iv><br></div><div>All the Lenexa paper says is "[the 10 guys present e=
ventually] opted against a variant default-initialized into its empty state=
, to limit the paths of
getting an empty variant to a throwing construction during an assignment or
call to emplace()."</div><div><br></div><div>The entire rationale is &=
quot;to limit the paths of getting an empty variant".=C2=A0 That's=
not a case.=C2=A0 It's 9 words.</div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span><br>
> Default constructing PlayingCard to Ace of Spades is exactly like defa=
ult<br>
> constructing a variant to hold a value of the first type.<br>
<br>
</span>In the sense that whether it should default construct to a valid val=
ue or not,<br>
yes, indeed, it's exactly like that - and which is right is somewhat<br=
>
domain-specific.<br>
Neither approach is "absurd"</blockquote><div><br></div><div>Sure=
, I got a bit salty with the language. :) =C2=A0Withdrawn.=C2=A0 My claim i=
s that default constructing to empty is better than default constructing to=
the first type.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=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"> - what _is_ absurd=
is making the claim that one<br>
of the approaches is "absurd", and seems to be heavily biased by =
the domains<br>
various people work in. Either approach can be, perhaps somewhat suboptimal=
ly,<br>
be built on top of the other, so I have a fairly hard time understanding wh=
y<br>
people insinuate this decision being so significant to the point that if on=
e's<br>
preferred approach isn't chosen, we shouldn't have a standard varia=
nt at all.<br>
We have plenty of evidence that, for the case of default construction,<br>
both constructing<br>
to a somewhat arbitrary state and to an empty state have reasonably motivat=
ed<br>
uses in the wild. If that's the trench you want to dig yourself in,<br>
it's somewhat<br>
unlikely that we can make progress by discussing it on this forum.<br>
<br>
For what it's worth, there's exactly two approaches that I find una=
cceptable:<br>
1) dynamic allocation.<br>
2) constraining variant to outright reject types with throwing moves.<br></=
blockquote><div><br></div><div>I would add to this:</div><div><br></div><di=
v>3) std::variant<A,B,C> is larger than</div><div><br></div><div>=C2=
=A0 =C2=A0 struct {</div><div>=C2=A0 =C2=A0 =C2=A0 union { A a; B b; C c; }=
storage;</div><div>=C2=A0 =C2=A0 =C2=A0 uint8 discriminator;</div><div>=C2=
=A0 =C2=A0 };<br></div><div><br></div><div>(Perhaps that went without sayin=
g for you?)</div><div>=C2=A0<br></div><blockquote class=3D"gmail_quote" sty=
le=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">
Everything else is negotiable.</blockquote><div><br></div><div>If the empty=
/ default construction issue is discussed in the Kona large group, and the=
decision is to go with default constructing to the first type, I would acc=
ept the decision.=C2=A0 As you say it is more-or-less easy to write an adap=
ter around such a variant to hide the not-aburd-but-suboptimal behaviour. :=
)</div><div><br></div><div>(Even if it isn't easy, it takes all of 2 se=
conds to fork std::variant from the stdlib code into a local namespace and =
make modifications to the internals.)</div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
I can deal with whichever alternatives<br>
that follow,<br>
and so can my users, after the education that needs to be performed anyway<=
br>
regardless of which exact approach gets chosen. The problem we face<br>
is the apparent inability of people to compromise on anything related<br>
to variant.<br>
<br>
We will likely have a large-crowd discussion about variant in Kona. I<br>
hope and expect<br>
that we can put a variant of some sort into a Technical Specification<br>
some time after<br>
Kona. Once we do, it's up to the users to provide feedback on whether<b=
r>
that variant<br>
is acceptable, but if it isn't, and any other approach isn't either=
,<br>
we'll get the "blissful"<br>
state of status quo, which is that C++ doesn't have a standard<br>
variant. So, the ultimate<br>
question to everybody discussing variant is this: what are you willing<br>
to sacrifice<br>
to get a type spelled std::variant? The other question is this: what<br>
are the approaches<br>
that are truly over-your-dead-body to the point that a variant using<br>
such approaches<br>
is worse than not having a variant at all?<br>
<div><div><br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b874e509ad4d00520c7a4e5--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 08:08:26 +0300
Raw View
On 28 September 2015 at 08:05, Andrew Tomazos <andrewtomazos@gmail.com> wrote:
>> For what it's worth, there's exactly two approaches that I find
>> unacceptable:
>> 1) dynamic allocation.
>> 2) constraining variant to outright reject types with throwing moves.
> I would add to this:
> 3) std::variant<A,B,C> is larger than
> struct {
> union { A a; B b; C c; } storage;
> uint8 discriminator;
> };
> (Perhaps that went without saying for you?)
I don't see how you think you have the warrant to add to my list of
non-negotiable
things. I don't find what you describe as (3) non-negotiable.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 08:12:11 +0300
Raw View
On 28 September 2015 at 08:08, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 28 September 2015 at 08:05, Andrew Tomazos <andrewtomazos@gmail.com> wrote:
>>> For what it's worth, there's exactly two approaches that I find
>>> unacceptable:
>>> 1) dynamic allocation.
>>> 2) constraining variant to outright reject types with throwing moves.
>> I would add to this:
>> 3) std::variant<A,B,C> is larger than
>> struct {
>> union { A a; B b; C c; } storage;
>> uint8 discriminator;
>> };
>> (Perhaps that went without saying for you?)
>
> I don't see how you think you have the warrant to add to my list of
> non-negotiable
> things. I don't find what you describe as (3) non-negotiable.
To clarify, I'm perfectly fine with your having your own list of things that
are non-negotiable, but please refrain from speculating whether mere
additions to my list "go without saying" for me. I want to make it perfectly
clear that _for me_, the list has two items. :) If you wanted to say that
it should go without saying for me that your list has an additional third
item, fine, although that was hardly obvious for me. :P
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Mon, 28 Sep 2015 07:14:30 +0200
Raw View
--089e0103009ca7bfe70520c7c5bf
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 7:08 AM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:
> On 28 September 2015 at 08:05, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
> >> For what it's worth, there's exactly two approaches that I find
> >> unacceptable:
> >> 1) dynamic allocation.
> >> 2) constraining variant to outright reject types with throwing moves.
> > I would add to this:
> > 3) std::variant<A,B,C> is larger than
> > struct {
> > union { A a; B b; C c; } storage;
> > uint8 discriminator;
> > };
> > (Perhaps that went without saying for you?)
>
> I don't see how you think you have the warrant to add to my list of
> non-negotiable
> things. I don't find what you describe as (3) non-negotiable.
>
Ok, that surprises me. For me it is non-negotiable. I would vote against
such a design and would never use it or advocate its use.
Just to confirm my understanding is correct - the Lenexa variant doesn't
have this property right?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0103009ca7bfe70520c7c5bf
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 M=
on, Sep 28, 2015 at 7:08 AM, Ville Voutilainen <span dir=3D"ltr"><<a hre=
f=3D"mailto:ville.voutilainen@gmail.com" target=3D"_blank">ville.voutilaine=
n@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span c=
lass=3D"">On 28 September 2015 at 08:05, Andrew Tomazos <<a href=3D"mail=
to:andrewtomazos@gmail.com">andrewtomazos@gmail.com</a>> wrote:<br>
>> For what it's worth, there's exactly two approaches that I=
find<br>
>> unacceptable:<br>
>> 1) dynamic allocation.<br>
>> 2) constraining variant to outright reject types with throwing mov=
es.<br>
> I would add to this:<br>
> 3) std::variant<A,B,C> is larger than<br>
>=C2=A0 =C2=A0 =C2=A0struct {<br>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0union { A a; B b; C c; } storage;<br>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0uint8 discriminator;<br>
>=C2=A0 =C2=A0 =C2=A0};<br>
> (Perhaps that went without saying for you?)<br>
<br>
</span>I don't see how you think you have the warrant to add to my list=
of<br>
non-negotiable<br>
things. I don't find what you describe as (3) non-negotiable.<br>
<div class=3D"HOEnZb"><div class=3D"h5"></div></div></blockquote></div><br>=
</div><div class=3D"gmail_extra">Ok, that surprises me.=C2=A0 For me it is =
non-negotiable.=C2=A0 I would vote against such a design and would never us=
e it or advocate its use.</div><div class=3D"gmail_extra"><br></div><div cl=
ass=3D"gmail_extra">Just to confirm my understanding is correct - the Lenex=
a variant doesn't have this property right?</div><div class=3D"gmail_ex=
tra"><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0103009ca7bfe70520c7c5bf--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Mon, 28 Sep 2015 00:20:02 -0500
Raw View
--001a1142f7ecca3bc80520c7db8b
Content-Type: text/plain; charset=UTF-8
On 28 September 2015 at 00:05, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> I am yet to hear that case. The Williams paper (see "Default
> Construction") comes to exactly the same conclusion I have on the issue.
> As has, last I heard, Stroustrup. Where is the paper that argues default
> constructing to the first type is better than default constructing to empty?
>
N4542. You know, the paper on variant the got *actual* consensus in
Lenexa, by people who thought it was important enough to discuss, as
opposed to a "small but vocal minority" on mailing lists. While you may
have the authority to speak for Stroustrup, the "appeal to authority" is a
very poor debate technique.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1142f7ecca3bc80520c7db8b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 28 September 2015 at 00:05, Andrew Tomazos <span dir=3D=
"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andr=
ewtomazos@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><di=
v 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"><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><div>I am yet to hear th=
at case.=C2=A0 The Williams paper (see "Default Construction") co=
mes to exactly the same conclusion I have on the issue.=C2=A0 As has, last =
I heard, Stroustrup.=C2=A0 Where is the paper that argues default construct=
ing to the first type is better than default constructing to empty?</div></=
div></div></div></blockquote><div><br></div><div>N4542.=C2=A0 You know, the=
paper on variant the got <i>actual</i>=C2=A0consensus in Lenexa, by people=
who thought it was important enough to discuss, as opposed to a "smal=
l but vocal minority" on mailing lists.=C2=A0 While you may have the a=
uthority to speak for Stroustrup, the "appeal to authority" is a =
very poor debate technique.</div></div>-- <br><div class=3D"gmail_signature=
">=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevi=
n@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 =
(847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1142f7ecca3bc80520c7db8b--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 08:20:59 +0300
Raw View
On 28 September 2015 at 08:14, Andrew Tomazos <andrewtomazos@gmail.com> wrote:
>> I don't see how you think you have the warrant to add to my list of
>> non-negotiable
>> things. I don't find what you describe as (3) non-negotiable.
> Ok, that surprises me. For me it is non-negotiable. I would vote against
> such a design and would never use it or advocate its use.
That would depend on whether such a variant is always larger than a
discriminated
union, or only when it has to be. But even so, that's still not non-negotiable.
> Just to confirm my understanding is correct - the Lenexa variant doesn't
> have this property right?
I don't think it does.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Mon, 28 Sep 2015 07:40:42 +0200
Raw View
--f46d04462e6a5cc7350520c8235a
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 7:20 AM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 28 September 2015 at 00:05, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
>
>> I am yet to hear that case. The Williams paper (see "Default
>> Construction") comes to exactly the same conclusion I have on the issue.
>> As has, last I heard, Stroustrup. Where is the paper that argues default
>> constructing to the first type is better than default constructing to empty?
>>
>
> N4542. You know, the paper on variant the got *actual* consensus in
> Lenexa, by people who thought it was important enough to discuss, as
> opposed to a "small but vocal minority" on mailing lists.
>
I already quoted the 9 word rationale from N4542. The design decision
(either way) deserves a more thorough treatment. I think that is a
completely reasonable expectation for a standard library facility of as
broad interest.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--f46d04462e6a5cc7350520c8235a
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 M=
on, Sep 28, 2015 at 7:20 AM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</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"">On 28 September 2015 at 00:05, Andrew Tomazos <span dir=3D"ltr">=
<<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtoma=
zos@gmail.com</a>></span> wrote:<br></span><div class=3D"gmail_extra"><d=
iv class=3D"gmail_quote"><span class=3D""><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>I=
am yet to hear that case.=C2=A0 The Williams paper (see "Default Cons=
truction") comes to exactly the same conclusion I have on the issue.=
=C2=A0 As has, last I heard, Stroustrup.=C2=A0 Where is the paper that argu=
es default constructing to the first type is better than default constructi=
ng to empty?</div></div></div></div></blockquote><div><br></div></span><div=
>N4542.=C2=A0 You know, the paper on variant the got <i>actual</i>=C2=A0con=
sensus in Lenexa, by people who thought it was important enough to discuss,=
as opposed to a "small but vocal minority" on mailing lists.</di=
v></div></div></div></blockquote><div>=C2=A0<br></div><div>I already quoted=
the 9 word rationale from N4542.=C2=A0 The design decision (either way) de=
serves a more thorough treatment.=C2=A0 I think that is a completely reason=
able expectation for a standard library facility of as broad interest.</div=
><div><br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--f46d04462e6a5cc7350520c8235a--
.
Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Mon, 28 Sep 2015 08:04:29 +0200
Raw View
--089e0103009c6cfd750520c878df
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 7:12 AM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:
> On 28 September 2015 at 08:08, Ville Voutilainen
> <ville.voutilainen@gmail.com> wrote:
> > On 28 September 2015 at 08:05, Andrew Tomazos <andrewtomazos@gmail.com>
> wrote:
> >>> For what it's worth, there's exactly two approaches that I find
> >>> unacceptable:
> >>> 1) dynamic allocation.
> >>> 2) constraining variant to outright reject types with throwing moves.
> >> I would add to this:
> >> 3) std::variant<A,B,C> is larger than
> >> struct {
> >> union { A a; B b; C c; } storage;
> >> uint8 discriminator;
> >> };
> >> (Perhaps that went without saying for you?)
> >
> > I don't see how you think you have the warrant to add to my list of
> > non-negotiable
> > things. I don't find what you describe as (3) non-negotiable.
>
> To clarify, I'm perfectly fine with your having your own list of things
> that
> are non-negotiable, but please refrain from speculating whether mere
> additions to my list "go without saying" for me. I want to make it
> perfectly
> clear that _for me_, the list has two items. :) If you wanted to say that
> it should go without saying for me that your list has an additional third
> item, fine, although that was hardly obvious for me. :P
>
Ville :) Yes. I think. To clarify. Your list has 2 things. My list has
3 things. :) I need sleep. :)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0103009c6cfd750520c878df
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 7:12 AM, Ville Voutilainen <span dir=3D"ltr">&l=
t;<a href=3D"mailto:ville.voutilainen@gmail.com" target=3D"_blank">ville.vo=
utilainen@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"=
>On 28 September 2015 at 08:08, Ville Voutilainen<br>
<span class=3D""><<a href=3D"mailto:ville.voutilainen@gmail.com">ville.v=
outilainen@gmail.com</a>> wrote:<br>
> On 28 September 2015 at 08:05, Andrew Tomazos <<a href=3D"mailto:an=
drewtomazos@gmail.com">andrewtomazos@gmail.com</a>> wrote:<br>
>>> For what it's worth, there's exactly two approaches th=
at I find<br>
>>> unacceptable:<br>
>>> 1) dynamic allocation.<br>
>>> 2) constraining variant to outright reject types with throwing=
moves.<br>
>> I would add to this:<br>
>> 3) std::variant<A,B,C> is larger than<br>
>>=C2=A0 =C2=A0 =C2=A0struct {<br>
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0union { A a; B b; C c; } storage;<br>
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0uint8 discriminator;<br>
>>=C2=A0 =C2=A0 =C2=A0};<br>
>> (Perhaps that went without saying for you?)<br>
><br>
> I don't see how you think you have the warrant to add to my list o=
f<br>
> non-negotiable<br>
> things. I don't find what you describe as (3) non-negotiable.<br>
<br>
</span>To clarify, I'm perfectly fine with your having your own list of=
things that<br>
are non-negotiable, but please refrain from speculating whether mere<br>
additions to my list "go without saying" for me. I want to make i=
t perfectly<br>
clear that _for me_, the list has two items. :) If you wanted to say that<b=
r>
it should go without saying for me that your list has an additional third<b=
r>
item, fine, although that was hardly obvious for me. :P<br>
<div class=3D"HOEnZb"><div class=3D"h5"></div></div></blockquote></div><br>=
</div><div class=3D"gmail_extra">Ville :) =C2=A0Yes.=C2=A0 I think.=C2=A0 T=
o clarify.=C2=A0 Your list has 2 things.=C2=A0 My list has 3 things. :) =C2=
=A0I need sleep. :)</div><div class=3D"gmail_extra"><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0103009c6cfd750520c878df--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Mon, 28 Sep 2015 01:04:47 -0500
Raw View
--001a1143f1c0d6cb3d0520c87baf
Content-Type: text/plain; charset=UTF-8
On 28 September 2015 at 00:40, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> I already quoted the 9 word rationale from N4542. The design decision
> (either way) deserves a more thorough treatment. I think that is a
> completely reasonable expectation for a standard library facility of as
> broad interest.
>
You weren't there. We discussed it. A lot. Over multiple sessions. We
brought up points made on mailing lists by people not in the room. When we
got out of sub group discussions and went to the full LEWG, we discussed it
again. Axel worked on interim versions of his paper during the meeting so
people could see what was happening.
I have no idea if the internal wiki captured that or not, as I wasn't the
one taking notes. If you have a better way to capture discussions on the
internal wiki that doesn't involve recording, I'm sure the entire committee
would love to hear about it.
AFAIK only one person who wasn't normally in LEWG had asked to be informed
when variant was being discussed. Had more people actually shown an
interest, it is likely a larger session would have been scheduled and we
wouldn't have wasted our time on the Lenexa consensus.
Oh, and the vast majority of standard library facilities has broad
interest; variant is not special in this regard. If they don't have broad
interest, why bother to standardize them?
And what is the minimum amount of people you would find acceptable before
we make decisions on these "facilities that have broad interest"?
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143f1c0d6cb3d0520c87baf
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 28 September 2015 at 00:40, Andrew Tomazos <span dir=3D=
"ltr"><<a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andr=
ewtomazos@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><di=
v 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"><di=
v class=3D"gmail_extra"><div class=3D"gmail_quote"><div>I already quoted th=
e 9 word rationale from N4542.=C2=A0 The design decision (either way) deser=
ves a more thorough treatment.=C2=A0 I think that is a completely reasonabl=
e expectation for a standard library facility of as broad interest.</div></=
div></div></div></blockquote><div><br></div><div>You weren't there.=C2=
=A0 We discussed it.=C2=A0 A lot.=C2=A0 Over multiple sessions.=C2=A0 We br=
ought up points made on mailing lists by people not in the room.=C2=A0 When=
we got out of sub group discussions and went to the full LEWG, we discusse=
d it again.=C2=A0 Axel worked on interim versions of his paper during the m=
eeting so people could see what was happening.</div><div><br></div><div>I h=
ave no idea if the internal wiki captured that or not, as I wasn't the =
one taking notes.=C2=A0 If you have a better way to capture discussions on =
the internal wiki that doesn't involve recording, I'm sure the enti=
re committee would love to hear about it.</div><div><br></div><div>AFAIK on=
ly one person who wasn't normally in LEWG had asked to be informed when=
variant was being discussed.=C2=A0 Had more people actually shown an inter=
est, it is likely a larger session would have been scheduled and we wouldn&=
#39;t have wasted our time on the Lenexa consensus.</div><div><br></div><di=
v>Oh, and the vast majority of standard library facilities has broad intere=
st; variant is not special in this regard.=C2=A0 If they don't have bro=
ad interest, why bother to standardize them?</div><div><br></div><div>And w=
hat is the minimum amount of people you would find acceptable before we mak=
e decisions on these "facilities that have broad interest"?</div>=
<div>--=C2=A0<br></div></div><div class=3D"gmail_signature">=C2=A0Nevin &qu=
ot;:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.co=
m" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</d=
iv>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143f1c0d6cb3d0520c87baf--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 09:22:16 +0300
Raw View
On 28 September 2015 at 09:04, Nevin Liber <nevin@eviloverlord.com> wrote:
>> I already quoted the 9 word rationale from N4542. The design decision
>> (either way) deserves a more thorough treatment. I think that is a
>> completely reasonable expectation for a standard library facility of as
>> broad interest.
> You weren't there. We discussed it. A lot. Over multiple sessions. We
> brought up points made on mailing lists by people not in the room. When we
> got out of sub group discussions and went to the full LEWG, we discussed it
> again. Axel worked on interim versions of his paper during the meeting so
> people could see what was happening.
In addition to that, a variant for which the main design goal is to desperately
avoid the cases where a variant is invalid, default-constructing to an invalid
state would semi-obviously defeat that goal. The fact that it also allows
the N4542 variant to be used as a map key and support map's operator[]
happens to be a nice bonus, and that bonus doesn't need to be emphasized
at least to me, it semi-automatically falls out from the
specification. :P As does
the fact that it works with the one-parameter overload of vector. And many, many
other things. Of course, those things are not necessarily specific to the N4542
variant, they apply to any variant that is defaultconstructible. That's also why
I find it absurd to state defaultconstructibility of a variant as
absurd, even if that
means it will always defaultconstruct the first type, which may not always be
an optimal choice. ;)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 28 Sep 2015 15:03:18 +0800
Raw View
--Apple-Mail=_73F9D310-89E1-45DA-85FA-6C1EE24CDEB2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9328, at 2:22 PM, Ville Voutilainen <ville.vouti=
lainen@gmail.com> wrote:
>=20
> In addition to that, a variant for which the main design goal is to despe=
rately
> avoid the cases where a variant is invalid, default-constructing to an in=
valid
> state would semi-obviously defeat that goal.
The feeling of desperation is a bad sign, that the architecture might be ov=
erconstrained.
Nicol mentioned GSL not_null as evidence of the advantage of avoiding null =
values. Why not spell a non-nullable variant as not_null<variant<T...>>?
Note that the current implementation of not_null actually does allow <https=
://github.com/Microsoft/GSL/blob/master/include/gsl.h#L126> its wrapped poi=
nter to be assigned a null value before it throws its exception; after all,=
that=E2=80=99s just as good as any dangling reference.
> The fact that it also allows
> the N4542 variant to be used as a map key and support map's operator[]
> happens to be a nice bonus,
But, default construction followed by assignment isn=E2=80=99t always as go=
od as construction with a value in the first place. map<T, variant> would b=
ehave ever so slightly differently from map<T, optional>. See my earlier ex=
ample with a container, or (if you have the stomach) my paper bit.ly/allocf=
un <http://bit.ly/allocfun>.
Does default-construction to a potentially bogus =E2=80=9Cfirst-listed=E2=
=80=9D state have the conceptual validity as to a disengaged state?
> That's also why
> I find it absurd to state defaultconstructibility of a variant as
> absurd,
I agree that non-absurd arguments exist for most of the alternatives. This =
debate could use a healthy dose of well-researched writeups on the design s=
pace (not only specs of single implementations). Passions are running high,=
and while this thread might (or might not) help to inform its participants=
, there are more folks in the community who are probably interested to lear=
n about the alternatives. It sounds like the committee is spending a dispro=
portionate amount of time on topics which are esoteric to the public, but o=
n which the community could possibly find more consensus if the debate outs=
ide the meetings had more cohesion.
--=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/.
--Apple-Mail=_73F9D310-89E1-45DA-85FA-6C1EE24CDEB2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9328, at 2:22 PM, Ville Voutilainen <<a href=3D"mailto:ville.vout=
ilainen@gmail.com" class=3D"">ville.voutilainen@gmail.com</a>> wrote:</d=
iv><br class=3D"Apple-interchange-newline"><div class=3D"">In addition to t=
hat, a variant for which the main design goal is to desperately<br class=3D=
"">avoid the cases where a variant is invalid, default-constructing to an i=
nvalid<br class=3D"">state would semi-obviously defeat that goal. </div></b=
lockquote><div><br class=3D""></div><div>The feeling of desperation is a ba=
d sign, that the architecture might be overconstrained.</div><div><br class=
=3D""></div><div>Nicol mentioned GSL <font face=3D"Courier" class=3D"">not_=
null</font> as evidence of the advantage of avoiding null values. Why =
not spell a non-nullable variant as <font face=3D"Courier" class=3D"">not_n=
ull<variant<T...>></font>?</div><div><br class=3D""></div><div>=
Note that the current implementation of <font face=3D"Courier" class=3D"">n=
ot_null</font> actually <a href=3D"https://github.com/Microsoft/GSL/bl=
ob/master/include/gsl.h#L126" class=3D"">does allow</a> its wrapped po=
inter to be assigned a null value before it throws its exception; after all=
, that=E2=80=99s just as good as any dangling reference.</div><br class=3D"=
"><blockquote type=3D"cite" class=3D""><div class=3D"">The fact that it als=
o allows<br class=3D"">the N4542 variant to be used as a map key and suppor=
t map's operator[]<br class=3D"">happens to be a nice bonus, </div></blockq=
uote><div><br class=3D""></div><div>But, default construction followed by a=
ssignment isn=E2=80=99t always as good as construction with a value in the =
first place. <font face=3D"Courier" class=3D"">map<T, variant></=
font> would behave ever so slightly differently from <font face=
=3D"Courier" class=3D"">map<T, optional></font>. See my earlier examp=
le with a container, or (if you have the stomach) my paper <a href=3D"http:=
//bit.ly/allocfun" class=3D"">bit.ly/allocfun</a>.</div><div><br class=3D""=
></div><div>Does default-construction to a potentially bogus =E2=80=9Cfirst=
-listed=E2=80=9D state have the conceptual validity as to a disengaged stat=
e?</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""=
>That's also why<br class=3D"">I find it absurd to state defaultconstructib=
ility of a variant as<br class=3D"">absurd,</div></blockquote><br class=3D"=
"></div><div>I agree that non-absurd arguments exist for most of the altern=
atives. This debate could use a healthy dose of well-researched writeups on=
the design space (not only specs of single implementations). Passions are =
running high, and while this thread might (or might not) help to inform its=
participants, there are more folks in the community who are probably inter=
ested to learn about the alternatives. It sounds like the committee is spen=
ding a disproportionate amount of time on topics which are esoteric to the =
public, but on which the community could possibly find more consensus if th=
e debate outside the meetings had more cohesion.</div><div><br class=3D""><=
/div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_73F9D310-89E1-45DA-85FA-6C1EE24CDEB2--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 10:51:55 +0300
Raw View
On 28 September 2015 at 10:03, David Krauss <potswa@gmail.com> wrote:
>
> On 2015=E2=80=9309=E2=80=9328, at 2:22 PM, Ville Voutilainen <ville.vouti=
lainen@gmail.com>
> wrote:
>
> In addition to that, a variant for which the main design goal is to
> desperately
> avoid the cases where a variant is invalid, default-constructing to an
> invalid
> state would semi-obviously defeat that goal.
>
>
> The feeling of desperation is a bad sign, that the architecture might be
> overconstrained.
In case every word is going to be taken out of context, "desperately"
in the sense
of "as far as possible, given that double buffering is not used", so
there are going
to be situations where that variant ends up being invalid, and those situat=
ions
are attempted to be avoided, by design.
> Nicol mentioned GSL not_null as evidence of the advantage of avoiding nul=
l
> values. Why not spell a non-nullable variant as not_null<variant<T...>>?
In order to make it a type that's not horrible to use, or doesn't immediate=
ly
require an alias to be remotely palatable?
> The fact that it also allows
> the N4542 variant to be used as a map key and support map's operator[]
> happens to be a nice bonus,
>
> But, default construction followed by assignment isn=E2=80=99t always as =
good as
> construction with a value in the first place. map<T, variant> would behav=
e
> ever so slightly differently from map<T, optional>. See my earlier exampl=
e
I said key, not value. Other than that, sure, although I don't see
what point you're
trying to make.
> That's also why
> I find it absurd to state defaultconstructibility of a variant as
> absurd,
>
> I agree that non-absurd arguments exist for most of the alternatives. Thi=
s
> debate could use a healthy dose of well-researched writeups on the design
> space (not only specs of single implementations). Passions are running hi=
gh,
> and while this thread might (or might not) help to inform its participant=
s,
> there are more folks in the community who are probably interested to lear=
n
> about the alternatives. It sounds like the committee is spending a
> disproportionate amount of time on topics which are esoteric to the publi=
c,
> but on which the community could possibly find more consensus if the deba=
te
> outside the meetings had more cohesion.
I don't see how you come to such a conclusion about what the committee
is spending
its time on.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 28 Sep 2015 16:08:23 +0800
Raw View
--Apple-Mail=_FF2C71C0-D50A-4F46-A047-71B460FDF397
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9328, at 3:51 PM, Ville Voutilainen <ville.vouti=
lainen@gmail.com> wrote:
>=20
>> The feeling of desperation is a bad sign, that the architecture might be
>> overconstrained.
>=20
> In case every word is going to be taken out of context, "desperately"
> in the sense
> of "as far as possible, given that double buffering is not used", so
> there are going
> to be situations where that variant ends up being invalid, and those situ=
ations
> are attempted to be avoided, by design.
Still sounds like conflicting constraints.
>> Nicol mentioned GSL not_null as evidence of the advantage of avoiding nu=
ll
>> values. Why not spell a non-nullable variant as not_null<variant<T...>>?
>=20
> In order to make it a type that's not horrible to use, or doesn't immedia=
tely
> require an alias to be remotely palatable?
How many types do you put into a variant (or a tuple) before declaring a ty=
pedef? Does any sort of reasonable program spell it out at every use?
> I don't see how you come to such a conclusion about what the committee
> is spending
> its time on.
Just based on what you and Nevin recently said, and the records in the offi=
cial proposals so far.
My point isn=E2=80=99t about conference time allocation, it=E2=80=99s about=
making debates like this one more productive. I hope that the main partici=
pants here will follow up, one way or another, and attempt to post some rea=
dable, impartial analysis. Better education should help to build consensus =
faster.
--=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/.
--Apple-Mail=_FF2C71C0-D50A-4F46-A047-71B460FDF397
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9328, at 3:51 PM, Ville Voutilainen <<a href=3D"mailto:ville.vout=
ilainen@gmail.com" class=3D"">ville.voutilainen@gmail.com</a>> wrote:</d=
iv><br class=3D"Apple-interchange-newline"><div class=3D""><blockquote type=
=3D"cite" class=3D"">The feeling of desperation is a bad sign, that the arc=
hitecture might be<br class=3D"">overconstrained.<br class=3D""></blockquot=
e><br class=3D"">In case every word is going to be taken out of context, "d=
esperately"<br class=3D"">in the sense<br class=3D"">of "as far as possible=
, given that double buffering is not used", so<br class=3D"">there are goin=
g<br class=3D"">to be situations where that variant ends up being invalid, =
and those situations<br class=3D"">are attempted to be avoided, by design.<=
br class=3D""></div></blockquote><div><br class=3D""></div><div>Still sound=
s like conflicting constraints.</div><br class=3D""><blockquote type=3D"cit=
e" class=3D""><div class=3D""><blockquote type=3D"cite" class=3D"">Nicol me=
ntioned GSL not_null as evidence of the advantage of avoiding null<br class=
=3D"">values. Why not spell a non-nullable variant as not_null<variant&l=
t;T...>>?<br class=3D""></blockquote><br class=3D"">In order to make =
it a type that's not horrible to use, or doesn't immediately<br class=3D"">=
require an alias to be remotely palatable?<br class=3D""></div></blockquote=
><div><br class=3D""></div><div>How many types do you put into a <font face=
=3D"Courier" class=3D"">variant</font> (or a <font face=3D"Courier" cl=
ass=3D"">tuple</font>) before declaring a typedef? Does any sort of reasona=
ble program spell it out at every use?</div><br class=3D""><blockquote type=
=3D"cite" class=3D""><div class=3D"">I don't see how you come to such a con=
clusion about what the committee<br class=3D"">is spending<br class=3D"">it=
s time on.<br class=3D""></div></blockquote></div><br class=3D""><div class=
=3D"">Just based on what you and Nevin recently said, and the records in th=
e official proposals so far.</div><div class=3D""><br class=3D""></div><div=
class=3D"">My point isn=E2=80=99t about conference time allocation, it=E2=
=80=99s about making debates like this one more productive. I hope that the=
main participants here will follow up, one way or another, and attempt to =
post some readable, impartial analysis. Better education should help to bui=
ld consensus faster.</div><div class=3D""><br class=3D""></div></body></htm=
l>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_FF2C71C0-D50A-4F46-A047-71B460FDF397--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 11:19:33 +0300
Raw View
On 28 September 2015 at 11:08, David Krauss <potswa@gmail.com> wrote:
> In case every word is going to be taken out of context, "desperately"
> in the sense
> of "as far as possible, given that double buffering is not used", so
> there are going
> to be situations where that variant ends up being invalid, and those
> situations
> are attempted to be avoided, by design.
>
> Still sounds like conflicting constraints.
Well, at the risk of considering that almost everything in this
variant is a trade-off
of some sort, what conflicting constraints are you talking about? If you th=
ink
that default-constructing to a non-invalid state for a variant that
has an invalid
state is a conflict, I would not agree - it's a trade-off, not a conflict.
> Nicol mentioned GSL not_null as evidence of the advantage of avoiding nul=
l
> values. Why not spell a non-nullable variant as not_null<variant<T...>>?
>
> In order to make it a type that's not horrible to use, or doesn't
> immediately
> require an alias to be remotely palatable?
>
> How many types do you put into a variant (or a tuple) before declaring a
> typedef? Does any sort of reasonable program spell it out at every use?
Many, and yes.
> I don't see how you come to such a conclusion about what the committee
> is spending
> its time on.
>
> Just based on what you and Nevin recently said, and the records in the
> official proposals so far.
In other words, you made conclusions that aren't based on evidence, but are
merely your misunderstandings.
> My point isn=E2=80=99t about conference time allocation, it=E2=80=99s abo=
ut making debates
> like this one more productive. I hope that the main participants here wil=
l
> follow up, one way or another, and attempt to post some readable, imparti=
al
> analysis. Better education should help to build consensus faster.
Such an impartial analysis would be great, but unfortunately I haven't had =
time
to write a yet-another rumination paper. :)
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Mon, 28 Sep 2015 09:26:25 +0100
Raw View
On 28/09/15 09:19, Ville Voutilainen wrote:
> On 28 September 2015 at 11:08, David Krauss <potswa@gmail.com> wrote:
>> My point isn=E2=80=99t about conference time allocation, it=E2=80=99s ab=
out making debates
>> like this one more productive. I hope that the main participants here wi=
ll
>> follow up, one way or another, and attempt to post some readable, impart=
ial
>> analysis. Better education should help to build consensus faster.
>=20
> Such an impartial analysis would be great, but unfortunately I haven't ha=
d time
> to write a yet-another rumination paper. :)
>=20
I have submitted a paper describing the requirements for providing the
strong guarantee for assignment, as outlined in my previous emails.
I've also submitted a paper proposing allowing constexpr access to the
common initial sequence of a union, to allow slightly better space
optimizations for variant.
Anthony
--=20
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Sep 2015 11:31:31 +0300
Raw View
On 28 September 2015 at 11:26, Anthony Williams <anthony.ajw@gmail.com> wrote:
> I have submitted a paper describing the requirements for providing the
> strong guarantee for assignment, as outlined in my previous emails.
You practically mean a description of what you have implemented? That's nice, we
will have concrete alternatives to discuss. I have some plans to curb
and curtail the discussion
somewhat, but I'll reveal those plans in Kona. ;)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 28 Sep 2015 16:33:51 +0800
Raw View
--Apple-Mail=_E289EF2B-B23D-4A4B-897B-F68220158FC1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9328, at 4:19 PM, Ville Voutilainen <ville.vouti=
lainen@gmail.com> wrote:
>=20
> Well, at the risk of considering that almost everything in this
> variant is a trade-off
> of some sort, what conflicting constraints are you talking about? If you =
think
> that default-constructing to a non-invalid state for a variant that
> has an invalid
> state is a conflict, I would not agree - it's a trade-off, not a conflict=
..
That=E2=80=99s a subjective call. It seems we understand each other well en=
ough.
>> How many types do you put into a variant (or a tuple) before declaring a
>> typedef? Does any sort of reasonable program spell it out at every use?
>=20
> Many, and yes.
So writing several types in the parameter list and remembering their order =
is OK, but putting one more identifier before =E2=80=9Cvariant=E2=80=9D is =
horrible?
Whatever. This is also too subjective to debate further. It=E2=80=99s true,=
adaptors aren=E2=80=99t as nice as native classes. (They should work bette=
r than they do, and there are core language features that would help.)
> In other words, you made conclusions that aren't based on evidence, but a=
re
> merely your misunderstandings.
I=E2=80=99m only mortal.
> Such an impartial analysis would be great, but unfortunately I haven't ha=
d time
> to write a yet-another rumination paper. :)
It=E2=80=99s nice when you write them, but you=E2=80=99re also only mortal.=
:)
--=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/.
--Apple-Mail=_E289EF2B-B23D-4A4B-897B-F68220158FC1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9328, at 4:19 PM, Ville Voutilainen <<a href=3D"mailto:ville.vout=
ilainen@gmail.com" class=3D"">ville.voutilainen@gmail.com</a>> wrote:</d=
iv><br class=3D"Apple-interchange-newline"><div class=3D"">Well, at the ris=
k of considering that almost everything in this<br class=3D"">variant is a =
trade-off<br class=3D"">of some sort, what conflicting constraints are you =
talking about? If you think<br class=3D"">that default-constructing to a no=
n-invalid state for a variant that<br class=3D"">has an invalid<br class=3D=
"">state is a conflict, I would not agree - it's a trade-off, not a conflic=
t.<br class=3D""></div></blockquote><div><br class=3D""></div><div>That=E2=
=80=99s a subjective call. It seems we understand each other well enough.</=
div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><bl=
ockquote type=3D"cite" class=3D"">How many types do you put into a variant =
(or a tuple) before declaring a<br class=3D"">typedef? Does any sort of rea=
sonable program spell it out at every use?<br class=3D""></blockquote><br c=
lass=3D"">Many, and yes.<br class=3D""></div></blockquote><div><br class=3D=
""></div><div>So writing several types in the parameter list and rememberin=
g their order is OK, but putting one more identifier before =E2=80=9C<font =
face=3D"Courier" class=3D"">variant</font>=E2=80=9D is horrible?</div><div>=
<br class=3D""></div><div>Whatever. This is also too subjective to debate f=
urther. It=E2=80=99s true, adaptors aren=E2=80=99t as nice as native classe=
s. (They <i class=3D"">should</i> work better than they do, and there are c=
ore language features that would help.)</div><br class=3D""><blockquote typ=
e=3D"cite" class=3D""><div class=3D"">In other words, you made conclusions =
that aren't based on evidence, but are<br class=3D"">merely your misunderst=
andings.<br class=3D""></div></blockquote><div><br class=3D""></div><div>I=
=E2=80=99m only mortal.</div><br class=3D""><blockquote type=3D"cite" class=
=3D""><div class=3D"">Such an impartial analysis would be great, but unfort=
unately I haven't had time<br class=3D"">to write a yet-another rumination =
paper. :)<br class=3D""></div></blockquote></div><br class=3D""><div class=
=3D"">It=E2=80=99s nice when you write them, but you=E2=80=99re also only m=
ortal. :)</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_E289EF2B-B23D-4A4B-897B-F68220158FC1--
.
Author: Peter Koch Larsen <peter.koch.larsen@gmail.com>
Date: Mon, 28 Sep 2015 12:46:51 +0200
Raw View
I do not understand why it should be so difficult to achieve the
strong guarantee for a variant, but I hope that you could enlighten be
about the problem?
In my understanding, if a variant element is nothrow move
constructible, you simply move the argument in. My humble guess is
that the move will be valid in the vast majority of cases.
If you can't move without the risk of throwing. you need to resort to
dynamic storage. This could be a double-buffer or simply by storing a
T* instead of a T for such types.
If you need the cadillac version, you could even have that as a
user-option so that we who dislike empty variants might have a say
when creating our code.
(I would also like a Ferrari version, where I could opt-in for dynamic
allocation if one of my elements was of a significant size - e.g.
variant<char,int,float,double,std::array<double,10000>>).
/Peter
On Sat, Sep 26, 2015 at 9:55 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 26 September 2015 at 14:44, Nicol Bolas <jmckesson@gmail.com> wrote:
>>
>>
>> I prefer never empty with the strong guarantee.
>
>
> None of the proposals give you that, as you'd have to pessimize assignment
> to the already engaged type to achieve it. Of the proposals talked about
> here, Williams.Variant comes closest to this.
> --
> Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Peter Koch Larsen <peter.koch.larsen@gmail.com>
Date: Mon, 28 Sep 2015 12:56:43 +0200
Raw View
Sorry, but I am not one of those programmers. I would expect v1 to equal v2.
Even if you consider a variant to be a container, how about
std::array? std::array can not be empty.
/Peter
On Sun, Sep 27, 2015 at 4:58 AM, Andrew Tomazos <andrewtomazos@gmail.com> wrote:
> On Sun, Sep 27, 2015 at 4:45 AM, Nevin Liber <nevin@eviloverlord.com> wrote:
>>
>>
>> On 26 September 2015 at 21:34, Andrew Tomazos <andrewtomazos@gmail.com>
>> wrote:
>>>
>>> I'm just using the above example to illustrate why an exactly-one variant
>>> default constructing the first type is surprising.
>>
>>
>> In other words, you don't want it default constructible because of a
>> feature that is not being proposed in any of the current variant proposals
>> and got rejected from earlier versions of N4542.
>>
>
> Let me clarify my claim.
>
> *IF* the following code compiles:
>
> struct L { ... };
> struct R { ... };
>
> using V = std::variant<L, R>;
>
> V v1;
> V v2(emplace<L>);
> V v3(emplace<R>);
>
> *THEN* most programmers will expect that v1, v2 and v3 have three distinct
> values.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 08:48:55 -0700 (PDT)
Raw View
------=_Part_408_1797682901.1443455335383
Content-Type: multipart/alternative;
boundary="----=_Part_409_1652243043.1443455335383"
------=_Part_409_1652243043.1443455335383
Content-Type: text/plain; charset=UTF-8
On Monday, September 28, 2015 at 6:46:54 AM UTC-4, Peter Koch Larsen wrote:
>
> I do not understand why it should be so difficult to achieve the
> strong guarantee for a variant, but I hope that you could enlighten be
> about the problem?
>
> In my understanding, if a variant element is nothrow move
> constructible, you simply move the argument in.
Yes, that's true. But the problem is, and always has been, with types that
are *not* no-throw move constructible.
If your types are well-behaved, then so too is `variant`. But we can't have
`variant` be broken or have a restricted interface if your types aren't
well-behaved. After all, not all standard library types are no-throw move
constructible (though hopefully we can get progress on *that* front). You
can't say that `variant<std::list<T>, ...)` is a lesser species of
`variant` than `variant<std::vector<T>, ...)`.
So `variant` has to be able to reasonably deal with less well-behaved types.
My humble guess is
> that the move will be valid in the vast majority of cases.
> If you can't move without the risk of throwing. you need to resort to
> dynamic storage.
Not everyone agrees with that. And those who don't have just as much of a
right to a value-type `variant`.
This could be a double-buffer or simply by storing a
> T* instead of a T for such types.
>
Ville already slammed down on the latter as being unacceptable. And I have
to agree; dynamic allocation, *especially* without some form of `allocator`
support, should be a non-starter. Even moreso if it's up to the
implementation to decide when it is necessary (and I have no idea how you
would enforce such an implementation through behavior). If you want dynamic
allocated memory in your `variant`, feel free to put a `unique_ptr<T>` in
the typelist.
The case of double-buffering is for some people legitimately acceptable,
especially given Williams's implementation that proves that it will only
happen when necessary and to a minimal extent. Others consider it to be
heresy of the highest order that a `variant` could ever exceed the size of
a union+byte. But I've never understood why it's so important that the size
of a `variant` be so limited.
Nobody decided that sizeof(std::list<T>)` must be sizeof(void*) or
something. Nobody said that sizeof(std::vector<T>) must be exactly 3
pointers in size. Quality of Implementation is a thing and I'm fine with
allowing some variance 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_409_1652243043.1443455335383
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, September 28, 2015 at 6:46:54 AM UTC-4, Peter K=
och Larsen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I do not unde=
rstand why it should be so difficult to achieve the
<br>strong guarantee for a variant, but I hope that you could enlighten be
<br>about the problem?
<br>
<br>In my understanding, if a variant element is nothrow move
<br>constructible, you simply move the argument in.</blockquote><div><br>Ye=
s, that's true. But the problem is, and always has been, with types tha=
t are <i>not</i> no-throw move constructible.<br><br>If your types are well=
-behaved, then so too is `variant`. But we can't have `variant` be brok=
en or have a restricted interface if your types aren't well-behaved. Af=
ter all, not all standard library types are no-throw move constructible (th=
ough hopefully we can get progress on <i>that</i> front). You can't say=
that `variant<std::list<T>, ...)` is a lesser species of `variant=
` than `variant<std::vector<T>, ...)`.<br><br>So `variant` has to =
be able to reasonably deal with less well-behaved types.<br><br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">My humble guess is
<br>that the move will be valid in the vast majority of cases.
<br>If you can't move without the risk of throwing. you need to resort =
to
<br>dynamic storage. </blockquote><div><br>Not everyone agrees with that. A=
nd those who don't have just as much of a right to a value-type `varian=
t`.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">This could be=
a double-buffer or simply by storing a
<br>T* instead of a T for such types.
<br></blockquote><div><br>Ville already slammed down on the latter as being=
unacceptable. And I have to agree; dynamic allocation, <i>especially</i> w=
ithout some form of `allocator` support, should be a non-starter. Even more=
so if it's up to the implementation to decide when it is necessary (and=
I have no idea how you would enforce such an implementation through behavi=
or). If you want dynamic allocated memory in your `variant`, feel free to p=
ut a `unique_ptr<T>` in the typelist.<br><br>The case of double-buffe=
ring is for some people legitimately acceptable, especially given Williams&=
#39;s implementation that proves that it will only happen when necessary an=
d to a minimal extent. Others consider it to be heresy of the highest order=
that a `variant` could ever exceed the size of a union+byte. But I've =
never understood why it's so important that the size of a `variant` be =
so limited.<br><br>Nobody decided that sizeof(std::list<T>)` must be =
sizeof(void*) or something. Nobody said that sizeof(std::vector<T>) m=
ust be exactly 3 pointers in size. Quality of Implementation is a thing and=
I'm fine with allowing some variance on this.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_409_1652243043.1443455335383--
------=_Part_408_1797682901.1443455335383--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 09:13:24 -0700 (PDT)
Raw View
------=_Part_2037_2077342111.1443456804858
Content-Type: multipart/alternative;
boundary="----=_Part_2038_380651365.1443456804859"
------=_Part_2038_380651365.1443456804859
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 28, 2015 at 3:03:26 AM UTC-4, David Krauss wrote:
>
> On 2015=E2=80=9309=E2=80=9328, at 2:22 PM, Ville Voutilainen <ville.vo...=
@gmail.com=20
> <javascript:>> wrote:
>
> In addition to that, a variant for which the main design goal is to=20
> desperately
> avoid the cases where a variant is invalid, default-constructing to an=20
> invalid
> state would semi-obviously defeat that goal.=20
>
>
> The feeling of desperation is a bad sign, that the architecture might be=
=20
> overconstrained.
>
It's more a sign of basic problems in C++, that's copy/moving/emplacing=20
objects within other objects has problems that cannot be easily dealt with.=
=20
Even destructive move that's implicitly no-throw wouldn't solve it. So long=
=20
as there exist types that cannot be destructively moved, the problem will=
=20
persist.
The validity feature of N4542 is simply one of the alternatives for solving=
=20
the overall problem while still having a "never-empty" variant. The=20
available solutions that retain never-empty status are:
1) Double buffering in the variant. Williams shows that this can be=20
restricted only to where it is *absolutely necessary*, and only to the=20
*extent* that it is absolutely necessary.
2) Allow dynamic allocation in the variant.
3) Use an invalid state in the variant, but one which can *only* be reached=
=20
due to a construction/assignment/etc failure, not through standard=20
operations (like default construction).
4) Give no real exception guarantees in variant.
The C++ language simply doesn't give us any more options for this. So long=
=20
as throwing-move objects exist, we have to either pick one of these or lose=
=20
never-empty.
Personally, I'm in favor #1, but #3 is acceptable if the "variant must=20
never be bigger than union!" people cannot be placated by #1. And #2 is off=
=20
the table.
And losing never-empty has problems, as outlined:
=20
> Nicol mentioned GSL not_null as evidence of the advantage of avoiding=20
> null values. Why not spell a non-nullable variant as=20
> not_null<variant<T...>>?
>
Oh, that's easy; you can't visit a `not_null<variant<Ts...>>`. You can only=
=20
visit the `variant` contained within.
Which means it comes back to that question: does the visitation function=20
require you to statically account for all possible states, including the=20
empty state?
If so, then you force users of "not-null variants" to check for a state=20
that is statically not supposed to be possible. And this also limits what=
=20
can be done in a visitation class, since if you're returning a value, you=
=20
have to be able to return a value even if the `variant` doesn't contain=20
something. Even if there's nothing you can do. So you have to return a=20
value or throw an exception.
In a function that, again, *statically* should never be called.
And if visitation doesn't check the empty state... you've lost crucial=20
static verification. Visitors may *accidentally* forget to check the empty=
=20
state, which would only be evident in the event that an empty variant is=20
actually visited by them. Unlike static checking which would error at=20
compile time, this is a runtime-only check.
And because it's runtime, it may not be encountered until the code ships.=
=20
Oops...
That's the advantage of a never-empty variant. If such a variant is given=
=20
an explicit "empty" state, then visitation statically verifies that you=20
have checked that state in your visitors. If it is not given one, then your=
=20
visitor classes don't have to check it.
Also, if the "empty" state of `variant` is used when a constructor fails,=
=20
then any time such a modification fails, you basically break the `not_null`=
=20
precodition. And you do so in a way that `not_null` doesn't know anything=
=20
about.
The biggest problem with an empty-able variant is that it is empty-able.=20
And therefore, if you needed one that cannot be empty, there's *nothing*=20
you can do about it except write your own class. Whereas, if you have a=20
never-empty variant, you can make it empty-able by giving it an empty state=
..
In one case, both sides get what they need. In the other case, only one=20
side gets what they need.
Why pick the option that punishes one side, rather than the one which=20
punishes no one?
--=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_2038_380651365.1443456804859
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, September 28, 2015 at 3:03:26 AM UTC-4, David K=
rauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word=
-wrap:break-word"><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=
=80=9328, at 2:22 PM, Ville Voutilainen <<a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"w4Ix7SKXCQAJ" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hre=
f=3D'javascript:';return true;">ville.vo...@gmail.com</a>> wrote=
:</div><br><div>In addition to that, a variant for which the main design go=
al is to desperately<br>avoid the cases where a variant is invalid, default=
-constructing to an invalid<br>state would semi-obviously defeat that goal.=
</div></blockquote><div><br></div><div>The feeling of desperation is a bad=
sign, that the architecture might be overconstrained.</div></div></div></b=
lockquote><div><br>It's more a sign of basic problems in C++, that'=
s copy/moving/emplacing objects within other objects has problems that cann=
ot be easily dealt with. Even destructive move that's implicitly no-thr=
ow wouldn't solve it. So long as there exist types that cannot be destr=
uctively moved, the problem will persist.<br><br>The validity feature of N4=
542 is simply one of the alternatives for solving the overall problem while=
still having a "never-empty" variant. The available solutions th=
at retain never-empty status are:<br><br>1) Double buffering in the variant=
.. Williams shows that this can be restricted only to where it is <i>absolut=
ely necessary</i>, and only to the <i>extent</i> that it is absolutely nece=
ssary.<br><br>2) Allow dynamic allocation in the variant.<br><br>3) Use an =
invalid state in the variant, but one which can <i>only</i> be reached due =
to a construction/assignment/etc failure, not through standard operations (=
like default construction).<br><br>4) Give no real exception guarantees in =
variant.<br><br>The C++ language simply doesn't give us any more option=
s for this. So long as throwing-move objects exist, we have to either pick =
one of these or lose never-empty.<br><br>Personally, I'm in favor #1, b=
ut #3 is acceptable if the "variant must never be bigger than union!&q=
uot; people cannot be placated by #1. And #2 is off the table.<br><br>And l=
osing never-empty has problems, as outlined:<br>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div=
>Nicol mentioned GSL <font face=3D"Courier">not_null</font>=C2=A0as evidenc=
e of the advantage of avoiding null values. Why not spell a non-nullable va=
riant as <font face=3D"Courier">not_null<variant<T...>></font>?=
</div></div></div></blockquote><div><br>Oh, that's easy; you can't =
visit a `not_null<variant<Ts...>>`. You can only visit the `var=
iant` contained within.<br><br>Which means it comes back to that question: =
does the visitation function require you to statically account for all poss=
ible states, including the empty state?<br><br>If so, then you force users =
of "not-null variants" to check for a state that is statically no=
t supposed to be possible. And this also limits what can be done in a visit=
ation class, since if you're returning a value, you have to be able to =
return a value even if the `variant` doesn't contain something. Even if=
there's nothing you can do. So you have to return a value or throw an =
exception.<br><br>In a function that, again, <i>statically</i> should never=
be called.<br><br>And if visitation doesn't check the empty state... y=
ou've lost crucial static verification. Visitors may <i>accidentally</i=
> forget to check the empty state, which would only be evident in the event=
that an empty variant is actually visited by them. Unlike static checking =
which would error at compile time, this is a runtime-only check.<br><br>And=
because it's runtime, it may not be encountered until the code ships. =
Oops...<br><br>That's the advantage of a never-empty variant. If such a=
variant is given an explicit "empty" state, then visitation stat=
ically verifies that you have checked that state in your visitors. If it is=
not given one, then your visitor classes don't have to check it.<br><b=
r>Also, if the "empty" state of `variant` is used when a construc=
tor fails, then any time such a modification fails, you basically break the=
`not_null` precodition. And you do so in a way that `not_null` doesn't=
know anything about.<br><br>The biggest problem with an empty-able variant=
is that it is empty-able. And therefore, if you needed one that cannot be =
empty, there's <i>nothing</i> you can do about it except write your own=
class. Whereas, if you have a never-empty variant, you can make it empty-a=
ble by giving it an empty state.<br><br>In one case, both sides get what th=
ey need. In the other case, only one side gets what they need.</div><br>Why=
pick the option that punishes one side, rather than the one which punishes=
no one?<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_2038_380651365.1443456804859--
------=_Part_2037_2077342111.1443456804858--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 09:38:53 -0700 (PDT)
Raw View
------=_Part_705_575101116.1443458334070
Content-Type: multipart/alternative;
boundary="----=_Part_706_1157537600.1443458334071"
------=_Part_706_1157537600.1443458334071
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 28, 2015 at 4:26:30 AM UTC-4, Anthony Williams wrote:
>
> On 28/09/15 09:19, Ville Voutilainen wrote:=20
> > On 28 September 2015 at 11:08, David Krauss <pot...@gmail.com=20
> <javascript:>> wrote:=20
> >> My point isn=E2=80=99t about conference time allocation, it=E2=80=99s =
about making=20
> debates=20
> >> like this one more productive. I hope that the main participants here=
=20
> will=20
> >> follow up, one way or another, and attempt to post some readable,=20
> impartial=20
> >> analysis. Better education should help to build consensus faster.=20
> >=20
> > Such an impartial analysis would be great, but unfortunately I haven't=
=20
> had time=20
> > to write a yet-another rumination paper. :)=20
> >=20
>
> I have submitted a paper describing the requirements for providing the=20
> strong guarantee for assignment, as outlined in my previous emails.
>
I had a thought about that.
The mechanism you described was ultimately based on the presence of nothrow=
=20
move construction. While that's good, I think we can do better:
Instead, base it on the presence of nothrow *swap*.
The Core Guidelines mentioned that many standard library types assume=20
no-throw swappable, and therefore do not behave well in the presence of a=
=20
throwing swap. And while many standard library types are not nothrow=20
moveable, they *all* are nothrow swappable.
Also, std::swap, for types that don't implement their own overload, is=20
noexcept if the type is noexcept moveable (both construction and=20
assignment). So for the most part, the guarantee is the same.
While there are legitimate reasons why a type will have to have a=20
throwing-move, I doubt there are types that cannot implement a noexcept=20
`swap` operation. So if you base your plan on `swap`, you can dramatically=
=20
decrease the number of types that can cause overhead.
Ideally to zero ;)
--=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_706_1157537600.1443458334071
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 28, 2015 at 4:26:30 AM UTC-4, Anthony Williams=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 28/09/15 09:19, Vill=
e Voutilainen wrote:
<br>> On 28 September 2015 at 11:08, David Krauss <<a href=3D"javascr=
ipt:" target=3D"_blank" gdf-obfuscated-mailto=3D"DfogW6ubCQAJ" rel=3D"nofol=
low" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=
=3D"this.href=3D'javascript:';return true;">pot...@gmail.com</a>>=
; wrote:
<br>>> My point isn=E2=80=99t about conference time allocation, it=E2=
=80=99s about making debates
<br>>> like this one more productive. I hope that the main participan=
ts here will
<br>>> follow up, one way or another, and attempt to post some readab=
le, impartial
<br>>> analysis. Better education should help to build consensus fast=
er.
<br>>=20
<br>> Such an impartial analysis would be great, but unfortunately I hav=
en't had time
<br>> to write a yet-another rumination paper. :)
<br>>=20
<br>
<br>I have submitted a paper describing the requirements for providing the
<br>strong guarantee for assignment, as outlined in my previous emails.<br>=
</blockquote><div><br>I had a thought about that.<br><br>The mechanism you =
described was ultimately based on the presence of nothrow move construction=
.. While that's good, I think we can do better:<br><br>Instead, base it =
on the presence of nothrow <i>swap</i>.<br><br>The Core Guidelines mentione=
d that many standard library types assume no-throw swappable, and therefore=
do not behave well in the presence of a throwing swap. And while many stan=
dard library types are not nothrow moveable, they <i>all</i> are nothrow sw=
appable.<br><br>Also, std::swap, for types that don't implement their o=
wn overload, is noexcept if the type is noexcept moveable (both constructio=
n and assignment). So for the most part, the guarantee is the same.<br><br>=
While there are legitimate reasons why a type will have to have a throwing-=
move, I doubt there are types that cannot implement a noexcept `swap` opera=
tion. So if you base your plan on `swap`, you can dramatically decrease the=
number of types that can cause overhead.<br><br>Ideally to zero ;)<br></di=
v>
<p></p>
-- <br />
<br />
--- <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 />
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_706_1157537600.1443458334071--
------=_Part_705_575101116.1443458334070--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 09:43:31 -0700 (PDT)
Raw View
------=_Part_4576_41324025.1443458611523
Content-Type: multipart/alternative;
boundary="----=_Part_4577_1096134287.1443458611523"
------=_Part_4577_1096134287.1443458611523
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 28, 2015 at 12:38:54 PM UTC-4, Nicol Bolas wrote:
>
>
>
> On Monday, September 28, 2015 at 4:26:30 AM UTC-4, Anthony Williams wrote=
:
>>
>> On 28/09/15 09:19, Ville Voutilainen wrote:=20
>> > On 28 September 2015 at 11:08, David Krauss <pot...@gmail.com> wrote:=
=20
>> >> My point isn=E2=80=99t about conference time allocation, it=E2=80=99s=
about making=20
>> debates=20
>> >> like this one more productive. I hope that the main participants here=
=20
>> will=20
>> >> follow up, one way or another, and attempt to post some readable,=20
>> impartial=20
>> >> analysis. Better education should help to build consensus faster.=20
>> >=20
>> > Such an impartial analysis would be great, but unfortunately I haven't=
=20
>> had time=20
>> > to write a yet-another rumination paper. :)=20
>> >=20
>>
>> I have submitted a paper describing the requirements for providing the=
=20
>> strong guarantee for assignment, as outlined in my previous emails.
>>
>
> I had a thought about that.
>
> The mechanism you described was ultimately based on the presence of=20
> nothrow move construction. While that's good, I think we can do better:
>
> Instead, base it on the presence of nothrow *swap*.
>
> The Core Guidelines mentioned that many standard library types assume=20
> no-throw swappable, and therefore do not behave well in the presence of a=
=20
> throwing swap. And while many standard library types are not nothrow=20
> moveable, they *all* are nothrow swappable.
>
> Also, std::swap, for types that don't implement their own overload, is=20
> noexcept if the type is noexcept moveable (both construction and=20
> assignment). So for the most part, the guarantee is the same.
>
> While there are legitimate reasons why a type will have to have a=20
> throwing-move, I doubt there are types that cannot implement a noexcept=
=20
> `swap` operation. So if you base your plan on `swap`, you can dramaticall=
y=20
> decrease the number of types that can cause overhead.
>
> Ideally to zero ;)
>
I just realized that swap requires both objects to be live. So it would=20
only work if there was also a noexcept default constructor for the type as=
=20
well.
So this usually doesn't help, since most objects with throwing moves also=
=20
have throwing default constructors...
--=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_4577_1096134287.1443458611523
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 28, 2015 at 12:38:54 PM UTC-4, Nicol Bolas wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><br><br>On Monday, Septembe=
r 28, 2015 at 4:26:30 AM UTC-4, Anthony Williams wrote:<blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex">On 28/09/15 09:19, Ville Voutilainen wrote:
<br>> On 28 September 2015 at 11:08, David Krauss <<a rel=3D"nofollow=
">pot...@gmail.com</a>> wrote:
<br>>> My point isn=E2=80=99t about conference time allocation, it=E2=
=80=99s about making debates
<br>>> like this one more productive. I hope that the main participan=
ts here will
<br>>> follow up, one way or another, and attempt to post some readab=
le, impartial
<br>>> analysis. Better education should help to build consensus fast=
er.
<br>>=20
<br>> Such an impartial analysis would be great, but unfortunately I hav=
en't had time
<br>> to write a yet-another rumination paper. :)
<br>>=20
<br>
<br>I have submitted a paper describing the requirements for providing the
<br>strong guarantee for assignment, as outlined in my previous emails.<br>=
</blockquote><div><br>I had a thought about that.<br><br>The mechanism you =
described was ultimately based on the presence of nothrow move construction=
.. While that's good, I think we can do better:<br><br>Instead, base it =
on the presence of nothrow <i>swap</i>.<br><br>The Core Guidelines mentione=
d that many standard library types assume no-throw swappable, and therefore=
do not behave well in the presence of a throwing swap. And while many stan=
dard library types are not nothrow moveable, they <i>all</i> are nothrow sw=
appable.<br><br>Also, std::swap, for types that don't implement their o=
wn overload, is noexcept if the type is noexcept moveable (both constructio=
n and assignment). So for the most part, the guarantee is the same.<br><br>=
While there are legitimate reasons why a type will have to have a throwing-=
move, I doubt there are types that cannot implement a noexcept `swap` opera=
tion. So if you base your plan on `swap`, you can dramatically decrease the=
number of types that can cause overhead.<br><br>Ideally to zero ;)<br></di=
v></blockquote><div><br>I just realized that swap requires both objects to =
be live. So it would only work if there was also a noexcept default constru=
ctor for the type as well.<br><br>So this usually doesn't help, since m=
ost objects with throwing moves also have throwing default constructors...<=
br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_4577_1096134287.1443458611523--
------=_Part_4576_41324025.1443458611523--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Mon, 28 Sep 2015 17:47:02 +0100
Raw View
On 28/09/15 17:38, Nicol Bolas wrote:
>=20
>=20
> On Monday, September 28, 2015 at 4:26:30 AM UTC-4, Anthony Williams wrote=
:
>=20
> On 28/09/15 09:19, Ville Voutilainen wrote:
> > On 28 September 2015 at 11:08, David Krauss <pot...@gmail.com
> <javascript:>> wrote:
> >> My point isn=E2=80=99t about conference time allocation, it=E2=80=
=99s about
> making debates
> >> like this one more productive. I hope that the main participants
> here will
> >> follow up, one way or another, and attempt to post some readable,
> impartial
> >> analysis. Better education should help to build consensus faster.
> >
> > Such an impartial analysis would be great, but unfortunately I
> haven't had time
> > to write a yet-another rumination paper. :)
> >
>=20
> I have submitted a paper describing the requirements for providing th=
e
> strong guarantee for assignment, as outlined in my previous emails.
>=20
>=20
> I had a thought about that.
>=20
> The mechanism you described was ultimately based on the presence of
> nothrow move construction. While that's good, I think we can do better:
>=20
> Instead, base it on the presence of nothrow /swap/.
How? Given a variant<A,B,C> that holds an A, how do we assign a C into
it, assuming that A, B and C have nothrow swap, but move constructors
that throw?
To get the C into place using a nothrow swap requires there's already a
C object there to swap with ... but we can't construct a C object
without throwing!
> While there are legitimate reasons why a type will have to have a
> throwing-move, I doubt there are types that cannot implement a noexcept
> `swap` operation. So if you base your plan on `swap`, you can
> dramatically decrease the number of types that can cause overhead.
variant<> is potentially a type without a nothrow swap operation ;-)
Anthony
--=20
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Nevin \":-)\" Liber" <"Nevin ":-)" Liber" <nliber@gmail.com>>
Date: Mon, 28 Sep 2015 12:18:19 -0500
Raw View
--Apple-Mail-E12F432B-9D1F-497C-B017-EA67A5356A64
Content-Type: text/plain; charset=UTF-8
> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> 1) Double buffering in the variant. Williams shows that this can be restricted only to where it is absolutely necessary, and only to the extent that it is absolutely necessary.
Not true. Boost.Variant minimizes double buffering by falling back on a nothrow default constructible type if it can, which Williams.Variant does not.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (312) 623-5420
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--Apple-Mail-E12F432B-9D1F-497C-B017-EA67A5356A64
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html><head><meta http-equiv=3D"content-type" content=3D"text/html; charset=
=3Dutf-8"></head><body dir=3D"auto"><div><br></div><div><br>On Sep 28, 2015=
, at 11:13 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com">jmcke=
sson@gmail.com</a>> wrote:<br><br></div><blockquote type=3D"cite">1) Dou=
ble buffering in the variant. Williams shows that this can be restricted on=
ly to where it is <i>absolutely necessary</i>, and only to the <i>extent</i=
> that it is absolutely necessary.<br></blockquote><br><div><span style=3D"=
background-color: rgba(255, 255, 255, 0);">Not true. Boost.Variant minimize=
s double buffering by falling back on a nothrow default constructible type =
if it can, which Williams.Variant does not.<br>-- </span><div><span st=
yle=3D"background-color: rgba(255, 255, 255, 0);"> Nevin ":-)" Liber &=
lt;<a href=3D"mailto:nevin@eviloverlord.com">mailto:nevin@eviloverlord.com<=
/a>> (312) 623-5420</span></div></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail-E12F432B-9D1F-497C-B017-EA67A5356A64--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 11:19:15 -0700 (PDT)
Raw View
------=_Part_781_96661177.1443464355138
Content-Type: multipart/alternative;
boundary="----=_Part_782_842046365.1443464355139"
------=_Part_782_842046365.1443464355139
Content-Type: text/plain; charset=UTF-8
On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber wrote:
>
> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmck...@gmail.com <javascript:>>
> wrote:
>
> 1) Double buffering in the variant. Williams shows that this can be
> restricted only to where it is *absolutely necessary*, and only to the
> *extent* that it is absolutely necessary.
>
>
> Not true. Boost.Variant minimizes double buffering by falling back on a
> nothrow default constructible type if it can, which Williams.Variant does
> not.
>
Yes, because Williams.Variant is trying to offer a stronger guarantee than
Boost.Variant. The state after a failure in Boost.Variant is undefined; the
state in Williams.Variant is well-specified.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_782_842046365.1443464355139
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin &=
quot;:-)" Liber 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"auto"><div>On Sep 28, 2015, at 11:13 AM, Nicol Bolas <<a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"gW_KgrG4CQAJ" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return tru=
e;" onclick=3D"this.href=3D'javascript:';return true;">jmck...@gmai=
l.com</a>> wrote:</div><blockquote type=3D"cite">1) Double buffering in =
the variant. Williams shows that this can be restricted only to where it is=
<i>absolutely necessary</i>, and only to the <i>extent</i> that it is abso=
lutely necessary.<br></blockquote><br><div><span style=3D"background-color:=
rgba(255,255,255,0)">Not true. Boost.Variant minimizes double buffering by =
falling back on a nothrow default constructible type if it can, which Willi=
ams.Variant does not.<br></span></div></div></blockquote><div><br>Yes, beca=
use Williams.Variant is trying to offer a stronger guarantee than Boost.Var=
iant. The state after a failure in Boost.Variant is undefined; the state in=
Williams.Variant is well-specified.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_782_842046365.1443464355139--
------=_Part_781_96661177.1443464355138--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 11:23:00 -0700 (PDT)
Raw View
------=_Part_4854_200556662.1443464580939
Content-Type: multipart/alternative;
boundary="----=_Part_4855_1793738079.1443464580939"
------=_Part_4855_1793738079.1443464580939
Content-Type: text/plain; charset=UTF-8
On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:
>
> On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber wrote:
>>
>> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>> 1) Double buffering in the variant. Williams shows that this can be
>> restricted only to where it is *absolutely necessary*, and only to the
>> *extent* that it is absolutely necessary.
>>
>>
>> Not true. Boost.Variant minimizes double buffering by falling back on a
>> nothrow default constructible type if it can, which Williams.Variant does
>> not.
>>
>
> Yes, because Williams.Variant is trying to offer a stronger guarantee than
> Boost.Variant. The state after a failure in Boost.Variant is undefined; the
> state in Williams.Variant is well-specified.
>
"Undefined" was the wrong word. It's "valid but unspecified."
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4855_1793738079.1443464580939
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Monday, =
September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber 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"auto"><div>On Sep 28, 20=
15, at 11:13 AM, Nicol Bolas <<a rel=3D"nofollow">jmck...@gmail.com</a>&=
gt; wrote:</div><blockquote type=3D"cite">1) Double buffering in the varian=
t. Williams shows that this can be restricted only to where it is <i>absolu=
tely necessary</i>, and only to the <i>extent</i> that it is absolutely nec=
essary.<br></blockquote><br><div><span style=3D"background-color:rgba(255,2=
55,255,0)">Not true. Boost.Variant minimizes double buffering by falling ba=
ck on a nothrow default constructible type if it can, which Williams.Varian=
t does not.<br></span></div></div></blockquote><div><br>Yes, because Willia=
ms.Variant is trying to offer a stronger guarantee than Boost.Variant. The =
state after a failure in Boost.Variant is undefined; the state in Williams.=
Variant is well-specified.<br></div></div></blockquote><div><br>"Undef=
ined" was the wrong word. It's "valid but unspecified." =
<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_4855_1793738079.1443464580939--
------=_Part_4854_200556662.1443464580939--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 14:29:40 -0400
Raw View
--001a11c3124a70e4b00520d2e160
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>
> On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:
>>
>> On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber
>> wrote:
>>>
>>> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>> 1) Double buffering in the variant. Williams shows that this can be
>>> restricted only to where it is *absolutely necessary*, and only to the
>>> *extent* that it is absolutely necessary.
>>>
>>>
>>> Not true. Boost.Variant minimizes double buffering by falling back on a
>>> nothrow default constructible type if it can, which Williams.Variant does
>>> not.
>>>
>>
>> Yes, because Williams.Variant is trying to offer a stronger guarantee
>> than Boost.Variant. The state after a failure in Boost.Variant is
>> undefined; the state in Williams.Variant is well-specified.
>>
>
> "Undefined" was the wrong word. It's "valid but unspecified."
>
Valid but unspecified, does, however, mean "never empty", which is what
your list was about. So "fallback to nothrow default constructible" should
be included in that list.
It is not my favourite option, but it does give you never empty.
Surprises, maybe, but never empty, no.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c3124a70e4b00520d2e160
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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"><span class=3D""><br>=
<br>On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:<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">On Monday, September=
28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"auto"><div>On Sep 28, 2015, at 11=
:13 AM, Nicol Bolas <<a rel=3D"nofollow">jmck...@gmail.com</a>> wrote=
:</div><blockquote type=3D"cite">1) Double buffering in the variant. Willia=
ms shows that this can be restricted only to where it is <i>absolutely nece=
ssary</i>, and only to the <i>extent</i> that it is absolutely necessary.<b=
r></blockquote><br><div><span style=3D"background-color:rgba(255,255,255,0)=
">Not true. Boost.Variant minimizes double buffering by falling back on a n=
othrow default constructible type if it can, which Williams.Variant does no=
t.<br></span></div></div></blockquote><div><br>Yes, because Williams.Varian=
t is trying to offer a stronger guarantee than Boost.Variant. The state aft=
er a failure in Boost.Variant is undefined; the state in Williams.Variant i=
s well-specified.<br></div></div></blockquote></span><div><br>"Undefin=
ed" was the wrong word. It's "valid but unspecified." <b=
r></div></blockquote><div><br></div></div><br></div><div class=3D"gmail_ext=
ra">Valid but unspecified, does, however, mean "never empty", whi=
ch is what your list was about.=C2=A0 So "fallback to nothrow default =
constructible" should be included in that list.<br></div><div class=3D=
"gmail_extra">It is not my favourite option, but it does give you never emp=
ty.=C2=A0 Surprises, maybe, but never empty, no.<br></div><div class=3D"gma=
il_extra">Tony<br></div><div class=3D"gmail_extra"><br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3124a70e4b00520d2e160--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 14:32:18 -0400
Raw View
--089e0158c00ed24aa70520d2eaa6
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 2:29 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>
> On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>>
>>
>> On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:
>>>
>>> On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber
>>> wrote:
>>>>
>>>> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>>
>>>> 1) Double buffering in the variant. Williams shows that this can be
>>>> restricted only to where it is *absolutely necessary*, and only to the
>>>> *extent* that it is absolutely necessary.
>>>>
>>>>
>>>> Not true. Boost.Variant minimizes double buffering by falling back on a
>>>> nothrow default constructible type if it can, which Williams.Variant does
>>>> not.
>>>>
>>>
>>> Yes, because Williams.Variant is trying to offer a stronger guarantee
>>> than Boost.Variant. The state after a failure in Boost.Variant is
>>> undefined; the state in Williams.Variant is well-specified.
>>>
>>
>> "Undefined" was the wrong word. It's "valid but unspecified."
>>
>
>
> Valid but unspecified, does, however, mean "never empty", which is what
> your list was about. So "fallback to nothrow default constructible" should
> be included in that list.
> It is not my favourite option, but it does give you never empty.
> Surprises, maybe, but never empty, no.
>
grrr. "Surprises, maybe, but empty, no."
> Tony
>
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0158c00ed24aa70520d2eaa6
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 2:29 PM, Tony V E <span dir=3D"ltr"><<a href=
=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.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 cla=
ss=3D""><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Mo=
n, Sep 28, 2015 at 2:23 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"ma=
ilto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><span><br><br>On Monday, Septe=
mber 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:<blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr">On Monday, September 28, 2015 at 1:18:22=
PM UTC-4, Nevin ":-)" Liber wrote:<blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"auto"><div>On Sep 28, 2015, at 11:13 AM, Nicol Bolas =
<<a rel=3D"nofollow">jmck...@gmail.com</a>> wrote:</div><blockquote t=
ype=3D"cite">1) Double buffering in the variant. Williams shows that this c=
an be restricted only to where it is <i>absolutely necessary</i>, and only =
to the <i>extent</i> that it is absolutely necessary.<br></blockquote><br><=
div><span style=3D"background-color:rgba(255,255,255,0)">Not true. Boost.Va=
riant minimizes double buffering by falling back on a nothrow default const=
ructible type if it can, which Williams.Variant does not.<br></span></div><=
/div></blockquote><div><br>Yes, because Williams.Variant is trying to offer=
a stronger guarantee than Boost.Variant. The state after a failure in Boos=
t.Variant is undefined; the state in Williams.Variant is well-specified.<br=
></div></div></blockquote></span><div><br>"Undefined" was the wro=
ng word. It's "valid but unspecified." <br></div></blockquote=
><div><br></div></div><br></div></span><div class=3D"gmail_extra">Valid but=
unspecified, does, however, mean "never empty", which is what yo=
ur list was about.=C2=A0 So "fallback to nothrow default constructible=
" should be included in that list.<br></div><div class=3D"gmail_extra"=
>It is not my favourite option, but it does give you never empty.=C2=A0 Sur=
prises, maybe, but never empty, no.<span class=3D"HOEnZb"><font color=3D"#8=
88888"><br></font></span></div></div></blockquote><div><br></div><div>grrr.=
"Surprises, maybe, but empty, no."<br><br>=C2=A0<br></div><block=
quote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><span =
class=3D"HOEnZb"><font color=3D"#888888"></font></span></div><span class=3D=
"HOEnZb"><font color=3D"#888888"><div class=3D"gmail_extra">Tony<br></div><=
div class=3D"gmail_extra"><br><br></div></font></span></div>
</blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0158c00ed24aa70520d2eaa6--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 11:49:40 -0700 (PDT)
Raw View
------=_Part_79_911096022.1443466180638
Content-Type: multipart/alternative;
boundary="----=_Part_80_1238954056.1443466180639"
------=_Part_80_1238954056.1443466180639
Content-Type: text/plain; charset=UTF-8
On Monday, September 28, 2015 at 2:29:47 PM UTC-4, Tony V E wrote:
>
>
>
> On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>>
>>
>> On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:
>>>
>>> On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber
>>> wrote:
>>>>
>>>> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>>
>>>> 1) Double buffering in the variant. Williams shows that this can be
>>>> restricted only to where it is *absolutely necessary*, and only to the
>>>> *extent* that it is absolutely necessary.
>>>>
>>>>
>>>> Not true. Boost.Variant minimizes double buffering by falling back on a
>>>> nothrow default constructible type if it can, which Williams.Variant does
>>>> not.
>>>>
>>>
>>> Yes, because Williams.Variant is trying to offer a stronger guarantee
>>> than Boost.Variant. The state after a failure in Boost.Variant is
>>> undefined; the state in Williams.Variant is well-specified.
>>>
>>
>> "Undefined" was the wrong word. It's "valid but unspecified."
>>
>
>
> Valid but unspecified, does, however, mean "never empty", which is what
> your list was about. So "fallback to nothrow default constructible" should
> be included in that list.
>
But it's not a *complete* solution, because there may not be a nothrow
default constructible type in the typelist. If there are none, you have to
do *something* safe.
In that case, Boost.Variant resorts to... dynamic memory allocation. So
really, Boost.Variant is just an optimized version of the dynamic
allocation case. Just as Williams.Variant is an optimized version of
double-buffering. Both do the expensive work only when necessary.
It should also be noted that Boost.Variant, even with dynamic allocation,
does not even offer the basic exception guarantee.
Let's say that the current type is Tcurr, and the incoming type is Tin. The
way Boost.Variant is stated to work
<http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty>
is this:
1) Copy-construct the content of the left-hand side to the heap; call the
pointer to this data backup.
2) Destroy the content of the left-hand side.
3) Copy-construct the content of the right-hand side in the (now-empty)
storage of the left-hand side.
4a) In the event of failure, copy backup to the left-hand side storage.
4b) In the event of success, deallocate the data pointed to by backup.
That's copied from the website.
If step 1 fails due to Tcurr's copy constructor, then the variant is in a
valid state (copying is `const` relative to the source object). So
everything is fine. But let's say that Tin's copy-constructor failed at
step 3, so we move to step 4a. And then... Tcurr's copy constructor failed.
Oops.
We already destructed our current value. And our attempt to get it back
failed. So... what are we?
Whereas Williams.Variant can actually handle this, thanks to the double
buffer.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_80_1238954056.1443466180639
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, September 28, 2015 at 2:29:47 PM UTC-4, Tony V E wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><div><br><=
div class=3D"gmail_quote">On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <spa=
n dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-=
mailto=3D"dsGVMJe8CQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'ja=
vascript:';return true;" onclick=3D"this.href=3D'javascript:';r=
eturn true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><span><br><br>On Monday, September 28, 2015 at 2:19:15 PM UTC=
-4, Nicol Bolas 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"l=
tr">On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)"=
; Liber 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"auto"><di=
v>On Sep 28, 2015, at 11:13 AM, Nicol Bolas <<a rel=3D"nofollow">jmck...=
@gmail.com</a>> wrote:</div><blockquote type=3D"cite">1) Double bufferin=
g in the variant. Williams shows that this can be restricted only to where =
it is <i>absolutely necessary</i>, and only to the <i>extent</i> that it is=
absolutely necessary.<br></blockquote><br><div><span style=3D"background-c=
olor:rgba(255,255,255,0)">Not true. Boost.Variant minimizes double bufferin=
g by falling back on a nothrow default constructible type if it can, which =
Williams.Variant does not.<br></span></div></div></blockquote><div><br>Yes,=
because Williams.Variant is trying to offer a stronger guarantee than Boos=
t.Variant. The state after a failure in Boost.Variant is undefined; the sta=
te in Williams.Variant is well-specified.<br></div></div></blockquote></spa=
n><div><br>"Undefined" was the wrong word. It's "valid b=
ut unspecified." <br></div></blockquote><div><br></div></div><br></div=
><div>Valid but unspecified, does, however, mean "never empty", w=
hich is what your list was about.=C2=A0 So "fallback to nothrow defaul=
t constructible" should be included in that list.<br></div></div></blo=
ckquote><div><br>But it's not a <i>complete</i> solution, because there=
may not be a nothrow default constructible type in the typelist. If there =
are none, you have to do <i>something</i> safe.<br><br>In that case, Boost.=
Variant resorts to... dynamic memory allocation. So really, Boost.Variant i=
s just an optimized version of the dynamic allocation case. Just as William=
s.Variant is an optimized version of double-buffering. Both do the expensiv=
e work only when necessary.<br><br>It should also be noted that Boost.Varia=
nt, even with dynamic allocation, does not even offer the basic exception g=
uarantee.<br><br>Let's say that the current type is Tcurr, and the inco=
ming type is Tin. The way <a href=3D"http://www.boost.org/doc/libs/1_59_0/d=
oc/html/variant/design.html#variant.design.never-empty">Boost.Variant is st=
ated to work</a> is this:<br><br>1) Copy-construct the content of the left-=
hand side to the heap; call the pointer to this data backup.<br><br>2) Dest=
roy the content of the left-hand side.<br><br>3) Copy-construct the content=
of the right-hand side in the (now-empty) storage of the left-hand side.<b=
r><br>4a) In the event of failure, copy backup to the left-hand side storag=
e.<br><br>4b) In the event of success, deallocate the data pointed to by ba=
ckup.<br><br>That's copied from the website.<br><br>If step 1 fails due=
to Tcurr's copy constructor, then the variant is in a valid state (cop=
ying is `const` relative to the source object). So everything is fine. But =
let's say that Tin's copy-constructor failed at step 3, so we move =
to step 4a. And then... Tcurr's copy constructor failed.<br><br>Oops.<b=
r><br>We already destructed our current value. And our attempt to get it ba=
ck failed. So... what are we?<br><br>Whereas Williams.Variant can actually =
handle this, thanks to the double buffer.<br></div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;">
</blockquote>
<p></p>
-- <br />
<br />
--- <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 />
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_80_1238954056.1443466180639--
------=_Part_79_911096022.1443466180638--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:10:03 -0400
Raw View
--089e0158c00ed377d60520d371e0
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 10:51 PM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:
>
>
> For what it's worth, there's exactly two approaches that I find
> unacceptable:
> 1) dynamic allocation.
> 2) constraining variant to outright reject types with throwing moves.
>
I think, if pressed, I could even go down to just
1) dynamic allocation
That really is my only over-my-national-body deal-breaker.
(And, of course, relational operators,... just kidding)
YMMV,
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0158c00ed377d60520d371e0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sun, Sep 27, 2015 at 10:51 PM, Ville Voutilainen <span dir=3D"ltr">&=
lt;<a href=3D"mailto:ville.voutilainen@gmail.com" target=3D"_blank">ville.v=
outilainen@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><br>
<br>
For what it's worth, there's exactly two approaches that I find una=
cceptable:<br>
1) dynamic allocation.<br>
2) constraining variant to outright reject types with throwing moves.<br></=
blockquote><div><br></div><div>I think, if pressed, I could even go down to=
just<br><br></div><div>1) dynamic allocation<br><br></div><div>That really=
is my only over-my-national-body deal-breaker.<br></div><div>(And, of cour=
se, relational operators,... just kidding)<br></div><div><br></div>YMMV,<br=
></div>Tony<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0158c00ed377d60520d371e0--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:14:38 -0400
Raw View
--001a11411c3837ecd80520d3827e
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 12:13 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> The available solutions that retain never-empty status are:
>
> 1) Double buffering in the variant. Williams shows that this can be
> restricted only to where it is *absolutely necessary*, and only to the
> *extent* that it is absolutely necessary.
>
> 2) Allow dynamic allocation in the variant.
>
> 3) Use an invalid state in the variant, but one which can *only* be
> reached due to a construction/assignment/etc failure, not through standard
> operations (like default construction).
>
> 4) Give no real exception guarantees in variant.
>
> The C++ language simply doesn't give us any more options for this. So long
> as throwing-move objects exist, we have to either pick one of these or lose
> never-empty.
>
> Personally, I'm in favor #1, but #3 is acceptable if the "variant must
> never be bigger than union!" people cannot be placated by #1. And #2 is off
> the table.
>
>
Me too. #1, else #3. Not 2 or 4: "Four shalt thou not count, neither count
thou two, excepting that thou then proceed to three. Five is right out."
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11411c3837ecd80520d3827e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 12:13 PM, Nicol Bolas <span dir=3D"ltr"><<a =
href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</=
a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><=
div dir=3D"ltr">=C2=A0The available solutions that retain never-empty statu=
s are:<br><div><br>1) Double buffering in the variant. Williams shows that =
this can be restricted only to where it is <i>absolutely necessary</i>, and=
only to the <i>extent</i> that it is absolutely necessary.<br><br>2) Allow=
dynamic allocation in the variant.<br><br>3) Use an invalid state in the v=
ariant, but one which can <i>only</i> be reached due to a construction/assi=
gnment/etc failure, not through standard operations (like default construct=
ion).<br><br>4) Give no real exception guarantees in variant.<br><br>The C+=
+ language simply doesn't give us any more options for this. So long as=
throwing-move objects exist, we have to either pick one of these or lose n=
ever-empty.<br><br>Personally, I'm in favor #1, but #3 is acceptable if=
the "variant must never be bigger than union!" people cannot be =
placated by #1. And #2 is off the table.<br><br></div></div></blockquote></=
div><br></div><div class=3D"gmail_extra">Me too. #1, else #3. Not 2 or 4: &=
quot;Four shalt thou not count, neither count thou two, excepting that thou=
then proceed to three. Five is right out."<br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11411c3837ecd80520d3827e--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 28 Sep 2015 12:14:51 -0700
Raw View
--089e01177341fec3440520d38214
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 11:29 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
>
> On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>>
>>
>> On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:
>>>
>>> On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber
>>> wrote:
>>>>
>>>> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>>
>>>> 1) Double buffering in the variant. Williams shows that this can be
>>>> restricted only to where it is *absolutely necessary*, and only to the
>>>> *extent* that it is absolutely necessary.
>>>>
>>>>
>>>> Not true. Boost.Variant minimizes double buffering by falling back on a
>>>> nothrow default constructible type if it can, which Williams.Variant does
>>>> not.
>>>>
>>>
>>> Yes, because Williams.Variant is trying to offer a stronger guarantee
>>> than Boost.Variant. The state after a failure in Boost.Variant is
>>> undefined; the state in Williams.Variant is well-specified.
>>>
>>
>> "Undefined" was the wrong word. It's "valid but unspecified."
>>
>
>
> Valid but unspecified, does, however, mean "never empty", which is what
> your list was about. So "fallback to nothrow default constructible" should
> be included in that list.
> It is not my favourite option, but it does give you never empty.
> Surprises, maybe, but empty, no.
>
Right. The fallback and double storage options (and boost's dynamic memory
allocation, though I don't think anyone here is too fond of) provide
never-empty guarantees. The thing that differs is that double storage
provides the strong exception guarantee for assignment/emplacement whereas
the fallback type provides only the basic exception guarantee.
Also, maybe this has already been covered, but is the idea, if the
committee were to decide that the strong exception guarantee is very
important for assignment (something I personally disagree with), to use the
double storage option for any copy/move-assignment that can throw, even
when both the left-hand and right-hand operand are the same underlying
field type? It seems like this would ultimately be necessary, otherwise
you'd only be sure to get the strong exception guarantee when the
assignment would change the underlying field type. You'd get whatever
guarantee the *field type* provides when both sides are of the same
underlying field type if you didn't use double storage or copy/move there
too, assuming that the assignment can throw. In that latter case, if the
strong exception guarantee is specified for variant here, we'd have no way
of knowing if the user's field type's assignment operation uses the basic
guarantee or the strong guarantee, unless there are some traits involved,
so we'd have to do the pessimistic thing and just assume that the field
type provides only the basic guarantee, meaning we'd have to double buffer,
or copy construct then move-assign instead of direct copy-assign.
Similarly, what is expected of emplacement? No matter what your field types
are (including all fundamental types), it's possible for a user to invoke
an emplace operation that can throw. Because of this, it seems to me that
when doing emplacement that can throw, you'd need double storage or to
allow copy-construct then move-assign (this latter point is probably not
controversial for types that are trivially
copy-constructible/destructible). Maybe I'm missing an obvious alternative,
though.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e01177341fec3440520d38214
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 M=
on, Sep 28, 2015 at 11:29 AM, Tony V E <span dir=3D"ltr"><<a href=3D"mai=
lto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=
wrote:<br><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-st=
yle:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><br><div clas=
s=3D"gmail_extra"><br><div class=3D"gmail_quote">On Mon, Sep 28, 2015 at 2:=
23 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.=
com" target=3D"_blank">jmckesson@gmail.com</a>></span> wrote:<br><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex"><span><br><br>On Monday, September 28, 2015 at 2:19:15 PM UTC-4, =
Nicol Bolas 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">On Monday, September 28=
, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"><div dir=3D"auto"><div>On Sep 28, 2015, at 11:13 AM, Nicol Bolas <<a=
rel=3D"nofollow">jmck...@gmail.com</a>> wrote:</div><blockquote type=3D=
"cite">1) Double buffering in the variant. Williams shows that this can be =
restricted only to where it is <i>absolutely necessary</i>, and only to the=
<i>extent</i> that it is absolutely necessary.<br></blockquote><br><div><s=
pan style=3D"background-color:rgba(255,255,255,0)">Not true. Boost.Variant =
minimizes double buffering by falling back on a nothrow default constructib=
le type if it can, which Williams.Variant does not.<br></span></div></div><=
/blockquote><div><br>Yes, because Williams.Variant is trying to offer a str=
onger guarantee than Boost.Variant. The state after a failure in Boost.Vari=
ant is undefined; the state in Williams.Variant is well-specified.<br></div=
></div></blockquote></span><div><br>"Undefined" was the wrong wor=
d. It's "valid but unspecified." <br></div></blockquote><div>=
<br></div></div><br></div></span><div class=3D"gmail_extra">Valid but unspe=
cified, does, however, mean "never empty", which is what your lis=
t was about.=C2=A0 So "fallback to nothrow default constructible"=
should be included in that list.<br></div><div class=3D"gmail_extra">It is=
not my favourite option, but it does give you never empty.=C2=A0 Surprises=
, maybe, but empty, no.</div></div></blockquote><div><br></div><div>Right. =
The fallback and double storage options (and boost's dynamic memory all=
ocation, though I don't think anyone here is too fond of) provide never=
-empty guarantees. The thing that differs is that double storage provides t=
he strong exception guarantee for assignment/emplacement whereas the fallba=
ck type provides only the basic exception guarantee.</div><div><br></div><d=
iv>Also, maybe this has already been covered, but is the idea, if the commi=
ttee were to decide that the strong exception guarantee is very important f=
or assignment (something I personally disagree with), to use the double sto=
rage option for any copy/move-assignment that can throw, even when both the=
left-hand and right-hand operand are the same underlying field type? It se=
ems like this would ultimately be necessary, otherwise you'd only be su=
re to get the strong exception guarantee when the assignment would change t=
he underlying field type. You'd get whatever guarantee the *field type*=
provides when both sides are of the same underlying field type if you didn=
't use double storage or copy/move there too, assuming that the assignm=
ent can throw. In that latter case, if the strong exception guarantee is sp=
ecified for variant here, we'd have no way of knowing if the user's=
field type's assignment operation uses the basic guarantee or the stro=
ng guarantee, unless there are some traits involved, so we'd have to do=
the pessimistic thing and just assume that the field type provides only th=
e basic guarantee, meaning we'd have to double buffer, or copy construc=
t then move-assign instead of direct copy-assign.</div><div><br></div><div>=
Similarly, what is expected of emplacement? No matter what your field types=
are (including all fundamental types), it's possible for a user to inv=
oke an emplace operation that can throw. Because of this, it seems to me th=
at when doing emplacement that can throw, you'd need double storage or =
to allow copy-construct then move-assign (this latter point is probably not=
controversial for types that are trivially copy-constructible/destructible=
). Maybe I'm missing an obvious alternative, though.</div></div></div><=
/div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01177341fec3440520d38214--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:14:54 -0400
Raw View
--001a113fb8c02e0fb80520d383aa
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 2:49 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>
> On Monday, September 28, 2015 at 2:29:47 PM UTC-4, Tony V E wrote:
>>
>>
>>
>> On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>>
>>>
>>> On Monday, September 28, 2015 at 2:19:15 PM UTC-4, Nicol Bolas wrote:
>>>>
>>>> On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin ":-)" Liber
>>>> wrote:
>>>>>
>>>>> On Sep 28, 2015, at 11:13 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>>>
>>>>> 1) Double buffering in the variant. Williams shows that this can be
>>>>> restricted only to where it is *absolutely necessary*, and only to
>>>>> the *extent* that it is absolutely necessary.
>>>>>
>>>>>
>>>>> Not true. Boost.Variant minimizes double buffering by falling back on
>>>>> a nothrow default constructible type if it can, which Williams.Variant does
>>>>> not.
>>>>>
>>>>
>>>> Yes, because Williams.Variant is trying to offer a stronger guarantee
>>>> than Boost.Variant. The state after a failure in Boost.Variant is
>>>> undefined; the state in Williams.Variant is well-specified.
>>>>
>>>
>>> "Undefined" was the wrong word. It's "valid but unspecified."
>>>
>>
>>
>> Valid but unspecified, does, however, mean "never empty", which is what
>> your list was about. So "fallback to nothrow default constructible" should
>> be included in that list.
>>
>
> But it's not a *complete* solution, because there may not be a nothrow
> default constructible type in the typelist. If there are none, you have to
> do *something* safe.
>
>
True. So I guess you could use it as a refinement to Williams, where you
likely double buffer less often. (not worth it to me, but it is a valid
option).
> In that case, Boost.Variant resorts to... dynamic memory allocation. So
> really, Boost.Variant is just an optimized version of the dynamic
> allocation case. Just as Williams.Variant is an optimized version of
> double-buffering. Both do the expensive work only when necessary.
>
> It should also be noted that Boost.Variant, even with dynamic allocation,
> does not even offer the basic exception guarantee.
>
> Let's say that the current type is Tcurr, and the incoming type is Tin.
> The way Boost.Variant is stated to work
> <http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty>
> is this:
>
> 1) Copy-construct the content of the left-hand side to the heap; call the
> pointer to this data backup.
>
> 2) Destroy the content of the left-hand side.
>
> 3) Copy-construct the content of the right-hand side in the (now-empty)
> storage of the left-hand side.
>
> 4a) In the event of failure, copy backup to the left-hand side storage.
>
> 4b) In the event of success, deallocate the data pointed to by backup.
>
> That's copied from the website.
>
> If step 1 fails due to Tcurr's copy constructor, then the variant is in a
> valid state (copying is `const` relative to the source object). So
> everything is fine. But let's say that Tin's copy-constructor failed at
> step 3, so we move to step 4a. And then... Tcurr's copy constructor failed.
>
> Oops.
>
>
Well, I stopped listening at "dynamic allocation", as that is a deal
breaker for me.
For boost, I would almost suggest just keeping the allocated backup and
using it as the value (and using a high-bit in the index to indicate that
the storage is a pointer to an X instead of an embedded X). This means the
allocation isn't temporary, but oh well.
> We already destructed our current value. And our attempt to get it back
> failed. So... what are we?
>
> Whereas Williams.Variant can actually handle this, thanks to the double
> buffer.
>
>> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113fb8c02e0fb80520d383aa
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 2:49 PM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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"><br><br>On Monday, Se=
ptember 28, 2015 at 2:29:47 PM UTC-4, Tony V E wrote:<span class=3D""><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><div><br><div class=
=3D"gmail_quote">On Mon, Sep 28, 2015 at 2:23 PM, Nicol Bolas <span dir=3D"=
ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<br><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
ccc solid;padding-left:1ex"><span><br><br>On Monday, September 28, 2015 at =
2:19:15 PM UTC-4, Nicol Bolas 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">On Monday, September 28, 2015 at 1:18:22 PM UTC-4, Nevin =
":-)" Liber wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"auto"><div>On Sep 28, 2015, at 11:13 AM, Nicol Bolas <<a rel=3D"nof=
ollow">jmck...@gmail.com</a>> wrote:</div><blockquote type=3D"cite">1) D=
ouble buffering in the variant. Williams shows that this can be restricted =
only to where it is <i>absolutely necessary</i>, and only to the <i>extent<=
/i> that it is absolutely necessary.<br></blockquote><br><div><span style=
=3D"background-color:rgba(255,255,255,0)">Not true. Boost.Variant minimizes=
double buffering by falling back on a nothrow default constructible type i=
f it can, which Williams.Variant does not.<br></span></div></div></blockquo=
te><div><br>Yes, because Williams.Variant is trying to offer a stronger gua=
rantee than Boost.Variant. The state after a failure in Boost.Variant is un=
defined; the state in Williams.Variant is well-specified.<br></div></div></=
blockquote></span><div><br>"Undefined" was the wrong word. It'=
;s "valid but unspecified." <br></div></blockquote><div><br></div=
></div><br></div><div>Valid but unspecified, does, however, mean "neve=
r empty", which is what your list was about.=C2=A0 So "fallback t=
o nothrow default constructible" should be included in that list.<br><=
/div></div></blockquote></span><div><br>But it's not a <i>complete</i> =
solution, because there may not be a nothrow default constructible type in =
the typelist. If there are none, you have to do <i>something</i> safe.<br><=
br></div></blockquote><div>=C2=A0<br><br></div><div>True.=C2=A0 So I guess =
you could use it as a refinement to Williams, where you likely double buffe=
r less often.=C2=A0 (not worth it to me, but it is a valid option).<br><br>=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div>In that case, Boost.Var=
iant resorts to... dynamic memory allocation. So really, Boost.Variant is j=
ust an optimized version of the dynamic allocation case. Just as Williams.V=
ariant is an optimized version of double-buffering. Both do the expensive w=
ork only when necessary.<br><br>It should also be noted that Boost.Variant,=
even with dynamic allocation, does not even offer the basic exception guar=
antee.<br><br>Let's say that the current type is Tcurr, and the incomin=
g type is Tin. The way <a href=3D"http://www.boost.org/doc/libs/1_59_0/doc/=
html/variant/design.html#variant.design.never-empty" target=3D"_blank">Boos=
t.Variant is stated to work</a> is this:<br><br>1) Copy-construct the conte=
nt of the left-hand side to the heap; call the pointer to this data backup.=
<br><br>2) Destroy the content of the left-hand side.<br><br>3) Copy-constr=
uct the content of the right-hand side in the (now-empty) storage of the le=
ft-hand side.<br><br>4a) In the event of failure, copy backup to the left-h=
and side storage.<br><br>4b) In the event of success, deallocate the data p=
ointed to by backup.<br><br>That's copied from the website.<br><br>If s=
tep 1 fails due to Tcurr's copy constructor, then the variant is in a v=
alid state (copying is `const` relative to the source object). So everythin=
g is fine. But let's say that Tin's copy-constructor failed at step=
3, so we move to step 4a. And then... Tcurr's copy constructor failed.=
<br><br>Oops.<br><br></div></blockquote><div><br></div><div>Well, I stopped=
listening at "dynamic allocation", as that is a deal breaker for=
me.<br></div><div>For boost, I would almost suggest just keeping the alloc=
ated backup and using it as the value (and using a high-bit in the index to=
indicate that the storage is a pointer to an X instead of an embedded X).=
=C2=A0 This means the allocation isn't temporary, but oh well.<br><br><=
/div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0=
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>We already destru=
cted our current value. And our attempt to get it back failed. So... what a=
re we?<br><br>Whereas Williams.Variant can actually handle this, thanks to =
the double buffer.<br></div><div class=3D"HOEnZb"><div class=3D"h5"><blockq=
uote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:=
1px #ccc solid;padding-left:1ex">
</blockquote>
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113fb8c02e0fb80520d383aa--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 28 Sep 2015 12:18:14 -0700
Raw View
--089e011773411add6f0520d38fa3
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 12:14 PM, Matt Calabrese <calabrese@google.com>
wrote:
> Similarly, what is expected of emplacement? No matter what your field
> types are (including all fundamental types), it's possible for a user to
> invoke an emplace operation that can throw. Because of this, it seems to me
> that when doing emplacement that can throw, you'd need double storage or to
> allow copy-construct then move-assign (this latter point is probably not
> controversial for types that are trivially copy-constructible/
> destructible)
>
Err, I mean *emplace somewhere then move-assign here, not copy then
move-assign.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e011773411add6f0520d38fa3
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 M=
on, Sep 28, 2015 at 12:14 PM, Matt Calabrese <span dir=3D"ltr"><<a href=
=3D"mailto:calabrese@google.com" target=3D"_blank">calabrese@google.com</a>=
></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bor=
der-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail=
_extra"><div class=3D"gmail_quote"><div>Similarly, what is expected of empl=
acement? No matter what your field types are (including all fundamental typ=
es), it's possible for a user to invoke an emplace operation that can t=
hrow. Because of this, it seems to me that when doing emplacement that can =
throw, you'd need double storage or to allow copy-construct then move-a=
ssign=C2=A0<span style=3D"font-size:12.8px">(this latter point is probably =
not controversial for types that are trivially copy-constructible/</span><s=
pan style=3D"font-size:12.8px">destructible)</span><br></div></div></div></=
div></blockquote><div><br></div><div>Err, I mean *emplace somewhere then mo=
ve-assign here, not copy then move-assign.</div></div><br></div><div class=
=3D"gmail_extra"><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e011773411add6f0520d38fa3--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:19:56 -0400
Raw View
--089e013d0ffc34aa070520d39527
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 3:14 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
>
>
> Also, maybe this has already been covered, but is the idea, if the
> committee were to decide that the strong exception guarantee is very
> important for assignment (something I personally disagree with), to use the
> double storage option for any copy/move-assignment that can throw, even
> when both the left-hand and right-hand operand are the same underlying
> field type? It seems like this would ultimately be necessary, otherwise
> you'd only be sure to get the strong exception guarantee when the
> assignment would change the underlying field type. You'd get whatever
> guarantee the *field type* provides when both sides are of the same
> underlying field type if you didn't use double storage or copy/move there
> too, assuming that the assignment can throw. In that latter case, if the
> strong exception guarantee is specified for variant here, we'd have no way
> of knowing if the user's field type's assignment operation uses the basic
> guarantee or the strong guarantee, unless there are some traits involved,
> so we'd have to do the pessimistic thing and just assume that the field
> type provides only the basic guarantee, meaning we'd have to double buffer,
> or copy construct then move-assign instead of direct copy-assign.
>
I'm pretty sure the idea would be to only go out of our way to cover the
problems that are introduced by variant. ie the problems of destroying and
constructing in the same place, without being left in the in-between state.
So we might get a strong guarantee for type-changes, but no guarantee at
all when just assigning an X to an X. That doesn't seem that too odd to
me, because variant is just taking care of its part of the equation.
>
> Similarly, what is expected of emplacement? No matter what your field
> types are (including all fundamental types), it's possible for a user to
> invoke an emplace operation that can throw. Because of this, it seems to me
> that when doing emplacement that can throw, you'd need double storage or to
> allow copy-construct then move-assign (this latter point is probably not
> controversial for types that are trivially
> copy-constructible/destructible). Maybe I'm missing an obvious alternative,
> though.
>
Any type-change would need to go through the hoops.
Tony
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e013d0ffc34aa070520d39527
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 3:14 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><br><div><br></div><div>Also, maybe t=
his has already been covered, but is the idea, if the committee were to dec=
ide that the strong exception guarantee is very important for assignment (s=
omething I personally disagree with), to use the double storage option for =
any copy/move-assignment that can throw, even when both the left-hand and r=
ight-hand operand are the same underlying field type? It seems like this wo=
uld ultimately be necessary, otherwise you'd only be sure to get the st=
rong exception guarantee when the assignment would change the underlying fi=
eld type. You'd get whatever guarantee the *field type* provides when b=
oth sides are of the same underlying field type if you didn't use doubl=
e storage or copy/move there too, assuming that the assignment can throw. I=
n that latter case, if the strong exception guarantee is specified for vari=
ant here, we'd have no way of knowing if the user's field type'=
s assignment operation uses the basic guarantee or the strong guarantee, un=
less there are some traits involved, so we'd have to do the pessimistic=
thing and just assume that the field type provides only the basic guarante=
e, meaning we'd have to double buffer, or copy construct then move-assi=
gn instead of direct copy-assign.</div></div></div></div></blockquote><div>=
<br></div><div>I'm pretty sure the idea would be to only go out of our =
way to cover the problems that are introduced by variant.=C2=A0 ie the prob=
lems of destroying and constructing in the same place, without being left i=
n the in-between state.<br><br></div><div>So we might get a strong guarante=
e for type-changes, but no guarantee at all when just assigning an X to an =
X.=C2=A0 That doesn't seem that too odd to me, because variant is just =
taking care of its part of the equation.<br>=C2=A0<br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"g=
mail_quote"><div><br></div><div>Similarly, what is expected of emplacement?=
No matter what your field types are (including all fundamental types), it&=
#39;s possible for a user to invoke an emplace operation that can throw. Be=
cause of this, it seems to me that when doing emplacement that can throw, y=
ou'd need double storage or to allow copy-construct then move-assign (t=
his latter point is probably not controversial for types that are trivially=
copy-constructible/destructible). Maybe I'm missing an obvious alterna=
tive, though.</div></div></div></div></blockquote><div><br></div><div>Any t=
ype-change would need to go through the hoops.<br><br></div><div>Tony <br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5"=
>
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e013d0ffc34aa070520d39527--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:34:51 -0400
Raw View
--001a1141eeec9176380520d3cabd
Content-Type: text/plain; charset=UTF-8
On Sun, Sep 27, 2015 at 9:59 PM, Andrew Tomazos <andrewtomazos@gmail.com>
wrote:
> ... default constructible...
>
Just my 2 cents:
I'm pretty sure I understand all your reasoning around default
construction, I can even follow the "imagine equality" even if/when
equality doesn't exist, etc.
And to a certain extent I agree, it is at least somewhat surprising. But I
wouldn't go farther than that.
I think the proper/theoretical thing would be to make it not default
constructible, But in practice, default construction is really handy. So
then it comes down to "construct first" vs "embrace empty". I just find
"construct first" to be something I can live with more than embrace empty.
It is not too surprising. So construction doesn't help with "embrace
empty" to me - it goes the other way "embrace empty" (for its other
reasons) can support empty-construction. But "embrace empty" doesn't have
enough other reasons for me.
Variant is somewhere between "a more perfect union" :-) and a real sum-type
(which we can't easily have). In between, it is all about compromise. I
can live with a compromise like "construct first", particularly when we
have the readily available excuse that it aligns with union.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1141eeec9176380520d3cabd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sun, Sep 27, 2015 at 9:59 PM, Andrew Tomazos <span dir=3D"ltr"><<=
a href=3D"mailto:andrewtomazos@gmail.com" target=3D"_blank">andrewtomazos@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">... default constructible...<br></div></blockquote></div><br></div=
><div class=3D"gmail_extra">Just=C2=A0 my 2 cents:<br></div><div class=3D"g=
mail_extra">I'm pretty sure I understand all your reasoning around defa=
ult construction, I can even follow the "imagine equality" even i=
f/when equality doesn't exist, etc.<br><br></div><div class=3D"gmail_ex=
tra">And to a certain extent I agree, it is at least somewhat surprising.=
=C2=A0 But I wouldn't go farther than that.<br><br></div><div class=3D"=
gmail_extra">I think the proper/theoretical thing would be to make it not d=
efault constructible, But in practice, default construction is really handy=
..=C2=A0 So then it comes down to "construct first" vs "embra=
ce empty".=C2=A0 I just find "construct first" to be somethi=
ng I can live with more than embrace empty.=C2=A0 It is not too surprising.=
=C2=A0 So construction doesn't help with "embrace empty" to m=
e - it goes the other way "embrace empty" (for its other reasons)=
can support empty-construction.=C2=A0 But "embrace empty" doesn&=
#39;t have enough other reasons for me.<br><br><br></div><div class=3D"gmai=
l_extra">Variant is somewhere between "a more perfect union" :-) =
and a real sum-type (which we can't easily have).=C2=A0 In between, it =
is all about compromise.=C2=A0 I can live with a compromise like "cons=
truct first", particularly when we have the readily available excuse t=
hat it aligns with union.<br><br></div><div class=3D"gmail_extra">Tony<br><=
br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1141eeec9176380520d3cabd--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 28 Sep 2015 12:35:41 -0700
Raw View
--089e011773418afc460520d3cd05
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
> I'm pretty sure the idea would be to only go out of our way to cover the
> problems that are introduced by variant. ie the problems of destroying and
> constructing in the same place, without being left in the in-between state.
>
> So we might get a strong guarantee for type-changes, but no guarantee at
> all when just assigning an X to an X. That doesn't seem that too odd to
> me, because variant is just taking care of its part of the equation.
>
That seems pretty odd to me and you'd not be providing the strong exception
guarantee anymore. Without that, how would someone correctly rely on the
*partial* strong exception guarantee in their code (especially if it's
generic code operating on dependent field types)? They'd have to manually
check to see that which() is not the same, and only then they'd be sure to
get the strong exception guarantee before doing the assignment. If which()
is equal and their type only specifies the basic guarantee, or if the field
type is dependent so they don't know whether or not assignment has the
strong or basic guarantee, then they'd have to do something more
complicated to keep track of the old state, assuming they need to get back
to it.
This just seems really inconsistent to me. If you decide that the strong
exception guarantee really is important for assignment, I think it needs to
be all-or-nothing. Otherwise you're only providing the basic guarantee
anyway, and in that case, I'd just embrace the basic guarantee whether the
underlying field types are the same or not. My personal thoughts are that
we should just always only specify the basic guarantee and be done with it.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e011773418afc460520d3cd05
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 M=
on, Sep 28, 2015 at 12:19 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mai=
lto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=
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"><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote"><div>I'm pretty sure the idea would be to only go o=
ut of our way to cover the problems that are introduced by variant.=C2=A0 i=
e the problems of destroying and constructing in the same place, without be=
ing left in the in-between state.<br><br></div><div>So we might get a stron=
g guarantee for type-changes, but no guarantee at all when just assigning a=
n X to an X.=C2=A0 That doesn't seem that too odd to me, because varian=
t is just taking care of its part of the equation.</div></div></div></div><=
/blockquote><div><br></div><div>That seems pretty odd to me and you'd n=
ot be providing the strong exception guarantee anymore. Without that, how w=
ould someone correctly rely on the *partial* strong exception guarantee in =
their code (especially if it's generic code operating on dependent fiel=
d types)? They'd have to manually check to see that which() is not the =
same, and only then they'd be sure to get the strong exception guarante=
e before doing the assignment. If which() is equal and their type only spec=
ifies the basic guarantee, or if the field type is dependent so they don=
9;t know whether or not assignment has the strong or basic guarantee, then =
they'd have to do something more complicated to keep track of the old s=
tate, assuming they need to get back to it.</div><div><br></div><div>This j=
ust seems really inconsistent to me. If you decide that the strong exceptio=
n guarantee really is important for assignment, I think it needs to be all-=
or-nothing. Otherwise you're only providing the basic guarantee anyway,=
and in that case, I'd just embrace the basic guarantee whether the und=
erlying field types are the same or not. My personal thoughts are that we s=
hould just always only specify the basic guarantee and be done with it.<br>=
</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e011773418afc460520d3cd05--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Mon, 28 Sep 2015 16:52:12 -0300
Raw View
On 9/28/2015 4:34 PM, Tony V E wrote:
> Variant is somewhere between "a more perfect union" :-) and a real
> sum-type (which we can't easily have). In between, it is all about
> compromise. I can live with a compromise like "construct first",
> particularly when we have the readily available excuse that it aligns
> with union.
Except it does not quite align with union. If you have a union of=20
trivially-constructible members then if you explicitly ask for it then=20
the first member is initialized, otherwise if the operation has any=20
runtime cost then union will just do nothing (default to empty).=20
Furthermore, if you have a union where any of its members is not=20
trivially-constructible, union simply won't try to guess for you and=20
will force you to pick which semantics you want (which might as well=20
include default to empty).
I think it's reasonable to have a never-empty variant default construct=20
the first member. I do not think this aligns with union.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:54:58 -0400
Raw View
--001a1141eeec7a35930520d41279
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sat, Sep 26, 2015 at 10:58 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
> On 9/26/2015 11:36 AM, Magnus Fromreide wrote:
>
>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>
>>>
>>> Disengagement is different from merely representing a value which is
>>> empty
>>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the vari=
ant wrapper, not
>>> the
>>> wrapped object which is what goes into visitors. The term =E2=80=9Cempt=
y state=E2=80=9D
>>> is
>>> confusingly ambiguous in this way. Treating the discriminator as a
>>> user-accessible scalar value adds to the confusion.
>>>
>>
>> My concern is that I don't want the types variant<T> and optional<T> to =
be
>> functionally equivalent, regardless of how variant is implemented.
>>
>
> The fundamental model for `optional<T>` is a union of `nullopt_t` and `T`=
,
> so it would be reasonable to expect `variant<nullopt_t, T>` to be
> functionally equivalent.
>
If variant falls-back to nullopt_t on exceptions, then yes, they are
functionally equivalent. But if it doesn't, they are not.
>
> Now, I have to admit to not having paid all that much attention to the ba=
ck
>> and forth of the debate about variant but this should imply that I don't
>> want to see a publicly accessible empty state in variant.
>>
>
> This does not seem to be related to `optional<T>`, which does not have an
> empty state. Instead, it defines its active member changing semantics as
> first switch to `nullopt_t`, then act.
>
optional<T> does have an empty state, which is equivalent to switching to
nullopt_t on failure, (and construction, reset(), etc....).
So "don't want to see... empty state in variant" is the same as "don't want
variant to fall back to default-constructible
nullopt_t/nullvar_t/blank_t/monostate/whatever".
At a high level optional<T> and variant<nullopt_t, T> are the same, but it
depends on the details. The fallback (vs never-empty-guarantee) is an
important detail (to some).
Tony
>
> Regards,
> --
> Agust=C3=ADn K-ballo Berg=C3=A9.-
> http://talesofcpp.fusionfenix.com
>
> --
>
> --- You received this message because you are subscribed to the Google
> Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=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/.
--001a1141eeec7a35930520d41279
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sat, Sep 26, 2015 at 10:58 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <span=
dir=3D"ltr"><<a href=3D"mailto:kaballo86@hotmail.com" target=3D"_blank"=
>kaballo86@hotmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_=
quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1=
ex"><span class=3D"">On 9/26/2015 11:36 AM, Magnus Fromreide wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
<br>
Disengagement is different from merely representing a value which is empty<=
br>
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the<br>
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is<br>
confusingly ambiguous in this way. Treating the discriminator as a<br>
user-accessible scalar value adds to the confusion.<br>
</blockquote>
<br>
My concern is that I don't want the types variant<T> and optional=
<T> to be<br>
functionally equivalent, regardless of how variant is implemented.<br>
</blockquote>
<br></span>
The fundamental model for `optional<T>` is a union of `nullopt_t` and=
`T`, so it would be reasonable to expect `variant<nullopt_t, T>` to =
be functionally equivalent.<span class=3D""><br></span></blockquote><div><b=
r></div><div>If variant falls-back to nullopt_t on exceptions, then yes, th=
ey are functionally equivalent.=C2=A0 But if it doesn't, they are not.<=
br>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=3D"">
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Now, I have to admit to not having paid all that much attention to the back=
<br>
and forth of the debate about variant but this should imply that I don'=
t<br>
want to see a publicly accessible empty state in variant.<br>
</blockquote>
<br></span>
This does not seem to be related to `optional<T>`, which does not hav=
e an empty state. Instead, it defines its active member changing semantics =
as first switch to `nullopt_t`, then act.<span class=3D"im HOEnZb"><br></sp=
an></blockquote><div><br></div><div>optional<T> does have an empty st=
ate, which is equivalent to switching to nullopt_t on failure, (and constru=
ction, reset(), etc....).<br><br></div><div>So "don't want to see.=
... empty state in variant" is the same as "don't want variant=
to fall back to default-constructible nullopt_t/nullvar_t/blank_t/monostat=
e/whatever".<br><br><br></div><div>At a high level optional<T> a=
nd variant<nullopt_t, T> are the same, but it depends on the details.=
=C2=A0 The fallback (vs never-empty-guarantee) is an important detail (to s=
ome).<br><br></div><div>Tony<br></div><div><br></div><div>=C2=A0<br></div><=
blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px=
#ccc solid;padding-left:1ex"><span class=3D"im HOEnZb">
<br>
Regards,<br>
-- <br>
Agust=C3=ADn K-ballo Berg=C3=A9.-<br>
<a href=3D"http://talesofcpp.fusionfenix.com" rel=3D"noreferrer" target=3D"=
_blank">http://talesofcpp.fusionfenix.com</a><br>
<br></span><div class=3D"HOEnZb"><div class=3D"h5">
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps "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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1141eeec7a35930520d41279--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:55:08 -0400
Raw View
--001a11411c381cb0200520d413f8
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sat, Sep 26, 2015 at 12:37 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
>
> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>
> Disengagement is different from merely representing a value which is empt=
y
> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the varian=
t wrapper, not the
> wrapped object which is what goes into visitors. The term =E2=80=9Cempty =
state=E2=80=9D is
> confusingly ambiguous in this way. Treating the discriminator as a
> user-accessible scalar value adds to the confusion.
>
> My concern is that I don't want the types variant<T> and optional<T> to b=
e
> functionally equivalent, regardless of how variant is implemented.
>
> You mean variant<nullopt_t,T> and optional<T> isn't it?
>
> I like to see optional<T> as a specialization of variant<nullopt_t, T>
> providing an interface similar to a smart pointer to T.
>
>
Only if variant falls-back to nullopt_t on exceptions.
> I like to see visitation on sum types as pattern matching, so when
> visiting an optional<T>, I would like to handle disengagement by matching
> the nullopt_t type.
>
>
I can agree with that (regardless as to whether variant has empty or not).
I'm tempted to say a const optional<T> is equivalent to a const
variant<nullopt_t, T>, such that the same generic visitation should work on
both, but if you remove the const, they behave differently, so I don't
expect them to necessarily support the same interfaces.
ie if you had some kind of readonly sum_type_view concept or class, they
could both model or derive from that.
Tony
> Vicente
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=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/.
--001a11411c381cb0200520d413f8
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sat, Sep 26, 2015 at 12:37 PM, Vicente J. Botet Escriba <span dir=3D=
"ltr"><<a href=3D"mailto:vicente.botet@wanadoo.fr" target=3D"_blank">vic=
ente.botet@wanadoo.fr</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">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 26/09/15 16:36, Magnus Fromreide a
=C3=A9crit=C2=A0:<br>
</div><span class=3D"">
<blockquote type=3D"cite">
<pre>On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
</pre>
<blockquote type=3D"cite">
<pre>Disengagement is different from merely representing a value wh=
ich is empty
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is
confusingly ambiguous in this way. Treating the discriminator as a
user-accessible scalar value adds to the confusion.
</pre>
</blockquote>
<pre>My concern is that I don't want the types variant<T> a=
nd optional<T> to be
functionally equivalent, regardless of how variant is implemented.</pre>
</blockquote></span>
You mean variant<nullopt_t,T> and optional<T> isn't it?=
<br>
<br>
<font size=3D"+1">I like to see optional<T> as a specialization
of variant<nullopt_t, T> providing an interface similar to a
smart pointer to T.<br>
<br></font></div></blockquote><div><br></div><div>Only if variant fal=
ls-back to nullopt_t on exceptions.<br>=C2=A0<br></div><div>=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div bgcolor=3D"#FFFFFF" text=3D"#000000"><font=
size=3D"+1">
</font><font size=3D"+1">I like to see visitation on sum types as
pattern matching, so when visiting an optional<T>, I would
like to handle disengagement by matching the nullopt_t </font><font s=
ize=3D"+1"><font size=3D"+1">type</font>.<span class=3D"HOEnZb"><font color=
=3D"#888888"><br>
<br></font></span></font></div></blockquote><div><br></div><div>I can=
agree with that (regardless as to whether variant has empty or not).<br><b=
r></div><div>I'm tempted to say a const optional<T> is equivalent=
to a const variant<nullopt_t, T>, such that the same generic visitat=
ion should work on both, but if you remove the const, they behave different=
ly, so I don't expect them to necessarily support the same interfaces.<=
br></div><div>ie if you had some kind of readonly sum_type_view concept or =
class, they could both model or derive from that.<br><br></div><div>Tony<br=
><br></div><div>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div bgcolor=
=3D"#FFFFFF" text=3D"#000000"><font size=3D"+1"><span class=3D"HOEnZb"><fon=
t color=3D"#888888">
Vicente<br>
</font></span></font>
</div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11411c381cb0200520d413f8--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 15:59:22 -0400
Raw View
--001a11411c3834922b0520d422f3
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 23, 2015 at 5:01 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Wed, Sep 23, 2015 at 8:00 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> Most functions with basic guarantees can be "upgraded" via assignment or
>> non-throwing swap - ie assign back a copy of the old value. But for
>> variant, assignment is the function in question, so there is no easy way to
>> implement strong on top of basic.
>>
>
> This is true regardless of there being an invalid state or not. I'm not
> implying that you are conflating them, I just want to make this clear so
> that if people disagree with one point the issues remain orthogonal.
> They've been conflated before.
>
> Assuming you really do need to get back the old value, which isn't even
> always required when handling an exception depending on your situation, you
> can do this via indirection in at least a couple of ways. First, you can
> store the offending fields that have move constructors that are not
> noexcept by way of a unique_ptr (as explained, this doesn't even
> necessarily imply dynamic memory allocation, though in practice this likely
> isn't an issue anyway, since your type that has a move-constructor that can
> throw likely is that way because it is itself doing some kind of dynamic
> memory allocation). Alternatively, you do the equivalent of the double
> storage option but at a higher level rather than the variant type
> implicitly doing it whenever it would need to in order to make assignment
> meet the strong guarantee (I.E. when one of the fields has a
> move-constructor that is not noexcept).
>
Building the double-buffer on top of variant probably leads to just
building your own variant from scratch.
>
> Another way to phrase this last point is that while you can build the
> equivalent of a variant type that uses the double storage option by way of
> a thinner variant as a building block, if you instead start with a variant
> that forces double storage, there is no way to get rid of that storage when
> you do not need it. If you don't need it and the cost is also too much,
> either because of overall memory usage or because arrays of such
> types/things that contain such types are less cache friendly, then you'd
> have to implement your own variant type more from scratch.
>
So they both lead to build your own. :-(
I'd welcome a proposal that let's you opt-out of double buffering (giving
less interface in return, for example), or the suggestion made elsewhere in
the thread that would allow you to static_assert on "wasted" space.
But I'm currently leaning towards double-buffering should be the default,
and NOT doing it be for advanced users. More correct instead of more
efficient.
Tony
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11411c3834922b0520d422f3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Sep 23, 2015 at 5:01 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Wed, Sep 23, 2015=
at 8:00 AM, Tony V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmai=
l.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> wrote:<br><block=
quote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div c=
lass=3D"gmail_quote"><div>Most functions with basic guarantees can be "=
;upgraded" via assignment or non-throwing swap - ie assign back a copy=
of the old value.=C2=A0 But for variant, assignment is the function in que=
stion, so there is no easy way to implement strong on top of basic.<br></di=
v></div></div></div></blockquote><div><br></div></span><div>This is true re=
gardless of there being an invalid state or not. I'm not implying that =
you are conflating them, I just want to make this clear so that if people d=
isagree with one point the issues remain orthogonal. They've been confl=
ated before.</div><div><br></div><div>Assuming you really do need to get ba=
ck the old value, which isn't even always required when handling an exc=
eption depending on your situation, you can do this via indirection in at l=
east a couple of ways. First, you can store the offending fields that have =
move constructors that are not noexcept by way of a unique_ptr (as explaine=
d, this doesn't even necessarily imply dynamic memory allocation, thoug=
h in practice this likely isn't an issue anyway, since your type that h=
as a move-constructor that can throw likely is that way because it is itsel=
f doing some kind of dynamic memory allocation). Alternatively, you do the =
equivalent of the double storage option but at a higher level rather than t=
he variant type implicitly doing it whenever it would need to in order to m=
ake assignment meet the strong guarantee (I.E. when one of the fields has a=
move-constructor that is not noexcept).</div></div></div></div></blockquot=
e><div><br></div><div>Building the double-buffer on top of variant probably=
leads to just building your own variant from scratch.<br>=C2=A0<br></div><=
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 class=3D"gmail_extra"><=
div class=3D"gmail_quote"><div><br></div><div>Another way to phrase this la=
st point is that while you can build the equivalent of a variant type that =
uses the double storage option by way of a thinner variant as a building bl=
ock, if you instead start with a variant that forces double storage, there =
is no way to get rid of that storage when you do not need it. If you don=
9;t need it and the cost is also too much, either because of overall memory=
usage or because arrays of such types/things that contain such types are l=
ess cache friendly, then you'd have to implement your own variant type =
more from scratch.</div></div></div></div></blockquote><div><br></div><div>=
So they both lead to build your own. :-(<br><br></div><div>I'd welcome =
a proposal that let's you opt-out of double buffering (giving less inte=
rface in return, for example), or the suggestion made elsewhere in the thre=
ad that would allow you to static_assert on "wasted" space.<br><b=
r></div><div>But I'm currently leaning towards double-buffering should =
be the default, and NOT doing it be for advanced users.=C2=A0 More correct =
instead of more efficient.<br><br></div><div>Tony<br></div><div>=C2=A0<br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5"=
>
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11411c3834922b0520d422f3--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 16:01:38 -0400
Raw View
--047d7b3a84c656a16e0520d42a50
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 23, 2015 at 6:06 PM, Anthony Williams <anthony.ajw@gmail.com>
wrote:
> On 23/09/15 05:03, Nevin Liber wrote:
> > Oh, and don't forget it is a pessimization to do
> > construct-then-noexcept-move instead of just construct when the variant
> > is changing types, so you are penalizing all users. Of course, double
> > buffering is also a pessimization in terms of cache as well as memory
> usage.
> >
> > Tradeoffs are hard.
>
> Yes, tradeoffs are hard.
>
> I've done some work on my variant implementation on bitbucket
> (https://bitbucket.org/anthonyw/variant) to add the strong guarantee.
>
> It does this in a variety of ways, in order to minimize space.
>
> 1. If the type you are constructing has a nothrow constructor you are
> trying to use, destroy old value then construct directly
>
> 2. If the type you are constructing has a nothrow move constructor, and
> it is not double-buffered (see below) then construct locally and then
> destroy old value, and move-construct into the variant.
>
> 3. If all the other types have a nothrow move constructor and this type
> is not double-buffered (see below) then move-construct the old value
> into a local buffer, construct the new value in place, then destroy the
> local buffer. On exception, move the old value back.
>
> 4. If at least 2 types are not nothrow-move-constructible then we need a
> double-buffer. The size of the buffer is set to big enough to cover all
> the types that are not nothrow-move-constructible. However, all types
> that fit are then counted as double-buffered. This avoids extra move
> constructions where possible, without imposing a space penalty beyond
> what is required.
>
> I think this is a reasonable trade-off. YMMV.
>
Nice work. This is what I've been imagining whenever talking about
double-buffering "when needed", but it really helps to see it spelled out
(particularly spelled out in code).
>
> Anthony
> --
> Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
> just::thread C++11 thread library http://www.stdthread.co.uk
> Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b3a84c656a16e0520d42a50
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Sep 23, 2015 at 6:06 PM, Anthony Williams <span dir=3D"ltr"><=
;<a href=3D"mailto:anthony.ajw@gmail.com" target=3D"_blank">anthony.ajw@gma=
il.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"><span class=
=3D"">On 23/09/15 05:03, Nevin Liber wrote:<br>
> Oh, and don't forget it is a pessimization to do<br>
> construct-then-noexcept-move instead of just construct when the varian=
t<br>
> is changing types, so you are penalizing all users.=C2=A0 Of course, d=
ouble<br>
> buffering is also a pessimization in terms of cache as well as memory =
usage.<br>
><br>
> Tradeoffs are hard.<br>
<br>
</span>Yes, tradeoffs are hard.<br>
<br>
I've done some work on my variant implementation on bitbucket<br>
(<a href=3D"https://bitbucket.org/anthonyw/variant" rel=3D"noreferrer" targ=
et=3D"_blank">https://bitbucket.org/anthonyw/variant</a>) to add the strong=
guarantee.<br>
<br>
It does this in a variety of ways, in order to minimize space.<br>
<br>
1. If the type you are constructing has a nothrow constructor you are<br>
trying to use, destroy old value then construct directly<br>
<br>
2. If the type you are constructing has a nothrow move constructor, and<br>
it is not double-buffered (see below) then construct locally and then<br>
destroy old value, and move-construct into the variant.<br>
<br>
3. If all the other types have a nothrow move constructor and this type<br>
is not double-buffered (see below) then move-construct the old value<br>
into a local buffer, construct the new value in place, then destroy the<br>
local buffer. On exception, move the old value back.<br>
<br>
4. If at least 2 types are not nothrow-move-constructible then we need a<br=
>
double-buffer. The size of the buffer is set to big enough to cover all<br>
the types that are not nothrow-move-constructible. However, all types<br>
that fit are then counted as double-buffered. This avoids extra move<br>
constructions where possible, without imposing a space penalty beyond<br>
what is required.<br>
<br>
I think this is a reasonable trade-off. YMMV.<br></blockquote><div><br></di=
v><div>Nice work.=C2=A0 This is what I've been imagining whenever talki=
ng about double-buffering "when needed", but it really helps to s=
ee it spelled out (particularly spelled out in code).<br>=C2=A0<br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px =
#ccc solid;padding-left:1ex">
<span class=3D"im HOEnZb"><br>
Anthony<br>
--<br>
Author of C++ Concurrency in Action=C2=A0 =C2=A0 =C2=A0<a href=3D"http://ww=
w.stdthread.co.uk/book/" rel=3D"noreferrer" target=3D"_blank">http://www.st=
dthread.co.uk/book/</a><br>
just::thread C++11 thread library=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0<a href=3D"http://www.stdthread.co.uk" rel=3D"noreferrer" target=3D"_=
blank">http://www.stdthread.co.uk</a><br>
Just Software Solutions Ltd=C2=A0 =C2=A0 =C2=A0 =C2=A0<a href=3D"http://www=
..justsoftwaresolutions.co.uk" rel=3D"noreferrer" target=3D"_blank">http://w=
ww.justsoftwaresolutions.co.uk</a><br>
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976<br=
>
<br>
</span><div class=3D"HOEnZb"><div class=3D"h5">--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b3a84c656a16e0520d42a50--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Mon, 28 Sep 2015 21:01:46 +0100
Raw View
On 28/09/15 20:18, 'Matt Calabrese' via ISO C++ Standard - Future
Proposals wrote:
> On Mon, Sep 28, 2015 at 12:14 PM, Matt Calabrese <calabrese@google.com
> <mailto:calabrese@google.com>> wrote:
>
> Similarly, what is expected of emplacement? No matter what your
> field types are (including all fundamental types), it's possible for
> a user to invoke an emplace operation that can throw. Because of
> this, it seems to me that when doing emplacement that can throw,
> you'd need double storage or to allow copy-construct then
> move-assign (this latter point is probably not controversial for
> types that are trivially copy-constructible/destructible)
>
>
> Err, I mean *emplace somewhere then move-assign here, not copy then
> move-assign.
Yes. My current implementation just provides basic guarantee for emplace
because the requirements are different to assignment and it's a
proof-of-concept implementation.
To provide the strong guarantee for emplace, you need to double-buffer
if *any* type is missing the nothrow move constructor (rather than only
if 2 types can throw), since you still need the backup even if the types
are the same, whereas with assignment you can use the type's native
assignment.
Of course, if you never use the type's native assignment (to really
provide the strong guarantee), then you need buffering for assignment
too if one type has a throwing move.
Also, you may end up using the buffer more often, unless you're willing
to emplace-construct a temporary and then nothrow-move from there. If
you were willing to do that, you'd probably not need emplace anyway as
you could just say v=T(args);
So, strong guarantee for emplacement increases the chance you'd need to
double-buffer.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 16:02:27 -0400
Raw View
--089e0141a718462ccd0520d42d38
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sat, Sep 26, 2015 at 2:33 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Saturday, September 26, 2015 at 1:21:34 PM UTC-4, Vicente J. Botet
> Escriba wrote:
>>
>> Le 26/09/15 19:10, Vicente J. Botet Escriba a =C3=A9crit :
>> > Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :
>> >> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss wrote=
:
>> >
>> >>
>> >> This also means we don't have to give types default constructors just
>> to
>> >> satisfy C++ usage anymore. Just declare an `optional` of it,
>> >> construct it
>> >> empty, then initialize it later on when you're ready to properly do
>> >> so. You
>> >> can even copy/move out of it when you're ready to pass it to whomever
>> >> needs
>> >> it.
>> >>
>> >> Do you have any other reasons why we need `variant` to be able to
>> become
>> >> "disengaged/empty/etc"? Note that I said "need", not "prefer". What
>> >> *actual
>> >> problems* would such a concept solve for you?
>> > optionals<Ts...> can be implemented more efficiently than
>> > optional<variants<Ts...>>, but I want it to be a model of sum type
>> > nullopt_t + Ts... and be able to visit it all at once. I don't want to
>> > have to check if the optional is engaged and only then do visit the
>> > stored value.
>> I want to be able to visit nullable variants like
>>
>> optionals<T1, T2> o =3D ...;
>> auto x=3D match(o,
>> [](nullopt_t)->U {...},
>> [](T1)->U {...},
>> [](T2)->U {...}
>> );
>>
>
> ... why would you not do:
>
> variant<monostate, T1, T2> v =3D ...;
>
> Why do you need a whole new type for something that a never-empty variant
> gives you by design?
because variant doesn't (currently) fallback to monostate, whereas
optionals<Ts...> would.
Not sure if that is enough of a difference to warrant the class or not.
Tony
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=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/.
--089e0141a718462ccd0520d42d38
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sat, Sep 26, 2015 at 2:33 PM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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 class=3D"HOEnZb"=
><div class=3D"h5">On Saturday, September 26, 2015 at 1:21:34 PM UTC-4, Vic=
ente J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">Le 26/0=
9/15 19:10, Vicente J. Botet Escriba a =C3=A9crit :
<br>> Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :
<br>>> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Kraus=
s wrote:
<br>>
<br>>>
<br>>> This also means we don't have to give types default constr=
uctors just to
<br>>> satisfy C++ usage anymore. Just declare an `optional` of it,=
=20
<br>>> construct it
<br>>> empty, then initialize it later on when you're ready to pr=
operly do=20
<br>>> so. You
<br>>> can even copy/move out of it when you're ready to pass it =
to whomever=20
<br>>> needs
<br>>> it.
<br>>>
<br>>> Do you have any other reasons why we need `variant` to be able=
to become
<br>>> "disengaged/empty/etc"? Note that I said "need&=
quot;, not "prefer". What=20
<br>>> *actual
<br>>> problems* would such a concept solve for you?
<br>> optionals<Ts...> can be implemented more efficiently than=20
<br>> optional<variants<Ts...>>, but I want it to be a model=
of sum type=20
<br>> nullopt_t + Ts... and be able to visit it all at once. I don't=
want to=20
<br>> have to check if the optional is engaged and only then do visit th=
e=20
<br>> stored value.
<br>I want to be able to visit nullable variants like
<br>
<br>optionals<T1, T2> o =3D ...;
<br>auto x=3D =C2=A0match(o,
<br>=C2=A0 =C2=A0 =C2=A0[](nullopt_t)->U {...},
<br>=C2=A0 =C2=A0 =C2=A0[](T1)->U {...},
<br>=C2=A0 =C2=A0 =C2=A0[](T2)->U {...}
<br>);
<br></blockquote></div></div><div><br>... why would you not do:<br><br><div=
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);b=
order-style:solid;border-width:1px;word-wrap:break-word"><code><div><span s=
tyle=3D"color:#000">variant</span><span style=3D"color:#660"><</span><sp=
an style=3D"color:#000">monostate</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> T1</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> T2</span><span style=3D"color:#660">></span><sp=
an style=3D"color:#000"> v </span><span style=3D"color:#660">=3D</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">...;</span></div>=
</code></div><br></div>Why do you need a whole new type for something that =
a never-empty variant gives you by design?</blockquote><div><br></div><div>=
because variant doesn't (currently) fallback to monostate, whereas opti=
onals<Ts...> would.<br></div><div>Not sure if that is enough of a dif=
ference to warrant the class or not.<br></div><div>Tony<br></div><div>=C2=
=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div clas=
s=3D"h5"><br>
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0141a718462ccd0520d42d38--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 16:06:18 -0400
Raw View
--001a11c223aa064d4a0520d43b6d
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Mon, Sep 28, 2015 at 3:52 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
> On 9/28/2015 4:34 PM, Tony V E wrote:
>
>> Variant is somewhere between "a more perfect union" :-) and a real
>> sum-type (which we can't easily have). In between, it is all about
>> compromise. I can live with a compromise like "construct first",
>> particularly when we have the readily available excuse that it aligns
>> with union.
>>
>
> Except it does not quite align with union. If you have a union of
> trivially-constructible members then if you explicitly ask for it then th=
e
> first member is initialized, otherwise if the operation has any runtime
> cost then union will just do nothing (default to empty). Furthermore, if
> you have a union where any of its members is not trivially-constructible,
> union simply won't try to guess for you and will force you to pick which
> semantics you want (which might as well include default to empty).
>
> I think it's reasonable to have a never-empty variant default construct
> the first member. I do not think this aligns with union.
>
Sure it doesn't completely align, but there is a similarity.
And yeah, I think it is reasonable if it union had never done it.
>
> Regards,
> --
> Agust=C3=ADn K-ballo Berg=C3=A9.-
> http://talesofcpp.fusionfenix.com
>
> --
>
> --- You received this message because you are subscribed to the Google
> Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=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/.
--001a11c223aa064d4a0520d43b6d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 3:52 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <span =
dir=3D"ltr"><<a href=3D"mailto:kaballo86@hotmail.com" target=3D"_blank">=
kaballo86@hotmail.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"><span class=3D"">On 9/28/2015 4:34 PM, Tony V E wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Variant is somewhere between "a more perfect union" :-) and a rea=
l<br>
sum-type (which we can't easily have).=C2=A0 In between, it is all abou=
t<br>
compromise.=C2=A0 I can live with a compromise like "construct first&q=
uot;,<br>
particularly when we have the readily available excuse that it aligns<br>
with union.<br>
</blockquote>
<br></span>
Except it does not quite align with union. If you have a union of trivially=
-constructible members then if you explicitly ask for it then the first mem=
ber is initialized, otherwise if the operation has any runtime cost then un=
ion will just do nothing (default to empty). Furthermore, if you have a uni=
on where any of its members is not trivially-constructible, union simply wo=
n't try to guess for you and will force you to pick which semantics you=
want (which might as well include default to empty).<br>
<br>
I think it's reasonable to have a never-empty variant default construct=
the first member. I do not think this aligns with union.<span class=3D"im =
HOEnZb"><br></span></blockquote><div><br></div><div>Sure it doesn't com=
pletely align, but there is a similarity.<br></div><div>And yeah, I think i=
t is reasonable if it union had never done it.<br>=C2=A0<br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><span class=3D"im HOEnZb">
<br>
Regards,<br>
-- <br>
Agust=C3=ADn K-ballo Berg=C3=A9.-<br>
<a href=3D"http://talesofcpp.fusionfenix.com" rel=3D"noreferrer" target=3D"=
_blank">http://talesofcpp.fusionfenix.com</a><br>
<br></span><div class=3D"HOEnZb"><div class=3D"h5">
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps "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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c223aa064d4a0520d43b6d--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Mon, 28 Sep 2015 15:07:33 -0500
Raw View
--001a1141dba0da61660520d441fa
Content-Type: text/plain; charset=UTF-8
On 28 September 2015 at 03:26, Anthony Williams <anthony.ajw@gmail.com>
wrote:
> I have submitted a paper describing the requirements for providing the
> strong guarantee for assignment, as outlined in my previous emails.
>
If the variant isn't changing its engaged type, are you still providing the
strong guarantee for assignment?
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1141dba0da61660520d441fa
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 28 September 2015 at 03:26, Anthony Williams <span dir=
=3D"ltr"><<a href=3D"mailto:anthony.ajw@gmail.com" target=3D"_blank">ant=
hony.ajw@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div=
class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 =
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I have submitted a pa=
per describing the requirements for providing the<br>
strong guarantee for assignment, as outlined in my previous emails.<br></bl=
ockquote><div><br></div><div>If the variant isn't changing its engaged =
type, are you still providing the strong guarantee for assignment?</div></d=
iv>-- <br><div class=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=
=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blan=
k">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1141dba0da61660520d441fa--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Mon, 28 Sep 2015 21:10:40 +0100
Raw View
On 28/09/15 21:07, Nevin Liber wrote:
> On 28 September 2015 at 03:26, Anthony Williams <anthony.ajw@gmail.com
> <mailto:anthony.ajw@gmail.com>> wrote:
>
> I have submitted a paper describing the requirements for providing the
> strong guarantee for assignment, as outlined in my previous emails.
>
>
> If the variant isn't changing its engaged type, are you still providing
> the strong guarantee for assignment?
My paper says "assuming we use the type's assignment operator for
same-type assignment" or something similar.... so no.
We could do it; see the email I just sent.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 16:27:59 -0400
Raw View
--001a113fb8c0887cfc0520d48831
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 3:35 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <tvaneerd@gmail.com> wrote:
>>
>> I'm pretty sure the idea would be to only go out of our way to cover the
>> problems that are introduced by variant. ie the problems of destroying and
>> constructing in the same place, without being left in the in-between state.
>>
>> So we might get a strong guarantee for type-changes, but no guarantee at
>> all when just assigning an X to an X. That doesn't seem that too odd to
>> me, because variant is just taking care of its part of the equation.
>>
>
> That seems pretty odd to me and you'd not be providing the strong
> exception guarantee anymore. Without that, how would someone correctly rely
> on the *partial* strong exception guarantee in their code (especially if
> it's generic code operating on dependent field types)? They'd have to
> manually check to see that which() is not the same, and only then they'd be
> sure to get the strong exception guarantee before doing the assignment. If
> which() is equal and their type only specifies the basic guarantee, or if
> the field type is dependent so they don't know whether or not assignment
> has the strong or basic guarantee, then they'd have to do something more
> complicated to keep track of the old state, assuming they need to get back
> to it.
>
> This just seems really inconsistent to me. If you decide that the strong
> exception guarantee really is important for assignment, I think it needs to
> be all-or-nothing. Otherwise you're only providing the basic guarantee
> anyway, and in that case, I'd just embrace the basic guarantee whether the
> underlying field types are the same or not. My personal thoughts are that
> we should just always only specify the basic guarantee and be done with it.
>
I think whenever possible[*], variant<X> should act like X. In my mind,
that overrides variant's aspirations. So assignment should assign straight
through.
I'm not sure if is enough for me to drop the strong guarantee. If
noexcept() could tell the difference between strong and basic... that might
be interesting.
I just see it as orthogonal: "I manage switching types. If I can't switch,
nothing changes". What X does when not switching is not variant's problem.
"just always only specify the basic guarantee and be done with it." of
course also requires either a type that is nothrow default constructible,
or limiting what variant can do. I'm hearing a bit of push-back on the
latter part. So what else could you do when none of the types can be
constructed? If people can't agree on limited functionality, then its
either double-buffer or empty or invalid. I'm at double-buffer > invalid >
empty > limited functionality.
[*] "whenever possible" means as long as it maintains whatever invariants
we decide for variant.
--
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113fb8c0887cfc0520d48831
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 3:35 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"lt=
r"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D"">O=
n Mon, Sep 28, 2015 at 12:19 PM, Tony V E <span dir=3D"ltr"><<a href=3D"=
mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></sp=
an> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr=
"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>I'm pretty=
sure the idea would be to only go out of our way to cover the problems tha=
t are introduced by variant.=C2=A0 ie the problems of destroying and constr=
ucting in the same place, without being left in the in-between state.<br><b=
r></div><div>So we might get a strong guarantee for type-changes, but no gu=
arantee at all when just assigning an X to an X.=C2=A0 That doesn't see=
m that too odd to me, because variant is just taking care of its part of th=
e equation.</div></div></div></div></blockquote><div><br></div></span><div>=
That seems pretty odd to me and you'd not be providing the strong excep=
tion guarantee anymore. Without that, how would someone correctly rely on t=
he *partial* strong exception guarantee in their code (especially if it'=
;s generic code operating on dependent field types)? They'd have to man=
ually check to see that which() is not the same, and only then they'd b=
e sure to get the strong exception guarantee before doing the assignment. I=
f which() is equal and their type only specifies the basic guarantee, or if=
the field type is dependent so they don't know whether or not assignme=
nt has the strong or basic guarantee, then they'd have to do something =
more complicated to keep track of the old state, assuming they need to get =
back to it.</div><div><br></div><div>This just seems really inconsistent to=
me. If you decide that the strong exception guarantee really is important =
for assignment, I think it needs to be all-or-nothing. Otherwise you're=
only providing the basic guarantee anyway, and in that case, I'd just =
embrace the basic guarantee whether the underlying field types are the same=
or not. My personal thoughts are that we should just always only specify t=
he basic guarantee and be done with it.<br></div></div></div></div></blockq=
uote><div><br></div><div><br>I think whenever possible[*], variant<X>=
should act like X.=C2=A0 In my mind, that overrides variant's aspirati=
ons. So assignment should assign straight through.<br><br></div><div>I'=
m not sure if is enough for me to drop the strong guarantee.=C2=A0 If noexc=
ept() could tell the difference between strong and basic... that might be i=
nteresting.<br><br></div><div>I just see it as orthogonal: "I manage s=
witching types. If I can't switch, nothing changes".=C2=A0 What X =
does when not switching is not variant's problem.<br></div><div><br>&qu=
ot;just always only specify the basic guarantee and be done with it." =
of course also requires either a type that is nothrow default constructible=
, or limiting what variant can do.=C2=A0 I'm hearing a bit of push-back=
on the latter part.=C2=A0 So what else could you do when none of the types=
can be constructed?=C2=A0 If people can't agree on limited functionali=
ty, then its either double-buffer or empty or invalid.=C2=A0 I'm at dou=
ble-buffer > invalid > empty > limited functionality.<br><br><br><=
/div><div>[*] "whenever possible" means as long as it maintains w=
hatever invariants we decide for variant.<br><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(2=
04,204,204);padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><=
div class=3D"gmail_quote"><div></div></div></div></div><div class=3D""><div=
class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113fb8c0887cfc0520d48831--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 13:37:30 -0700 (PDT)
Raw View
------=_Part_548_1415880145.1443472650249
Content-Type: multipart/alternative;
boundary="----=_Part_549_428419643.1443472650250"
------=_Part_549_428419643.1443472650250
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 28, 2015 at 4:02:31 PM UTC-4, Tony V E wrote:
>
> On Sat, Sep 26, 2015 at 2:33 PM, Nicol Bolas <jmck...@gmail.com=20
> <javascript:>> wrote:
>
>> On Saturday, September 26, 2015 at 1:21:34 PM UTC-4, Vicente J. Botet=20
>> Escriba wrote:
>>>
>>> Le 26/09/15 19:10, Vicente J. Botet Escriba a =C3=A9crit :=20
>>> > Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :=20
>>> >> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Krauss=20
>>> wrote:=20
>>> >=20
>>> >>=20
>>> >> This also means we don't have to give types default constructors jus=
t=20
>>> to=20
>>> >> satisfy C++ usage anymore. Just declare an `optional` of it,=20
>>> >> construct it=20
>>> >> empty, then initialize it later on when you're ready to properly do=
=20
>>> >> so. You=20
>>> >> can even copy/move out of it when you're ready to pass it to whomeve=
r=20
>>> >> needs=20
>>> >> it.=20
>>> >>=20
>>> >> Do you have any other reasons why we need `variant` to be able to=20
>>> become=20
>>> >> "disengaged/empty/etc"? Note that I said "need", not "prefer". What=
=20
>>> >> *actual=20
>>> >> problems* would such a concept solve for you?=20
>>> > optionals<Ts...> can be implemented more efficiently than=20
>>> > optional<variants<Ts...>>, but I want it to be a model of sum type=20
>>> > nullopt_t + Ts... and be able to visit it all at once. I don't want t=
o=20
>>> > have to check if the optional is engaged and only then do visit the=
=20
>>> > stored value.=20
>>> I want to be able to visit nullable variants like=20
>>>
>>> optionals<T1, T2> o =3D ...;=20
>>> auto x=3D match(o,=20
>>> [](nullopt_t)->U {...},=20
>>> [](T1)->U {...},=20
>>> [](T2)->U {...}=20
>>> );=20
>>>
>>
>> ... why would you not do:
>>
>> variant<monostate, T1, T2> v =3D ...;
>>
>> Why do you need a whole new type for something that a never-empty varian=
t=20
>> gives you by design?
>
>
> because variant doesn't (currently) fallback to monostate, whereas=20
> optionals<Ts...> would.
> Not sure if that is enough of a difference to warrant the class or not.
> Tony
>
To me, I see that as a strength. You can tell the difference between=20
"broken due to exception" and "empty, as set by user". I like that.
And with the construct-first paradigm, your default constructed=20
`variant<monostate, ...>` will start in the valid-but-empty state, which is=
=20
what you generally want.
--=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_549_428419643.1443472650250
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 28, 2015 at 4:02:31 PM UTC-4, Tony V E wrote:<blockquo=
te 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><div class=3D"gma=
il_quote">On Sat, Sep 26, 2015 at 2:33 PM, Nicol Bolas <span dir=3D"ltr">&l=
t;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"UkGlxa=
bBCQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';r=
eturn true;" onclick=3D"this.href=3D'javascript:';return true;">jmc=
k...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
><div>On Saturday, September 26, 2015 at 1:21:34 PM UTC-4, Vicente J. Botet=
Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex">Le 26/09/15 19:10, V=
icente J. Botet Escriba a =C3=A9crit :
<br>> Le 26/09/15 16:51, Nicol Bolas a =C3=A9crit :
<br>>> On Friday, September 25, 2015 at 9:06:36 PM UTC-4, David Kraus=
s wrote:
<br>>
<br>>>
<br>>> This also means we don't have to give types default constr=
uctors just to
<br>>> satisfy C++ usage anymore. Just declare an `optional` of it,=
=20
<br>>> construct it
<br>>> empty, then initialize it later on when you're ready to pr=
operly do=20
<br>>> so. You
<br>>> can even copy/move out of it when you're ready to pass it =
to whomever=20
<br>>> needs
<br>>> it.
<br>>>
<br>>> Do you have any other reasons why we need `variant` to be able=
to become
<br>>> "disengaged/empty/etc"? Note that I said "need&=
quot;, not "prefer". What=20
<br>>> *actual
<br>>> problems* would such a concept solve for you?
<br>> optionals<Ts...> can be implemented more efficiently than=20
<br>> optional<variants<Ts...>>, but I want it to be a model=
of sum type=20
<br>> nullopt_t + Ts... and be able to visit it all at once. I don't=
want to=20
<br>> have to check if the optional is engaged and only then do visit th=
e=20
<br>> stored value.
<br>I want to be able to visit nullable variants like
<br>
<br>optionals<T1, T2> o =3D ...;
<br>auto x=3D =C2=A0match(o,
<br>=C2=A0 =C2=A0 =C2=A0[](nullopt_t)->U {...},
<br>=C2=A0 =C2=A0 =C2=A0[](T1)->U {...},
<br>=C2=A0 =C2=A0 =C2=A0[](T2)->U {...}
<br>);
<br></blockquote></div></div><div><br>... why would you not do:<br><br><div=
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);b=
order-style:solid;border-width:1px;word-wrap:break-word"><code><div><span s=
tyle=3D"color:#000">variant</span><span style=3D"color:#660"><</span><sp=
an style=3D"color:#000">monostate</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> T1</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> T2</span><span style=3D"color:#660">></span><sp=
an style=3D"color:#000"> v </span><span style=3D"color:#660">=3D</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">...;</span></div>=
</code></div><br></div>Why do you need a whole new type for something that =
a never-empty variant gives you by design?</blockquote><div><br></div><div>=
because variant doesn't (currently) fallback to monostate, whereas opti=
onals<Ts...> would.<br></div><div>Not sure if that is enough of a dif=
ference to warrant the class or not.<br></div><div>Tony<br></div></div></di=
v></div></blockquote><div><br>To me, I see that as a strength. You can tell=
the difference between "broken due to exception" and "empty=
, as set by user". I like that.<br><br>And with the construct-first pa=
radigm, your default constructed `variant<monostate, ...>` will start=
in the valid-but-empty state, which is what you generally want.</div>
<p></p>
-- <br />
<br />
--- <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 />
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_549_428419643.1443472650250--
------=_Part_548_1415880145.1443472650249--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 13:39:39 -0700 (PDT)
Raw View
------=_Part_917_707070412.1443472779596
Content-Type: multipart/alternative;
boundary="----=_Part_918_1242721331.1443472779596"
------=_Part_918_1242721331.1443472779596
Content-Type: text/plain; charset=UTF-8
On Monday, September 28, 2015 at 3:35:44 PM UTC-4, Matt Calabrese wrote:
>
> On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <tvan...@gmail.com
> <javascript:>> wrote:
>>
>> I'm pretty sure the idea would be to only go out of our way to cover the
>> problems that are introduced by variant. ie the problems of destroying and
>> constructing in the same place, without being left in the in-between state.
>>
>> So we might get a strong guarantee for type-changes, but no guarantee at
>> all when just assigning an X to an X. That doesn't seem that too odd to
>> me, because variant is just taking care of its part of the equation.
>>
>
> That seems pretty odd to me and you'd not be providing the strong
> exception guarantee anymore. Without that, how would someone correctly rely
> on the *partial* strong exception guarantee in their code (especially if
> it's generic code operating on dependent field types)? They'd have to
> manually check to see that which() is not the same, and only then they'd be
> sure to get the strong exception guarantee before doing the assignment. If
> which() is equal and their type only specifies the basic guarantee, or if
> the field type is dependent so they don't know whether or not assignment
> has the strong or basic guarantee, then they'd have to do something more
> complicated to keep track of the old state, assuming they need to get back
> to it.
>
> This just seems really inconsistent to me. If you decide that the strong
> exception guarantee really is important for assignment, I think it needs to
> be all-or-nothing. Otherwise you're only providing the basic guarantee
> anyway, and in that case, I'd just embrace the basic guarantee whether the
> underlying field types are the same or not. My personal thoughts are that
> we should just always only specify the basic guarantee and be done with it.
>
It's sorta consistent, if you think of it like this:
Variant will always give you *at least* the guarantee that the underlying
type(s) offer.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_918_1242721331.1443472779596
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 28, 2015 at 3:35:44 PM UTC-4, Matt Calabrese wrote:<bl=
ockquote 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><div class=
=3D"gmail_quote">On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <span dir=3D"lt=
r"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"J=
08jczDACQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&#=
39;;return true;" onclick=3D"this.href=3D'javascript:';return true;=
">tvan...@gmail.com</a>></span> wrote:<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"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div>I'm pretty sure the idea would be =
to only go out of our way to cover the problems that are introduced by vari=
ant.=C2=A0 ie the problems of destroying and constructing in the same place=
, without being left in the in-between state.<br><br></div><div>So we might=
get a strong guarantee for type-changes, but no guarantee at all when just=
assigning an X to an X.=C2=A0 That doesn't seem that too odd to me, be=
cause variant is just taking care of its part of the equation.</div></div><=
/div></div></blockquote><div><br></div><div>That seems pretty odd to me and=
you'd not be providing the strong exception guarantee anymore. Without=
that, how would someone correctly rely on the *partial* strong exception g=
uarantee in their code (especially if it's generic code operating on de=
pendent field types)? They'd have to manually check to see that which()=
is not the same, and only then they'd be sure to get the strong except=
ion guarantee before doing the assignment. If which() is equal and their ty=
pe only specifies the basic guarantee, or if the field type is dependent so=
they don't know whether or not assignment has the strong or basic guar=
antee, then they'd have to do something more complicated to keep track =
of the old state, assuming they need to get back to it.</div><div><br></div=
><div>This just seems really inconsistent to me. If you decide that the str=
ong exception guarantee really is important for assignment, I think it need=
s to be all-or-nothing. Otherwise you're only providing the basic guara=
ntee anyway, and in that case, I'd just embrace the basic guarantee whe=
ther the underlying field types are the same or not. My personal thoughts a=
re that we should just always only specify the basic guarantee and be done =
with it.<br></div></div></div></div></blockquote><div><br>It's sorta co=
nsistent, if you think of it like this:<br><br>Variant will always give you=
<i>at least</i> the guarantee that the underlying type(s) offer.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_918_1242721331.1443472779596--
------=_Part_917_707070412.1443472779596--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Sep 2015 13:44:49 -0700 (PDT)
Raw View
------=_Part_598_1393416124.1443473089645
Content-Type: multipart/alternative;
boundary="----=_Part_599_90614817.1443473089646"
------=_Part_599_90614817.1443473089646
Content-Type: text/plain; charset=UTF-8
On Monday, September 28, 2015 at 4:28:02 PM UTC-4, Tony V E wrote:
>
> On Mon, Sep 28, 2015 at 3:35 PM, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-pr...@isocpp.org <javascript:>> wrote:
>
> On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <tvan...@gmail.com
> <javascript:>> wrote:
>
> I'm pretty sure the idea would be to only go out of our way to cover the
> problems that are introduced by variant. ie the problems of destroying and
> constructing in the same place, without being left in the in-between state.
>
> So we might get a strong guarantee for type-changes, but no guarantee at
> all when just assigning an X to an X. That doesn't seem that too odd to
> me, because variant is just taking care of its part of the equation.
>
>
> That seems pretty odd to me and you'd not be providing the strong
> exception guarantee anymore. Without that, how would someone correctly rely
> on the *partial* strong exception guarantee in their code (especially if
> it's generic code operating on dependent field types)? They'd have to
> manually check to see that which() is not the same, and only then they'd be
> sure to get the strong exception guarantee before doing the assignment. If
> which() is equal and their type only specifies the basic guarantee, or if
> the field type is dependent so they don't know whether or not assignment
> has the strong or basic guarantee, then they'd have to do something more
> complicated to keep track of the old state, assuming they need to get back
> to it.
>
> This just seems really inconsistent to me. If you decide that the strong
> exception guarantee really is important for assignment, I think it needs to
> be all-or-nothing. Otherwise you're only providing the basic guarantee
> anyway, and in that case, I'd just embrace the basic guarantee whether the
> underlying field types are the same or not. My personal thoughts are that
> we should just always only specify the basic guarantee and be done with it.
>
>
>
> I think whenever possible[*], variant<X> should act like X. In my mind,
> that overrides variant's aspirations. So assignment should assign straight
> through.
>
> I'm not sure if is enough for me to drop the strong guarantee. If
> noexcept() could tell the difference between strong and basic... that might
> be interesting.
>
> I just see it as orthogonal: "I manage switching types. If I can't switch,
> nothing changes". What X does when not switching is not variant's problem.
>
Also, one thing that we should not encourage is the use of `variant<X>`
purely as a way to force a type to offer the strong exception guarantee.
Though as a separate proposal, perhaps someone could create a type that
does force a type to offer the strong exception guarantee. Not to be used
with `variant` of course, but just as a generally useful thing when you're
dealing with poorly-behaved types.
"just always only specify the basic guarantee and be done with it." of
> course also requires either a type that is nothrow default constructible,
> or limiting what variant can do. I'm hearing a bit of push-back on the
> latter part. So what else could you do when none of the types can be
> constructed? If people can't agree on limited functionality, then its
> either double-buffer or empty or invalid. I'm at double-buffer > invalid >
> empty > limited functionality.
>
Agreed, particularly with Williams' demonstration of the minimal costs of
double-buffering.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_599_90614817.1443473089646
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 28, 2015 at 4:28:02 PM UTC-4, Tony V E wrote:<blockquo=
te 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><div>On Mon, Sep =
28, 2015 at 3:35 PM, 'Matt Calabrese' via ISO C++ Standard - Future=
Proposals <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"OfRqDQvDCQAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">std-pr...@isocpp.org</a>></span> wrote:<br><=
blockquote style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr"><div><div><span>On Mon, Sep 28,=
2015 at 12:19 PM, Tony V E <span dir=3D"ltr"><<a href=3D"javascript:" t=
arget=3D"_blank" gdf-obfuscated-mailto=3D"OfRqDQvDCQAJ" rel=3D"nofollow" on=
mousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"thi=
s.href=3D'javascript:';return true;">tvan...@gmail.com</a>></spa=
n> wrote:<blockquote style=3D"margin:0px 0px 0px 0.8ex;border-left:1px soli=
d rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div><div>I'=
m pretty sure the idea would be to only go out of our way to cover the prob=
lems that are introduced by variant.=C2=A0 ie the problems of destroying an=
d constructing in the same place, without being left in the in-between stat=
e.<br><br></div><div>So we might get a strong guarantee for type-changes, b=
ut no guarantee at all when just assigning an X to an X.=C2=A0 That doesn&#=
39;t seem that too odd to me, because variant is just taking care of its pa=
rt of the equation.</div></div></div></div></blockquote><div><br></div></sp=
an><div>That seems pretty odd to me and you'd not be providing the stro=
ng exception guarantee anymore. Without that, how would someone correctly r=
ely on the *partial* strong exception guarantee in their code (especially i=
f it's generic code operating on dependent field types)? They'd hav=
e to manually check to see that which() is not the same, and only then they=
'd be sure to get the strong exception guarantee before doing the assig=
nment. If which() is equal and their type only specifies the basic guarante=
e, or if the field type is dependent so they don't know whether or not =
assignment has the strong or basic guarantee, then they'd have to do so=
mething more complicated to keep track of the old state, assuming they need=
to get back to it.</div><div><br></div><div>This just seems really inconsi=
stent to me. If you decide that the strong exception guarantee really is im=
portant for assignment, I think it needs to be all-or-nothing. Otherwise yo=
u're only providing the basic guarantee anyway, and in that case, I'=
;d just embrace the basic guarantee whether the underlying field types are =
the same or not. My personal thoughts are that we should just always only s=
pecify the basic guarantee and be done with it.<br></div></div></div></div>=
</blockquote><div><br></div><div><br>I think whenever possible[*], variant&=
lt;X> should act like X.=C2=A0 In my mind, that overrides variant's =
aspirations. So assignment should assign straight through.<br><br></div><di=
v>I'm not sure if is enough for me to drop the strong guarantee.=C2=A0 =
If noexcept() could tell the difference between strong and basic... that mi=
ght be interesting.<br><br></div><div>I just see it as orthogonal: "I =
manage switching types. If I can't switch, nothing changes".=C2=A0=
What X does when not switching is not variant's problem.<br></div></di=
v></div></div></blockquote><div><br>Also, one thing that we should not enco=
urage is the use of=20
`variant<X>` purely as a way to force a type to offer the strong=20
exception guarantee.<br><br>Though as a separate proposal, perhaps=20
someone could create a type that does force a type to offer the strong=20
exception guarantee. Not to be used with `variant` of course, but just=20
as a generally useful thing when you're dealing with poorly-behaved=20
types.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div><div></div><div>"just always only specify the basic=
guarantee and be done with it." of course also requires either a type=
that is nothrow default constructible, or limiting what variant can do.=C2=
=A0 I'm hearing a bit of push-back on the latter part.=C2=A0 So what el=
se could you do when none of the types can be constructed?=C2=A0 If people =
can't agree on limited functionality, then its either double-buffer or =
empty or invalid.=C2=A0 I'm at double-buffer > invalid > empty &g=
t; limited functionality.<br></div></div></div></div></blockquote><div><br>=
Agreed, particularly with Williams' demonstration of the minimal costs =
of double-buffering.</div>
<p></p>
-- <br />
<br />
--- <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 />
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_599_90614817.1443473089646--
------=_Part_598_1393416124.1443473089645--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 16:50:13 -0400
Raw View
--001a11c377a212e0a80520d4d8b2
Content-Type: text/plain; charset=UTF-8
One more idea (as if we didn't have enough already), based somewhat on
Matt's idea of using optional<variant<T, U>>.
Every time I see that, I think I'd rather use variant<T, optional<U>>
(assuming U is the offending class that doesn't offer the right nothrow
operations). Kind of pointing out the "bad guy". Of course with multiple
bad types, this would be less efficient than a single "empty" flag for all
types.
However, taking it one step further, for variant-with-invalid, you could
actually (without extra space) keep track of _which_ type caused the
variant to become invalid (or which type it was before it became invalid.)
ie set the high-bit on the index when the variant becomes invalid.
Not sure if that is useful, or might lead to a more interesting idea. (I
didn't lead me anywhere else, but I'm just throwing it out there for others)
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c377a212e0a80520d4d8b2
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div><div><div><div>One more idea (as if we didn'=
t have enough already), based somewhat on Matt's idea of using optional=
<variant<T, U>>.<br><br></div>Every time I see that, I think I&=
#39;d rather use variant<T, optional<U>> (assuming U is the off=
ending class that doesn't offer the right nothrow operations).=C2=A0 Ki=
nd of pointing out the "bad guy".=C2=A0 Of course with multiple b=
ad types, this would be less efficient than a single "empty" flag=
for all types.<br><br></div>However, taking it one step further, for varia=
nt-with-invalid, you could actually (without extra space) keep track of _wh=
ich_ type caused the variant to become invalid (or which type it was before=
it became invalid.) <br><br></div>ie set the high-bit on the index when th=
e variant becomes invalid.<br><br></div>Not sure if that is useful, or migh=
t lead to a more interesting idea.=C2=A0 (I didn't lead me anywhere els=
e, but I'm just throwing it out there for others)<br><br></div>Tony<br>=
<div><div><br></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c377a212e0a80520d4d8b2--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 28 Sep 2015 13:56:42 -0700
Raw View
--089e0153660848ba030520d4ef21
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 1:27 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>
> On Mon, Sep 28, 2015 at 3:35 PM, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>> On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <tvaneerd@gmail.com> wrote:
>>>
>>> I'm pretty sure the idea would be to only go out of our way to cover the
>>> problems that are introduced by variant. ie the problems of destroying and
>>> constructing in the same place, without being left in the in-between state.
>>>
>>> So we might get a strong guarantee for type-changes, but no guarantee at
>>> all when just assigning an X to an X. That doesn't seem that too odd to
>>> me, because variant is just taking care of its part of the equation.
>>>
>>
>> That seems pretty odd to me and you'd not be providing the strong
>> exception guarantee anymore. Without that, how would someone correctly rely
>> on the *partial* strong exception guarantee in their code (especially if
>> it's generic code operating on dependent field types)? They'd have to
>> manually check to see that which() is not the same, and only then they'd be
>> sure to get the strong exception guarantee before doing the assignment. If
>> which() is equal and their type only specifies the basic guarantee, or if
>> the field type is dependent so they don't know whether or not assignment
>> has the strong or basic guarantee, then they'd have to do something more
>> complicated to keep track of the old state, assuming they need to get back
>> to it.
>>
>> This just seems really inconsistent to me. If you decide that the strong
>> exception guarantee really is important for assignment, I think it needs to
>> be all-or-nothing. Otherwise you're only providing the basic guarantee
>> anyway, and in that case, I'd just embrace the basic guarantee whether the
>> underlying field types are the same or not. My personal thoughts are that
>> we should just always only specify the basic guarantee and be done with it.
>>
>
>
> I think whenever possible[*], variant<X> should act like X. In my mind,
> that overrides variant's aspirations. So assignment should assign straight
> through.
>
> I'm not sure if is enough for me to drop the strong guarantee. If
> noexcept() could tell the difference between strong and basic... that might
> be interesting.
>
Yeah, I like the idea, though I don't think it can be a part of noexcept,
since in the general case multiple function arguments can be modified
(you'd probably want to specify behavior specific to each mutating argument
rather than to the expression as a whole). A trait for assignment might be
good, though even that might be little more difficult than it initially
seems, since a move-assign operation, for instance, technically mutates two
operands. Even a trait would have to tell you information about both
operands separately to be complete.
On Mon, Sep 28, 2015 at 1:27 PM, Tony V E <tvaneerd@gmail.com> wrote:
> I just see it as orthogonal: "I manage switching types. If I can't switch,
> nothing changes". What X does when not switching is not variant's problem.
>
Right, but if people can only rely on the strong guarantee when lhs.which()
!= rhs.which() I just question why we are paying for the overhead of things
like double storage, given that we wouldn't get an overall strong exception
guarantee anyway. In those cases, at a minimum, it seems like it is
pointless to try to double buffer since users cannot in practice rely on
the strong guarantee for general assignment there anyway. My personal
interpretation of this is that without some kind of separate traits, we'd
either only ever specify the nothrow or basic guarantee for variant (and
require a Boost-like fallback if someone tries to perform assignment,
forgetting about double buffering), or we'd do full double buffering
whenever it is necessary to *actually* provide the strong guarantee, even
for assignments where the underlying field types are the same.
On Mon, Sep 28, 2015 at 1:27 PM, Tony V E <tvaneerd@gmail.com> wrote:
> "just always only specify the basic guarantee and be done with it." of
> course also requires either a type that is nothrow default constructible,
> or limiting what variant can do. I'm hearing a bit of push-back on the
> latter part. So what else could you do when none of the types can be
> constructed? If people can't agree on limited functionality, then its
> either double-buffer or empty or invalid. I'm at double-buffer > invalid >
> empty > limited functionality.
>
Yeah. I know that there is push-back on placing requirements on assignment
in that case, and against a fallback, though I still do think it is a solid
option (in my opinion the best, but short of that, it at the very least is
a *valid* option). I had a paper on this topic that I was working on this
past week, but I didn't manage to complete it before the deadline. I'll try
to at least distribute a draft before Kona. I'm not yet sure if I'll be
able to attend though, but I'd like to in order to present an unrelated
proposal anyway.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0153660848ba030520d4ef21
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 M=
on, Sep 28, 2015 at 1:27 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mail=
to:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><br><div class=3D"gmail_extra">=
<br><div class=3D"gmail_quote"><div><div class=3D"h5">On Mon, Sep 28, 2015 =
at 3:35 PM, 'Matt Calabrese' via ISO C++ Standard - Future Proposal=
s <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@isocpp.org" target=
=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<br><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1=
ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<span>On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <span dir=3D"ltr"><<a h=
ref=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>&=
gt;</span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:r=
gb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extr=
a"><div class=3D"gmail_quote"><div>I'm pretty sure the idea would be to=
only go out of our way to cover the problems that are introduced by varian=
t.=C2=A0 ie the problems of destroying and constructing in the same place, =
without being left in the in-between state.<br><br></div><div>So we might g=
et a strong guarantee for type-changes, but no guarantee at all when just a=
ssigning an X to an X.=C2=A0 That doesn't seem that too odd to me, beca=
use variant is just taking care of its part of the equation.</div></div></d=
iv></div></blockquote><div><br></div></span><div>That seems pretty odd to m=
e and you'd not be providing the strong exception guarantee anymore. Wi=
thout that, how would someone correctly rely on the *partial* strong except=
ion guarantee in their code (especially if it's generic code operating =
on dependent field types)? They'd have to manually check to see that wh=
ich() is not the same, and only then they'd be sure to get the strong e=
xception guarantee before doing the assignment. If which() is equal and the=
ir type only specifies the basic guarantee, or if the field type is depende=
nt so they don't know whether or not assignment has the strong or basic=
guarantee, then they'd have to do something more complicated to keep t=
rack of the old state, assuming they need to get back to it.</div><div><br>=
</div><div>This just seems really inconsistent to me. If you decide that th=
e strong exception guarantee really is important for assignment, I think it=
needs to be all-or-nothing. Otherwise you're only providing the basic =
guarantee anyway, and in that case, I'd just embrace the basic guarante=
e whether the underlying field types are the same or not. My personal thoug=
hts are that we should just always only specify the basic guarantee and be =
done with it.<br></div></div></div></div></blockquote><div><br></div></div>=
</div><div><br>I think whenever possible[*], variant<X> should act li=
ke X.=C2=A0 In my mind, that overrides variant's aspirations. So assign=
ment should assign straight through.<br><br></div><div>I'm not sure if =
is enough for me to drop the strong guarantee.=C2=A0 If noexcept() could te=
ll the difference between strong and basic... that might be interesting.<br=
></div></div></div></div></blockquote><div><br></div><div>Yeah, I like the =
idea, though I don't think it can be a part of noexcept, since in the g=
eneral case multiple function arguments can be modified (you'd probably=
want to specify behavior specific to each mutating argument rather than to=
the expression as a whole). A trait for assignment might be good, though e=
ven that might be little more difficult than it initially seems, since a mo=
ve-assign operation, for instance, technically mutates two operands. Even a=
trait would have to tell you information about both operands separately to=
be complete.</div><div><br></div><div>On Mon, Sep 28, 2015 at 1:27 PM, Ton=
y V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" targ=
et=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:</div><blockquot=
e 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-lef=
t:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quot=
e"><div>I just see it as orthogonal: "I manage switching types. If I c=
an't switch, nothing changes".=C2=A0 What X does when not switchin=
g is not variant's problem.<br></div></div></div></div></blockquote><di=
v><br></div><div>Right, but if people can only rely on the strong guarantee=
when lhs.which() !=3D rhs.which() I just question why we are paying for th=
e overhead of things like double storage, given that we wouldn't get an=
overall strong exception guarantee anyway. In those cases, at a minimum, i=
t seems like it is pointless to try to double buffer since users cannot in =
practice rely on the strong guarantee for general assignment there anyway. =
My personal interpretation of this is that without some kind of separate tr=
aits, we'd either only ever specify the nothrow or basic guarantee for =
variant (and require a Boost-like fallback if someone tries to perform assi=
gnment, forgetting about double buffering), or we'd do full double buff=
ering whenever it is necessary to <i>actually</i>=C2=A0provide the strong g=
uarantee, even for assignments where the underlying field types are the sam=
e.</div><div><br></div><div>On Mon, Sep 28, 2015 at 1:27 PM, Tony V E=C2=A0=
<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blan=
k">tvaneerd@gmail.com</a>></span>=C2=A0wrote:<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>"just always only specify the basic guarantee and be done with it.&qu=
ot; of course also requires either a type that is nothrow default construct=
ible, or limiting what variant can do.=C2=A0 I'm hearing a bit of push-=
back on the latter part.=C2=A0 So what else could you do when none of the t=
ypes can be constructed?=C2=A0 If people can't agree on limited functio=
nality, then its either double-buffer or empty or invalid.=C2=A0 I'm at=
double-buffer > invalid > empty > limited functionality.<br></div=
></div></div></div></blockquote><div><br></div><div>Yeah. I know that there=
is push-back on placing requirements on assignment in that case, and again=
st a fallback, though I still do think it is a solid option (in my opinion =
the best, but short of that, it at the very least is a *valid* option). I h=
ad a paper on this topic that I was working on this past week, but I didn&#=
39;t manage to complete it before the deadline. I'll try to at least di=
stribute a draft before Kona. I'm not yet sure if I'll be able to a=
ttend though, but I'd like to in order to present an unrelated proposal=
anyway.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0153660848ba030520d4ef21--
.
Author: Larry Evans <cppljevans@suddenlink.net>
Date: Mon, 28 Sep 2015 16:06:09 -0500
Raw View
On 09/23/2015 01:43 PM, Larry Evans wrote:
> On 09/23/2015 12:59 PM, Tony V E wrote:
>>
>>
>> On Wed, Sep 23, 2015 at 8:28 AM, Larry Evans <cppljevans@suddenlink.net
>> <mailto:cppljevans@suddenlink.net>> wrote:
>>
>> On 09/23/2015 02:11 AM, David Krauss wrote:
>> >
>> >> On 2015=E2=80=9309=E2=80=9323, at 11:44 AM, Nicol Bolas <jmckesso=
n@gmail.com <mailto:jmckesson@gmail.com>
>> >> <mailto:jmckesson@gmail.com <mailto:jmckesson@gmail.com>>> wrote:
>> [snip]
>> >> ... are you kidding? Just on visitation /alone/, I'd never use a
>> >> `union` again.
>> >
>> > Note that visitation can=E2=80=99t tell duplicate members apart=E2=
=80=A6 Sorry, I meant
>> > to ask for use-cases distinct from sum types.
>> >
>> It can if the visitor dispatches on the index instead of
>> the type while holding the variant as a reference:
>>
>> template<std::size_t I>
>> using index=3Dstd::integral_constant<std::size_t,I>;
>>
>> struct visitor
>> {
>> variant<T0,T1>& my_var;
>> visitor(variant<T0,T1>& a_var)
>> :my_var(a_var)
>> {}
>> void visit(index<0>)
>> { //do something with get<0>(my_var)
>> }
>> void visit(index<1>)
>> { //do something with get<1>(my_var)
>> }
>> };
>>
>>
>> I don't think the index<N> signature is enough to differentiate by-type
>> visitation from by-index visitation. Because some day I'll have (via
>> templates of course) a variant<index<1>, index<0>> class, and be really
>> sad.
>>
>> The above is OK if visitation is initiated differently. ie
>> visit_by_index(visitor, var) instead of visit(visitor, var).
>=20
> That's what I meant. Sorry for not explicitly stating this.
>=20
>=20
The code here:
https://github.com/cppljevans/variadic_templates/blob/master/sandbox/indice=
s_val2type/indices_val2type.cpp
allows switching between the two methods by the tag_enum template
parameter to the multi-visitation visit function on line 497.
The output of the code is:
***test< tag_not>()
alternative< 0, 1>
alternative< 1, 2>
alternative< 2, 3>
result=3D3
***test< tag_yes>()
tag_alt< 1, alternative< 0, 1> >
tag_alt< 2, alternative< 1, 2> >
tag_alt< 3, alternative< 2, 3> >
result=3D3
-regards
Larry
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 28 Sep 2015 17:43:33 -0400
Raw View
--001a11403322cb07740520d596df
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 4:56 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Mon, Sep 28, 2015 at 1:27 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>>
>>
>> On Mon, Sep 28, 2015 at 3:35 PM, 'Matt Calabrese' via ISO C++ Standard -
>> Future Proposals <std-proposals@isocpp.org> wrote:
>>
>>> On Mon, Sep 28, 2015 at 12:19 PM, Tony V E <tvaneerd@gmail.com> wrote:
>>>>
>>>> I'm pretty sure the idea would be to only go out of our way to cover
>>>> the problems that are introduced by variant. ie the problems of destroying
>>>> and constructing in the same place, without being left in the in-between
>>>> state.
>>>>
>>>> So we might get a strong guarantee for type-changes, but no guarantee
>>>> at all when just assigning an X to an X. That doesn't seem that too odd to
>>>> me, because variant is just taking care of its part of the equation.
>>>>
>>>
>>> That seems pretty odd to me and you'd not be providing the strong
>>> exception guarantee anymore. Without that, how would someone correctly rely
>>> on the *partial* strong exception guarantee in their code (especially if
>>> it's generic code operating on dependent field types)? They'd have to
>>> manually check to see that which() is not the same, and only then they'd be
>>> sure to get the strong exception guarantee before doing the assignment. If
>>> which() is equal and their type only specifies the basic guarantee, or if
>>> the field type is dependent so they don't know whether or not assignment
>>> has the strong or basic guarantee, then they'd have to do something more
>>> complicated to keep track of the old state, assuming they need to get back
>>> to it.
>>>
>>> This just seems really inconsistent to me. If you decide that the strong
>>> exception guarantee really is important for assignment, I think it needs to
>>> be all-or-nothing. Otherwise you're only providing the basic guarantee
>>> anyway, and in that case, I'd just embrace the basic guarantee whether the
>>> underlying field types are the same or not. My personal thoughts are that
>>> we should just always only specify the basic guarantee and be done with it.
>>>
>>
>>
>> I think whenever possible[*], variant<X> should act like X. In my mind,
>> that overrides variant's aspirations. So assignment should assign straight
>> through.
>>
>> I'm not sure if is enough for me to drop the strong guarantee. If
>> noexcept() could tell the difference between strong and basic... that might
>> be interesting.
>>
>
> Yeah, I like the idea, though I don't think it can be a part of noexcept,
> since in the general case multiple function arguments can be modified
> (you'd probably want to specify behavior specific to each mutating argument
> rather than to the expression as a whole). A trait for assignment might be
> good, though even that might be little more difficult than it initially
> seems, since a move-assign operation, for instance, technically mutates two
> operands. Even a trait would have to tell you information about both
> operands separately to be complete.
>
> On Mon, Sep 28, 2015 at 1:27 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> I just see it as orthogonal: "I manage switching types. If I can't
>> switch, nothing changes". What X does when not switching is not variant's
>> problem.
>>
>
> Right, but if people can only rely on the strong guarantee when
> lhs.which() != rhs.which() I just question why we are paying for the
> overhead of things like double storage, given that we wouldn't get an
> overall strong exception guarantee anyway. In those cases, at a minimum, it
> seems like it is pointless to try to double buffer since users cannot in
> practice rely on the strong guarantee for general assignment there anyway.
> My personal interpretation of this is that without some kind of separate
> traits, we'd either only ever specify the nothrow or basic guarantee for
> variant (and require a Boost-like fallback if someone tries to perform
> assignment, forgetting about double buffering), or we'd do full double
> buffering whenever it is necessary to *actually* provide the strong
> guarantee, even for assignments where the underlying field types are the
> same.
>
> On Mon, Sep 28, 2015 at 1:27 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> "just always only specify the basic guarantee and be done with it." of
>> course also requires either a type that is nothrow default constructible,
>> or limiting what variant can do. I'm hearing a bit of push-back on the
>> latter part. So what else could you do when none of the types can be
>> constructed? If people can't agree on limited functionality, then its
>> either double-buffer or empty or invalid. I'm at double-buffer > invalid >
>> empty > limited functionality.
>>
>
> Yeah. I know that there is push-back on placing requirements on assignment
> in that case, and against a fallback, though I still do think it is a solid
> option (in my opinion the best, but short of that, it at the very least is
> a *valid* option). I had a paper on this topic that I was working on this
> past week, but I didn't manage to complete it before the deadline. I'll try
> to at least distribute a draft before Kona. I'm not yet sure if I'll be
> able to attend though, but I'd like to in order to present an unrelated
> proposal anyway.
>
I definitely agree your option is valid. Sometimes I'm only arguing
against everything in this thread as a devils advocate to make sure I
understand all the repercussions. My biggest problem is that I see
benefits of all the options. Makes it hard to decide.
As for strong vs basic on assignment, the more I think about it, the more I
see it as orthogonal. For (somewhat) similar examples: I don't think
optional<X> turns empty when assignment throws (when the optional was
already an X), and more generically, if there was some magic way to call
X.foo() from variant<X,Y>, I wouldn't expect variant to change do anything
special in that case either (when X was already active).
Tony
--
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11403322cb07740520d596df
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 4:56 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Mon, Sep 28, 2015=
at 1:27 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmai=
l.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> wrote:<br><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w=
idth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding=
-left:1ex"><div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=
=3D"gmail_quote"><div><div>On Mon, Sep 28, 2015 at 3:35 PM, 'Matt Calab=
rese' via ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a =
href=3D"mailto:std-proposals@isocpp.org" target=3D"_blank">std-proposals@is=
ocpp.org</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><span>On Mon, Sep 28, 2015=
at 12:19 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gma=
il.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> wrote:<blockquo=
te class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-widt=
h:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-le=
ft:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quo=
te"><div>I'm pretty sure the idea would be to only go out of our way to=
cover the problems that are introduced by variant.=C2=A0 ie the problems o=
f destroying and constructing in the same place, without being left in the =
in-between state.<br><br></div><div>So we might get a strong guarantee for =
type-changes, but no guarantee at all when just assigning an X to an X.=C2=
=A0 That doesn't seem that too odd to me, because variant is just takin=
g care of its part of the equation.</div></div></div></div></blockquote><di=
v><br></div></span><div>That seems pretty odd to me and you'd not be pr=
oviding the strong exception guarantee anymore. Without that, how would som=
eone correctly rely on the *partial* strong exception guarantee in their co=
de (especially if it's generic code operating on dependent field types)=
? They'd have to manually check to see that which() is not the same, an=
d only then they'd be sure to get the strong exception guarantee before=
doing the assignment. If which() is equal and their type only specifies th=
e basic guarantee, or if the field type is dependent so they don't know=
whether or not assignment has the strong or basic guarantee, then they'=
;d have to do something more complicated to keep track of the old state, as=
suming they need to get back to it.</div><div><br></div><div>This just seem=
s really inconsistent to me. If you decide that the strong exception guaran=
tee really is important for assignment, I think it needs to be all-or-nothi=
ng. Otherwise you're only providing the basic guarantee anyway, and in =
that case, I'd just embrace the basic guarantee whether the underlying =
field types are the same or not. My personal thoughts are that we should ju=
st always only specify the basic guarantee and be done with it.<br></div></=
div></div></div></blockquote><div><br></div></div></div><div><br>I think wh=
enever possible[*], variant<X> should act like X.=C2=A0 In my mind, t=
hat overrides variant's aspirations. So assignment should assign straig=
ht through.<br><br></div><div>I'm not sure if is enough for me to drop =
the strong guarantee.=C2=A0 If noexcept() could tell the difference between=
strong and basic... that might be interesting.<br></div></div></div></div>=
</blockquote><div><br></div></span><div>Yeah, I like the idea, though I don=
't think it can be a part of noexcept, since in the general case multip=
le function arguments can be modified (you'd probably want to specify b=
ehavior specific to each mutating argument rather than to the expression as=
a whole). A trait for assignment might be good, though even that might be =
little more difficult than it initially seems, since a move-assign operatio=
n, for instance, technically mutates two operands. Even a trait would have =
to tell you information about both operands separately to be complete.</div=
><span class=3D""><div><br></div><div>On Mon, Sep 28, 2015 at 1:27 PM, Tony=
V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" targe=
t=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:</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"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote=
"><div>I just see it as orthogonal: "I manage switching types. If I ca=
n't switch, nothing changes".=C2=A0 What X does when not switching=
is not variant's problem.<br></div></div></div></div></blockquote><div=
><br></div></span><div>Right, but if people can only rely on the strong gua=
rantee when lhs.which() !=3D rhs.which() I just question why we are paying =
for the overhead of things like double storage, given that we wouldn't =
get an overall strong exception guarantee anyway. In those cases, at a mini=
mum, it seems like it is pointless to try to double buffer since users cann=
ot in practice rely on the strong guarantee for general assignment there an=
yway. My personal interpretation of this is that without some kind of separ=
ate traits, we'd either only ever specify the nothrow or basic guarante=
e for variant (and require a Boost-like fallback if someone tries to perfor=
m assignment, forgetting about double buffering), or we'd do full doubl=
e buffering whenever it is necessary to <i>actually</i>=C2=A0provide the st=
rong guarantee, even for assignments where the underlying field types are t=
he same.</div><span class=3D""><div><br></div><div>On Mon, Sep 28, 2015 at =
1:27 PM, Tony V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gma=
il.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:<br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>"just always only specify the basic guarantee =
and be done with it." of course also requires either a type that is no=
throw default constructible, or limiting what variant can do.=C2=A0 I'm=
hearing a bit of push-back on the latter part.=C2=A0 So what else could yo=
u do when none of the types can be constructed?=C2=A0 If people can't a=
gree on limited functionality, then its either double-buffer or empty or in=
valid.=C2=A0 I'm at double-buffer > invalid > empty > limited =
functionality.<br></div></div></div></div></blockquote><div><br></div></spa=
n><div>Yeah. I know that there is push-back on placing requirements on assi=
gnment in that case, and against a fallback, though I still do think it is =
a solid option (in my opinion the best, but short of that, it at the very l=
east is a *valid* option). I had a paper on this topic that I was working o=
n this past week, but I didn't manage to complete it before the deadlin=
e. I'll try to at least distribute a draft before Kona. I'm not yet=
sure if I'll be able to attend though, but I'd like to in order to=
present an unrelated proposal anyway.</div></div></div></div></blockquote>=
<div><br><br></div><div>I definitely agree your option is valid.=C2=A0 Some=
times I'm only arguing against everything in this thread as a devils ad=
vocate to make sure I understand all the repercussions.=C2=A0 My biggest pr=
oblem is that I see benefits of all the options.=C2=A0 Makes it hard to dec=
ide.<br><br></div><div>As for strong vs basic on assignment, the more I thi=
nk about it, the more I see it as orthogonal.=C2=A0 For (somewhat) similar =
examples: I don't think optional<X> turns empty when assignment t=
hrows (when the optional was already an X), and more generically, if there =
was some magic way to call X.foo() from variant<X,Y>, I wouldn't =
expect variant to change do anything special in that case either (when X wa=
s already active).<br><br></div><div>Tony<br><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11403322cb07740520d596df--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Tue, 29 Sep 2015 00:55:47 +0200
Raw View
Le 28/09/15 21:54, Tony V E a =C3=A9crit :
> On Sat, Sep 26, 2015 at 10:58 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <
> kaballo86@hotmail.com> wrote:
>
>> On 9/26/2015 11:36 AM, Magnus Fromreide wrote:
>>
>>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>>
>>>> Disengagement is different from merely representing a value which is
>>>> empty
>>>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the var=
iant wrapper, not
>>>> the
>>>> wrapped object which is what goes into visitors. The term =E2=80=9Cemp=
ty state=E2=80=9D
>>>> is
>>>> confusingly ambiguous in this way. Treating the discriminator as a
>>>> user-accessible scalar value adds to the confusion.
>>>>
>>> My concern is that I don't want the types variant<T> and optional<T> to=
be
>>> functionally equivalent, regardless of how variant is implemented.
>>>
>> The fundamental model for `optional<T>` is a union of `nullopt_t` and `T=
`,
>> so it would be reasonable to expect `variant<nullopt_t, T>` to be
>> functionally equivalent.
>>
> If variant falls-back to nullopt_t on exceptions, then yes, they are
> functionally equivalent. But if it doesn't, they are not.
>
>
>> Now, I have to admit to not having paid all that much attention to the b=
ack
>>> and forth of the debate about variant but this should imply that I don'=
t
>>> want to see a publicly accessible empty state in variant.
>>>
>> This does not seem to be related to `optional<T>`, which does not have a=
n
>> empty state. Instead, it defines its active member changing semantics as
>> first switch to `nullopt_t`, then act.
>>
> optional<T> does have an empty state, which is equivalent to switching to
> nullopt_t on failure, (and construction, reset(), etc....).
Hmm, I don't see from where are you deducing that optional switch to=20
nullopt_ton failure.Could you point me to the wording?
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Tue, 29 Sep 2015 01:06:31 +0200
Raw View
Le 28/09/15 21:55, Tony V E a =C3=A9crit :
> On Sat, Sep 26, 2015 at 12:37 PM, Vicente J. Botet Escriba <
> vicente.botet@wanadoo.fr> wrote:
>
>> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
>>
>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>
>> Disengagement is different from merely representing a value which is emp=
ty
>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the varia=
nt wrapper, not the
>> wrapped object which is what goes into visitors. The term =E2=80=9Cempty=
state=E2=80=9D is
>> confusingly ambiguous in this way. Treating the discriminator as a
>> user-accessible scalar value adds to the confusion.
>>
>> My concern is that I don't want the types variant<T> and optional<T> to =
be
>> functionally equivalent, regardless of how variant is implemented.
>>
>> You mean variant<nullopt_t,T> and optional<T> isn't it?
>>
>> I like to see optional<T> as a specialization of variant<nullopt_t, T>
>> providing an interface similar to a smart pointer to T.
>>
>>
> Only if variant falls-back to nullopt_t on exceptions.
Neither optional<T> nor variant<nullopt_t, T> falls-back to nullopt_t on=20
failure if we take Anthony's optimization.
>
>
>
>> I like to see visitation on sum types as pattern matching, so when
>> visiting an optional<T>, I would like to handle disengagement by matchin=
g
>> the nullopt_t type.
>>
>>
> I can agree with that (regardless as to whether variant has empty or not)=
..
>
> I'm tempted to say a const optional<T> is equivalent to a const
> variant<nullopt_t, T>, such that the same generic visitation should work =
on
> both, but if you remove the const, they behave differently, so I don't
> expect them to necessarily support the same interfaces.
> ie if you had some kind of readonly sum_type_view concept or class, they
> could both model or derive from that.
>
>
I don't agree here until you show me that optional<T> falls-back to=20
nullopt_t on failure. IMO, optional<T> support the basic guaranties of T.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 29 Sep 2015 15:37:06 +0800
Raw View
--Apple-Mail=_CEAAAC64-54F4-49FD-8E0D-A491680A2C93
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9329, at 4:37 AM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> To me, I see that as a strength. You can tell the difference between "bro=
ken due to exception" and "empty, as set by user". I like that.
>=20
> And with the construct-first paradigm, your default constructed `variant<=
monostate, ...>` will start in the valid-but-empty state, which is what you=
generally want.
That doesn=E2=80=99t make sense. If it represents brokenness due to an exce=
ption, then there should be an exception_ptr. What difference does it make =
why there is no valid value? It sounds evil to use monostate to represent v=
alues of unrelated stateless types.
Say I have a configuration file, mapping variable names to values. Each val=
ue can be a string, a number, or empty (the variable is merely present), ac=
cording to a dynamic file format. Should the empty values be represented by=
monostate? Having an empty value in a string variable is just as broken as=
having an exceptional state. Having an empty-by-default value in an empty =
variable would be incorrect, since =E2=80=9Cempty=E2=80=9D is actually a re=
cord that the variable was present in the file.
Default construction should not make guesses (or encourage the user to make=
educated guesses) for convenience. Default construct into the invalid stat=
e and let the object be validated when the program has done the actual work=
to make it valid.
Say there=E2=80=99s a completely unrelated variant elsewhere in the program=
, representing tiles on a game board. Some tiles in this game are empty. Sh=
ould they be monostate? It seems reasonable to default-construct an empty b=
oard. But then, the type of an empty tile is really the same as the type of=
a merely-present config variable. That=E2=80=99s nonsense. And we can=E2=
=80=99t validate that every tile was initialized meaningfully for the actua=
l game because they were all initialized meaninglessly at the start.
Now the user refactors default game tiles into something more sophisticated=
, derived from a base class. What=E2=80=99s wrong with giving such a base c=
lass a throwing default constructor? Can=E2=80=99t the user avoid construct=
ing empty tiles she doesn=E2=80=99t want?
Wanting validity by default is setting a low standard for validity. It=E2=
=80=99s easy (and good) to define each sense of emptiness in a program, so =
we don=E2=80=99t need (and shouldn=E2=80=99t want) std::monostate. It=E2=80=
=99s easy to define your own class derived from variant and default-constru=
cting it a particular way. It=E2=80=99s less easy to take an automatically-=
=E2=80=9Cvalid=E2=80=9D variant and set the error state as the default.
--=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/.
--Apple-Mail=_CEAAAC64-54F4-49FD-8E0D-A491680A2C93
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9329, at 4:37 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D""><span style=3D"font-family: Helvetica;=
font-size: 12px; font-style: normal; font-variant: normal; font-weight: no=
rmal; letter-spacing: normal; line-height: normal; orphans: auto; text-alig=
n: start; text-indent: 0px; text-transform: none; white-space: normal; wido=
ws: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; d=
isplay: inline !important;" class=3D"">To me, I see that as a strength. You=
can tell the difference between "broken due to exception" and "empty, as s=
et by user". I like that.</span><br style=3D"font-family: Helvetica; font-s=
ize: 12px; font-style: normal; font-variant: normal; font-weight: normal; l=
etter-spacing: normal; line-height: normal; orphans: auto; text-align: star=
t; text-indent: 0px; text-transform: none; white-space: normal; widows: aut=
o; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><br style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D""><span style=3D"font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant: normal; font-weight: normal; letter=
-spacing: normal; line-height: normal; orphans: auto; text-align: start; te=
xt-indent: 0px; text-transform: none; white-space: normal; widows: auto; wo=
rd-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inli=
ne !important;" class=3D"">And with the construct-first paradigm, your defa=
ult constructed `variant<monostate, ...>` will start in the valid-but=
-empty state, which is what you generally want.</span></div></blockquote></=
div><br class=3D""><div class=3D"">That doesn=E2=80=99t make sense. If it r=
epresents brokenness due to an exception, then there should be an <font fac=
e=3D"Courier" class=3D"">exception_ptr</font>. What difference does it make=
why there is no valid value? It sounds evil to use <font face=3D"Cour=
ier" class=3D"">monostate</font> to represent values of unrelated stateless=
types.</div><div class=3D""><br class=3D""></div><div class=3D"">Say I hav=
e a configuration file, mapping variable names to values. Each value can be=
a string, a number, or empty (the variable is merely present), according t=
o a dynamic file format. Should the empty values be represented by <font fa=
ce=3D"Courier" class=3D"">monostate</font>? Having an empty value in a stri=
ng variable is just as broken as having an exceptional state. Having an emp=
ty-by-default value in an empty variable would be incorrect, since =E2=80=
=9Cempty=E2=80=9D is actually a record that the variable was present in the=
file.</div><div class=3D""><br class=3D""></div><div class=3D"">Default co=
nstruction should not make guesses (or encourage the user to make educated =
guesses) for convenience. Default construct into the invalid state and let =
the object be validated when the program has done the actual work to make i=
t valid.</div><div class=3D""><br class=3D""></div><div class=3D"">Say ther=
e=E2=80=99s a completely unrelated variant elsewhere in the program, repres=
enting tiles on a game board. Some tiles in this game are empty. Should the=
y be monostate? It seems reasonable to default-construct an empty board. Bu=
t then, the type of an empty tile is really the same as the type of a merel=
y-present config variable. That=E2=80=99s nonsense. And we can=E2=80=99t va=
lidate that every tile was initialized meaningfully for the actual game bec=
ause they were all initialized meaninglessly at the start.</div><div class=
=3D""><br class=3D""></div><div class=3D"">Now the user refactors default g=
ame tiles into something more sophisticated, derived from a base class. Wha=
t=E2=80=99s wrong with giving such a base class a throwing default construc=
tor? Can=E2=80=99t the user avoid constructing empty tiles she doesn=E2=80=
=99t want?</div><div class=3D""><br class=3D""></div><div class=3D"">Wantin=
g validity by default is setting a low standard for validity. It=E2=80=99s =
easy (and good) to define each sense of emptiness in a program, so we don=
=E2=80=99t need (and shouldn=E2=80=99t want) <font face=3D"Courier" cl=
ass=3D"">std::monostate</font>. It=E2=80=99s easy to define your own class =
derived from <font face=3D"Courier" class=3D"">variant</font> and default-c=
onstructing it a particular way. It=E2=80=99s less easy to take an automati=
cally-=E2=80=9Cvalid=E2=80=9D variant and set the error state as the defaul=
t.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_CEAAAC64-54F4-49FD-8E0D-A491680A2C93--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 29 Sep 2015 07:41:22 -0500
Raw View
--001a1142f7ecf934e00520e22325
Content-Type: text/plain; charset=UTF-8
On 28 September 2015 at 15:10, Anthony Williams <anthony.ajw@gmail.com>
wrote:
> On 28/09/15 21:07, Nevin Liber wrote:
> > On 28 September 2015 at 03:26, Anthony Williams <anthony.ajw@gmail.com
> > <mailto:anthony.ajw@gmail.com>> wrote:
> >
> > I have submitted a paper describing the requirements for providing
> the
> > strong guarantee for assignment, as outlined in my previous emails.
> >
> >
> > If the variant isn't changing its engaged type, are you still providing
> > the strong guarantee for assignment?
>
*Always* strong guarantee == strong guarantee.
*Mostly* strong guarantee == basic guarantee (or less).
Or to put it another way: <https://youtu.be/xbE8E1ez97M>
None of the variant proposals, including yours, gives anything better than
the basic guarantee.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1142f7ecf934e00520e22325
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 28 September 2015 at 15:10, Anthony Williams <span dir=
=3D"ltr"><<a href=3D"mailto:anthony.ajw@gmail.com" target=3D"_blank">ant=
hony.ajw@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div=
class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><span class=3D"">On 28/09/15 21:07,=
Nevin Liber wrote:<br>
> On 28 September 2015 at 03:26, Anthony Williams <<a href=3D"mailto:=
anthony.ajw@gmail.com">anthony.ajw@gmail.com</a><br>
</span><span class=3D"">> <mailto:<a href=3D"mailto:anthony.ajw@gmail=
..com">anthony.ajw@gmail.com</a>>> wrote:<br>
><br>
>=C2=A0 =C2=A0 =C2=A0I have submitted a paper describing the requirement=
s for providing the<br>
>=C2=A0 =C2=A0 =C2=A0strong guarantee for assignment, as outlined in my =
previous emails.<br>
><br>
><br>
> If the variant isn't changing its engaged type, are you still prov=
iding<br>
> the strong guarantee for assignment?<br></span></blockquote><div><br><=
/div><div><i>Always</i>=C2=A0strong guarantee =3D=3D strong guarantee.</div=
><div><i>Mostly</i> strong guarantee =3D=3D basic guarantee (or less).</div=
><div><br></div><div>Or to put it another way: <<a href=3D"https://youtu=
..be/xbE8E1ez97M">https://youtu.be/xbE8E1ez97M</a>></div><div><br></div><=
div>None of the variant proposals, including yours, gives anything better t=
han the basic guarantee.</div></div>-- <br><div class=3D"gmail_signature">=
=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@=
eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (8=
47) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1142f7ecf934e00520e22325--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Tue, 29 Sep 2015 14:26:04 +0100
Raw View
On 29/09/15 13:41, Nevin Liber wrote:
> On 28 September 2015 at 15:10, Anthony Williams <anthony.ajw@gmail.com
> <mailto:anthony.ajw@gmail.com>> wrote:
>
> On 28/09/15 21:07, Nevin Liber wrote:
> > On 28 September 2015 at 03:26, Anthony Williams <anthony.ajw@gmail.com <mailto:anthony.ajw@gmail.com>
> > <mailto:anthony.ajw@gmail.com <mailto:anthony.ajw@gmail.com>>> wrote:
> >
> > I have submitted a paper describing the requirements for providing the
> > strong guarantee for assignment, as outlined in my previous emails.
> >
> >
> > If the variant isn't changing its engaged type, are you still providing
> > the strong guarantee for assignment?
>
>
> /Always/ strong guarantee == strong guarantee.
> /Mostly/ strong guarantee == basic guarantee (or less).
Agreed.
> None of the variant proposals, including yours, gives anything better
> than the basic guarantee.
I have described what is necessary to provide the strong guarantee.
The C++ committee can ensure we provide it, or can settle for less.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 29 Sep 2015 10:06:12 -0400
Raw View
--001a11341a340b66120520e351fd
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Mon, Sep 28, 2015 at 7:06 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
> Le 28/09/15 21:55, Tony V E a =C3=A9crit :
>
>> On Sat, Sep 26, 2015 at 12:37 PM, Vicente J. Botet Escriba <
>> vicente.botet@wanadoo.fr> wrote:
>>
>> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
>>>
>>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>>
>>> Disengagement is different from merely representing a value which is
>>> empty
>>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the vari=
ant wrapper, not
>>> the
>>> wrapped object which is what goes into visitors. The term =E2=80=9Cempt=
y state=E2=80=9D
>>> is
>>> confusingly ambiguous in this way. Treating the discriminator as a
>>> user-accessible scalar value adds to the confusion.
>>>
>>> My concern is that I don't want the types variant<T> and optional<T> to
>>> be
>>> functionally equivalent, regardless of how variant is implemented.
>>>
>>> You mean variant<nullopt_t,T> and optional<T> isn't it?
>>>
>>> I like to see optional<T> as a specialization of variant<nullopt_t, T>
>>> providing an interface similar to a smart pointer to T.
>>>
>>>
>>> Only if variant falls-back to nullopt_t on exceptions.
>>
> Neither optional<T> nor variant<nullopt_t, T> falls-back to nullopt_t on
> failure if we take Anthony's optimization.
>
>>
>>
>>
>> I like to see visitation on sum types as pattern matching, so when
>>> visiting an optional<T>, I would like to handle disengagement by matchi=
ng
>>> the nullopt_t type.
>>>
>>>
>>> I can agree with that (regardless as to whether variant has empty or
>> not).
>>
>> I'm tempted to say a const optional<T> is equivalent to a const
>> variant<nullopt_t, T>, such that the same generic visitation should work
>> on
>> both, but if you remove the const, they behave differently, so I don't
>> expect them to necessarily support the same interfaces.
>> ie if you had some kind of readonly sum_type_view concept or class, they
>> could both model or derive from that.
>>
>>
>> I don't agree here until you show me that optional<T> falls-back to
> nullopt_t on failure. IMO, optional<T> support the basic guaranties of T.
>
>
> Vicente
>
Whoops, your right. Since optional<T> only switches type when going from
nullopt_t to T (and back), it never really needs to fallback. On failure
to construct T it doesn't "fallback" to nullopt_t, it just _stays_
nullopt_t. And going from T to nullopt_t never fails (except maybe if ~T()
throws, but don't do that, and we could still catch, set nullopt, and
rethrow to end up with nullopt_t here).
I'm not sure how I got confused. I may have been thinking ahead to
optional<T,U,V>. In that case, I can imagine a failed switch from T to U
going to nullopt, although it also could double buffer and retain T.
To me it just seems that "empty" is inherent in optional<>, so I would
fallback to empty on failure to switch from T to U, and not offer stronger
guarantees.
For variant, empty is not inherent (depending on your version of variant),
so it shouldn't fall back.
Tony
> --
>
> --- You received this message because you are subscribed to the Google
> Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=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/.
--001a11341a340b66120520e351fd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 7:06 PM, Vicente J. Botet Escriba <span dir=3D"=
ltr"><<a href=3D"mailto:vicente.botet@wanadoo.fr" target=3D"_blank">vice=
nte.botet@wanadoo.fr</a>></span> wrote:<br><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
">Le 28/09/15 21:55, Tony V E a =C3=A9crit :<span class=3D""><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
On Sat, Sep 26, 2015 at 12:37 PM, Vicente J. Botet Escriba <<br>
<a href=3D"mailto:vicente.botet@wanadoo.fr" target=3D"_blank">vicente.botet=
@wanadoo.fr</a>> wrote:<br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :<br>
<br>
On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:<br>
<br>
Disengagement is different from merely representing a value which is empty<=
br>
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the<br>
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is<br>
confusingly ambiguous in this way. Treating the discriminator as a<br>
user-accessible scalar value adds to the confusion.<br>
<br>
My concern is that I don't want the types variant<T> and optional=
<T> to be<br>
functionally equivalent, regardless of how variant is implemented.<br>
<br>
You mean variant<nullopt_t,T> and optional<T> isn't it?<br>
<br>
I like to see optional<T> as a specialization of variant<nullopt_t=
, T><br>
providing an interface similar to a smart pointer to T.<br>
<br>
<br>
</blockquote>
Only if variant falls-back to nullopt_t on exceptions.<br>
</blockquote></span>
Neither optional<T> nor variant<nullopt_t, T> falls-back to nul=
lopt_t on failure if we take Anthony's optimization.<span class=3D""><b=
r>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
<br>
<br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
I like to see visitation on sum types as pattern matching, so when<br>
visiting an optional<T>, I would like to handle disengagement by matc=
hing<br>
the nullopt_t type.<br>
<br>
<br>
</blockquote>
I can agree with that (regardless as to whether variant has empty or not).<=
br>
<br>
I'm tempted to say a const optional<T> is equivalent to a const<b=
r>
variant<nullopt_t, T>, such that the same generic visitation should w=
ork on<br>
both, but if you remove the const, they behave differently, so I don't<=
br>
expect them to necessarily support the same interfaces.<br>
ie if you had some kind of readonly sum_type_view concept or class, they<br=
>
could both model or derive from that.<br>
<br>
<br>
</blockquote></span>
I don't agree here until you show me that optional<T> falls-back =
to nullopt_t on failure. IMO, optional<T> support the basic guarantie=
s of T.<div class=3D"HOEnZb"><div class=3D"h5"><br>
<br>
Vicente<br></div></div></blockquote><div><br></div><div>Whoops, your right.=
=C2=A0 Since optional<T> only switches type when going from nullopt_t=
to T (and back), it never really needs to fallback.=C2=A0 On failure to co=
nstruct T it doesn't "fallback" to nullopt_t, it just _stays_=
nullopt_t.=C2=A0 And going from T to nullopt_t never fails (except maybe i=
f ~T() throws, but don't do that, and we could still catch, set nullopt=
, and rethrow to end up with nullopt_t here). <br><br></div><div>I'm no=
t sure how I got confused.=C2=A0 I may have been thinking ahead to optional=
<T,U,V>.=C2=A0 In that case, I can imagine a failed switch from T to =
U going to nullopt, although it also could double buffer and retain T.<br><=
br></div><div>To me it just seems that "empty" is inherent in opt=
ional<>, so I would fallback to empty on failure to switch from T to =
U, and not offer stronger guarantees.<br></div><div>For variant, empty is n=
ot inherent (depending on your version of variant), so it shouldn't fal=
l back.<br><br></div><div>Tony<br></div><div><br><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5">
<br>
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps "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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11341a340b66120520e351fd--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 29 Sep 2015 10:08:02 -0400
Raw View
--001a11c223aa9773b60520e3576c
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tue, Sep 29, 2015 at 10:06 AM, Tony V E <tvaneerd@gmail.com> wrote:
>
>
> On Mon, Sep 28, 2015 at 7:06 PM, Vicente J. Botet Escriba <
> vicente.botet@wanadoo.fr> wrote:
>
>> Le 28/09/15 21:55, Tony V E a =C3=A9crit :
>>
>>> On Sat, Sep 26, 2015 at 12:37 PM, Vicente J. Botet Escriba <
>>> vicente.botet@wanadoo.fr> wrote:
>>>
>>> Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :
>>>>
>>>> On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:
>>>>
>>>> Disengagement is different from merely representing a value which is
>>>> empty
>>>> of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the var=
iant wrapper, not
>>>> the
>>>> wrapped object which is what goes into visitors. The term =E2=80=9Cemp=
ty state=E2=80=9D
>>>> is
>>>> confusingly ambiguous in this way. Treating the discriminator as a
>>>> user-accessible scalar value adds to the confusion.
>>>>
>>>> My concern is that I don't want the types variant<T> and optional<T> t=
o
>>>> be
>>>> functionally equivalent, regardless of how variant is implemented.
>>>>
>>>> You mean variant<nullopt_t,T> and optional<T> isn't it?
>>>>
>>>> I like to see optional<T> as a specialization of variant<nullopt_t, T>
>>>> providing an interface similar to a smart pointer to T.
>>>>
>>>>
>>>> Only if variant falls-back to nullopt_t on exceptions.
>>>
>> Neither optional<T> nor variant<nullopt_t, T> falls-back to nullopt_t on
>> failure if we take Anthony's optimization.
>>
>>>
>>>
>>>
>>> I like to see visitation on sum types as pattern matching, so when
>>>> visiting an optional<T>, I would like to handle disengagement by
>>>> matching
>>>> the nullopt_t type.
>>>>
>>>>
>>>> I can agree with that (regardless as to whether variant has empty or
>>> not).
>>>
>>> I'm tempted to say a const optional<T> is equivalent to a const
>>> variant<nullopt_t, T>, such that the same generic visitation should wor=
k
>>> on
>>> both, but if you remove the const, they behave differently, so I don't
>>> expect them to necessarily support the same interfaces.
>>> ie if you had some kind of readonly sum_type_view concept or class, the=
y
>>> could both model or derive from that.
>>>
>>>
>>> I don't agree here until you show me that optional<T> falls-back to
>> nullopt_t on failure. IMO, optional<T> support the basic guaranties of T=
..
>>
>>
>> Vicente
>>
>
> Whoops, your right. Since optional<T> only switches type when going from
> nullopt_t to T (and back), it never really needs to fallback. On failure
> to construct T it doesn't "fallback" to nullopt_t, it just _stays_
> nullopt_t. And going from T to nullopt_t never fails (except maybe if ~T=
()
> throws, but don't do that, and we could still catch, set nullopt, and
> rethrow to end up with nullopt_t here).
>
> I'm not sure how I got confused. I may have been thinking ahead to
> optional<T,U,V>. In that case, I can imagine a failed switch from T to U
> going to nullopt, although it also could double buffer and retain T.
>
> To me it just seems that "empty" is inherent in optional<>, so I would
> fallback to empty on failure to switch from T to U, and not offer stronge=
r
> guarantees.
> For variant, empty is not inherent (depending on your version of variant)=
,
> so it shouldn't fall back.
>
> Tony
>
>
So, to be clear, I don't see (the non-existent) optional<T, U, V> as
equivalent to variant<nullopt_t, T, U, V>.
But optional<T> happens to be equivalent to variant<nullopt_t, 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 a=
n
>> email to std-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>
--=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/.
--001a11c223aa9773b60520e3576c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 29, 2015 at 10:06 AM, Tony V E <span dir=3D"ltr"><<a hre=
f=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.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"><br><div=
class=3D"gmail_extra"><br><div class=3D"gmail_quote"><div><div class=3D"h5=
">On Mon, Sep 28, 2015 at 7:06 PM, Vicente J. Botet Escriba <span dir=3D"lt=
r"><<a href=3D"mailto:vicente.botet@wanadoo.fr" target=3D"_blank">vicent=
e.botet@wanadoo.fr</a>></span> wrote:<br><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
Le 28/09/15 21:55, Tony V E a =C3=A9crit :<span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
On Sat, Sep 26, 2015 at 12:37 PM, Vicente J. Botet Escriba <<br>
<a href=3D"mailto:vicente.botet@wanadoo.fr" target=3D"_blank">vicente.botet=
@wanadoo.fr</a>> wrote:<br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Le 26/09/15 16:36, Magnus Fromreide a =C3=A9crit :<br>
<br>
On Sat, Sep 26, 2015 at 09:06:30AM +0800, David Krauss wrote:<br>
<br>
Disengagement is different from merely representing a value which is empty<=
br>
of state. The term =E2=80=9Cempty state=E2=80=9D appertains to the variant =
wrapper, not the<br>
wrapped object which is what goes into visitors. The term =E2=80=9Cempty st=
ate=E2=80=9D is<br>
confusingly ambiguous in this way. Treating the discriminator as a<br>
user-accessible scalar value adds to the confusion.<br>
<br>
My concern is that I don't want the types variant<T> and optional=
<T> to be<br>
functionally equivalent, regardless of how variant is implemented.<br>
<br>
You mean variant<nullopt_t,T> and optional<T> isn't it?<br>
<br>
I like to see optional<T> as a specialization of variant<nullopt_t=
, T><br>
providing an interface similar to a smart pointer to T.<br>
<br>
<br>
</blockquote>
Only if variant falls-back to nullopt_t on exceptions.<br>
</blockquote></span>
Neither optional<T> nor variant<nullopt_t, T> falls-back to nul=
lopt_t on failure if we take Anthony's optimization.<span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
<br>
<br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
I like to see visitation on sum types as pattern matching, so when<br>
visiting an optional<T>, I would like to handle disengagement by matc=
hing<br>
the nullopt_t type.<br>
<br>
<br>
</blockquote>
I can agree with that (regardless as to whether variant has empty or not).<=
br>
<br>
I'm tempted to say a const optional<T> is equivalent to a const<b=
r>
variant<nullopt_t, T>, such that the same generic visitation should w=
ork on<br>
both, but if you remove the const, they behave differently, so I don't<=
br>
expect them to necessarily support the same interfaces.<br>
ie if you had some kind of readonly sum_type_view concept or class, they<br=
>
could both model or derive from that.<br>
<br>
<br>
</blockquote></span>
I don't agree here until you show me that optional<T> falls-back =
to nullopt_t on failure. IMO, optional<T> support the basic guarantie=
s of T.<div><div><br>
<br>
Vicente<br></div></div></blockquote><div><br></div></div></div><div>Whoops,=
your right.=C2=A0 Since optional<T> only switches type when going fr=
om nullopt_t to T (and back), it never really needs to fallback.=C2=A0 On f=
ailure to construct T it doesn't "fallback" to nullopt_t, it =
just _stays_ nullopt_t.=C2=A0 And going from T to nullopt_t never fails (ex=
cept maybe if ~T() throws, but don't do that, and we could still catch,=
set nullopt, and rethrow to end up with nullopt_t here). <br><br></div><di=
v>I'm not sure how I got confused.=C2=A0 I may have been thinking ahead=
to optional<T,U,V>.=C2=A0 In that case, I can imagine a failed switc=
h from T to U going to nullopt, although it also could double buffer and re=
tain T.<br><br></div><div>To me it just seems that "empty" is inh=
erent in optional<>, so I would fallback to empty on failure to switc=
h from T to U, and not offer stronger guarantees.<br></div><div>For variant=
, empty is not inherent (depending on your version of variant), so it shoul=
dn't fall back.<span class=3D"HOEnZb"><font color=3D"#888888"><br><br><=
/font></span></div><span class=3D"HOEnZb"><font color=3D"#888888"><div>Tony=
<br></div></font></span><span class=3D""><div><br></div></span></div></div>=
</div></blockquote><div><br></div><div>So, to be clear, I don't see (th=
e non-existent) optional<T, U, V> as equivalent to variant<nullopt=
_t, T, U, V>. <br></div><div>But optional<T> happens to be equival=
ent to variant<nullopt_t, T>.<br><br><br></div><blockquote class=3D"g=
mail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_qu=
ote"><span class=3D""><div><br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><d=
iv>
<br>
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps "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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></span></div><br></div></div>
</blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c223aa9773b60520e3576c--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 Sep 2015 07:28:30 -0700 (PDT)
Raw View
------=_Part_5733_1751035528.1443536910836
Content-Type: multipart/alternative;
boundary="----=_Part_5734_508701214.1443536910836"
------=_Part_5734_508701214.1443536910836
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 29, 2015 at 3:38:16 AM UTC-4, David Krauss wrote:
>
> On 2015=E2=80=9309=E2=80=9329, at 4:37 AM, Nicol Bolas <jmck...@gmail.com=
<javascript:>>=20
> wrote:
>
> To me, I see that as a strength. You can tell the difference between=20
> "broken due to exception" and "empty, as set by user". I like that.
>
> And with the construct-first paradigm, your default constructed=20
> `variant<monostate, ...>` will start in the valid-but-empty state, which =
is=20
> what you generally want.
>
>
> That doesn=E2=80=99t make sense. If it represents brokenness due to an ex=
ception,=20
> then there should be an exception_ptr. What difference does it make why=
=20
> there is no valid value? It sounds evil to use monostate to represent=20
> values of unrelated stateless types.
>
.... huh? I think you may have conflated the two statements to be about the=
=20
same thing. The second paragraph is not about what happens on errors; it's=
=20
about how you generally use the type. People who want emptyable variants=20
want the default constructor to construct it as empty. So putting=20
`monostate` first in a never-empty variant will do that for them.
=20
> Say I have a configuration file, mapping variable names to values. Each=
=20
> value can be a string, a number, or empty (the variable is merely present=
),=20
> according to a dynamic file format. Should the empty values be represente=
d=20
> by monostate?
>
Yes.
=20
> Having an empty value in a string variable is just as broken as having an=
=20
> exceptional state.
>
.... I don't understand what you mean here. We're talking about a variant=20
variable, not a string variable.
=20
> Having an empty-by-default value in an empty variable would be incorrect,=
=20
> since =E2=80=9Cempty=E2=80=9D is actually a record that the variable was =
present in the=20
> file.
>
The default is irrelevant, because you're not using it. You're initializing=
=20
the variant with data from the file. So it doesn't matter what it would=20
"default" to; you're either emplacement-constructing it with the proper=20
type or you're emplacement-assigning with the proper type. Either way, each=
=20
loaded value gets a specific type in the typelist.
=20
> Default construction should not make guesses (or encourage the user to=20
> make educated guesses) for convenience. Default construct into the invali=
d=20
> state and let the object be validated when the program has done the actua=
l=20
> work to make it valid.
>
But that requires everyone to check to see if someone did something stupid,=
=20
like not initializing it. It also only offers the basic exception guarantee=
..
Say there=E2=80=99s a completely unrelated variant elsewhere in the program=
,=20
> representing tiles on a game board. Some tiles in this game are empty.=20
> Should they be monostate?
>
Define "empty" within the context of this program. To the extent that I=20
would use variants for such data (rather than a user-defined type), I might=
=20
suggest monostate or not based on what exactly "empty" conveys.
=20
> It seems reasonable to default-construct an empty board. But then, the=20
> type of an empty tile is really the same as the type of a merely-present=
=20
> config variable. That=E2=80=99s nonsense.
>
.... how is that nonsense? It's functionally no different than a=20
`std::string` that represents a variable name and a `std::string` that=20
represents a description of a tile. Same type, different *meaning*.
However, if it really ruffles your sensibilities that much, nobody's=20
forcing you to use `monostate`. You could use `tile_empty` for the game=20
board case and `no_value` for the other case.
`monostate` doesn't change the semantics of `variant`. Any empty type would=
=20
be acceptable there and it would behave in the *exact same way*.
=20
> And we can=E2=80=99t validate that every tile was initialized meaningfull=
y for the=20
> actual game because they were all initialized meaninglessly at the start.
>
If that's so important to you, then take away `empty_tile`'s default=20
constructor.
Problem solved.
=20
> Now the user refactors default game tiles into something more=20
> sophisticated, derived from a base class. What=E2=80=99s wrong with givin=
g such a=20
> base class a throwing default constructor? Can=E2=80=99t the user avoid=
=20
> constructing empty tiles she doesn=E2=80=99t want?
>
At no time have I ever suggested or promoted the view that throwing should=
=20
revert to `monostate` or to any other state. I believe in the strong=20
exception guarantee. Failing that, the next option would be an invalid=20
state that is *only enter-able* in the event of such failures. Not from=20
default construction.
--=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_5734_508701214.1443536910836
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 29, 2015 at 3:38:16 AM UTC-4, David Krauss wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;"> <div><blockquote><div>On 2015=
=E2=80=9309=E2=80=9329, at 4:37 AM, Nicol Bolas <<a href=3D"javascript:"=
target=3D"_blank" gdf-obfuscated-mailto=3D"8sFlQZ7nCQAJ" rel=3D"nofollow" =
onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"t=
his.href=3D'javascript:';return true;">jmck...@gmail.com</a>> wr=
ote:</div><br><div><span style=3D"font-family:Helvetica;font-size:12px;font=
-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;=
line-height:normal;text-align:start;text-indent:0px;text-transform:none;whi=
te-space:normal;word-spacing:0px;float:none;display:inline!important">To me=
, I see that as a strength. You can tell the difference between "broke=
n due to exception" and "empty, as set by user". I like that=
..</span><br style=3D"font-family:Helvetica;font-size:12px;font-style:normal=
;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:n=
ormal;text-align:start;text-indent:0px;text-transform:none;white-space:norm=
al;word-spacing:0px"><br style=3D"font-family:Helvetica;font-size:12px;font=
-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;=
line-height:normal;text-align:start;text-indent:0px;text-transform:none;whi=
te-space:normal;word-spacing:0px"><span style=3D"font-family:Helvetica;font=
-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-=
spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-tra=
nsform:none;white-space:normal;word-spacing:0px;float:none;display:inline!i=
mportant">And with the construct-first paradigm, your default constructed `=
variant<monostate, ...>` will start in the valid-but-empty state, whi=
ch is what you generally want.</span></div></blockquote></div><br><div>That=
doesn=E2=80=99t make sense. If it represents brokenness due to an exceptio=
n, then there should be an <font face=3D"Courier">exception_ptr</font>. Wha=
t difference does it make why there is no valid value? It sounds evil to us=
e=C2=A0<font face=3D"Courier">monostate</font> to represent values of unrel=
ated stateless types.</div></blockquote><div><br>... huh? I think you may h=
ave conflated the two statements to be about the same thing. The second par=
agraph is not about what happens on errors; it's about how you generall=
y use the type. People who want emptyable variants want the default constru=
ctor to construct it as empty. So putting `monostate` first in a never-empt=
y variant will do that for them.<br>=C2=A0</div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div></div><div>Say I have a configuration file, mapping =
variable names to values. Each value can be a string, a number, or empty (t=
he variable is merely present), according to a dynamic file format. Should =
the empty values be represented by <font face=3D"Courier">monostate</font>?=
</div></blockquote><div><br>Yes.<br>=C2=A0</div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div>Having an empty value in a string variable is just a=
s broken as having an exceptional state.</div></blockquote><div><br>... I d=
on't understand what you mean here. We're talking about a variant v=
ariable, not a string variable.<br>=C2=A0</div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div>Having an empty-by-default value in an empty variable=
would be incorrect, since =E2=80=9Cempty=E2=80=9D is actually a record tha=
t the variable was present in the file.</div></blockquote><div><br>The defa=
ult is irrelevant, because you're not using it. You're initializing=
the variant with data from the file. So it doesn't matter what it woul=
d "default" to; you're either emplacement-constructing it wit=
h the proper type or you're emplacement-assigning with the proper type.=
Either way, each loaded value gets a specific type in the typelist.<br>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div></div><div>Defau=
lt construction should not make guesses (or encourage the user to make educ=
ated guesses) for convenience. Default construct into the invalid state and=
let the object be validated when the program has done the actual work to m=
ake it valid.</div></blockquote><div><br>But that requires everyone to chec=
k to see if someone did something stupid, like not initializing it. It also=
only offers the basic exception guarantee.<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div>Say there=E2=80=99s a completely unrelated=
variant elsewhere in the program, representing tiles on a game board. Some=
tiles in this game are empty. Should they be monostate?</div></blockquote>=
<div><br>Define "empty" within the context of this program. To th=
e extent that I would use variants for such data (rather than a user-define=
d type), I might suggest monostate or not based on what exactly "empty=
" conveys.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div>It seems reasonable to default-construct an empty board. But then, th=
e type of an empty tile is really the same as the type of a merely-present =
config variable. That=E2=80=99s nonsense.</div></blockquote><div><br>... ho=
w is that nonsense? It's functionally no different than a `std::string`=
that represents a variable name and a `std::string` that represents a desc=
ription of a tile. Same type, different <i>meaning</i>.<br><br>However, if =
it really ruffles your sensibilities that much, nobody's forcing you to=
use `monostate`. You could use `tile_empty` for the game board case and `n=
o_value` for the other case.<br><br>`monostate` doesn't change the sema=
ntics of `variant`. Any empty type would be acceptable there and it would b=
ehave in the <i>exact same way</i>.<br>=C2=A0</div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div>And we can=E2=80=99t validate that every tile was=
initialized meaningfully for the actual game because they were all initial=
ized meaninglessly at the start.</div></blockquote><div><br>If that's s=
o important to you, then take away `empty_tile`'s default constructor.<=
br><br>Problem solved.<br>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div>Now the user refactors default game tiles into something more =
sophisticated, derived from a base class. What=E2=80=99s wrong with giving =
such a base class a throwing default constructor? Can=E2=80=99t the user av=
oid constructing empty tiles she doesn=E2=80=99t want?</div></blockquote><d=
iv><br>At no time have I ever suggested or promoted the view that throwing =
should revert to `monostate` or to any other state. I believe in the strong=
exception guarantee. Failing that, the next option would be an invalid sta=
te that is <i>only enter-able</i> in the event of such failures. Not from d=
efault construction.</div>
<p></p>
-- <br />
<br />
--- <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 />
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_5734_508701214.1443536910836--
------=_Part_5733_1751035528.1443536910836--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 Sep 2015 08:22:06 -0700 (PDT)
Raw View
------=_Part_330_275200763.1443540126634
Content-Type: multipart/alternative;
boundary="----=_Part_331_1622396992.1443540126634"
------=_Part_331_1622396992.1443540126634
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 29, 2015 at 3:38:16 AM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9329, at 4:37 AM, Nicol Bolas <jmck...@gmail.com=
> wrote:
>
> To me, I see that as a strength. You can tell the difference between=20
> "broken due to exception" and "empty, as set by user". I like that.
>
> And with the construct-first paradigm, your default constructed=20
> `variant<monostate, ...>` will start in the valid-but-empty state, which =
is=20
> what you generally want.
>
>
> That doesn=E2=80=99t make sense. If it represents brokenness due to an ex=
ception,=20
> then there should be an exception_ptr. What difference does it make why=
=20
> there is no valid value? It sounds evil to use monostate to represent=20
> values of unrelated stateless types.
>
> Say I have a configuration file, mapping variable names to values. Each=
=20
> value can be a string, a number, or empty (the variable is merely present=
),=20
> according to a dynamic file format. Should the empty values be represente=
d=20
> by monostate? Having an empty value in a string variable is just as=20
> broken as having an exceptional state. Having an empty-by-default value i=
n=20
> an empty variable would be incorrect, since =E2=80=9Cempty=E2=80=9D is ac=
tually a record=20
> that the variable was present in the file.
>
> Default construction should not make guesses (or encourage the user to=20
> make educated guesses) for convenience. Default construct into the invali=
d=20
> state and let the object be validated when the program has done the actua=
l=20
> work to make it valid.
>
After thinking about this some more, I'm not really sure what the context=
=20
here is.
If I have a function that parses text and returns a variant representing=20
the content of that text, I have no reason to assume that this function=20
will return an invalid variant. That function will have post-conditions,=20
presumably ones that says the return is valid. In a well-behaved program,=
=20
that function will *statically* ensure that the variant is initialized, in=
=20
accord with the data from the file.
For my receiving code to be constantly testing such post-conditions=20
represents a level of defensive programming that is... ludicrous. Do you=20
test reference variables to see if they're NULL? Of course not. The same=20
goes here; if the function did its job, then the variant will have the=20
appropriate value based on the text in question.
There's a difference between defensive programming and *paranoia*. What=20
you're talking about is the latter.
To me, the only code that needs to (conceptually) tell the difference=20
between the two is the code that *tests* the parser.
And even that doesn't really need to recognize the difference between=20
default constructed and specifically initialized with a type. Why? Because=
=20
all it's interested in is whether the function produces the expected=20
results. If you pass in a variable with no assignment, it gets the empty=20
state. Whether that happened by default construction or not is an=20
irrelevant implementation detail. So long as every reasonable syntactically=
=20
correct input string produces the correct output, who cares how it happened=
?
=20
> Say there=E2=80=99s a completely unrelated variant elsewhere in the progr=
am,=20
> representing tiles on a game board. Some tiles in this game are empty.=20
> Should they be monostate? It seems reasonable to default-construct an emp=
ty=20
> board. But then, the type of an empty tile is really the same as the type=
=20
> of a merely-present config variable. That=E2=80=99s nonsense. And we can=
=E2=80=99t validate=20
> that every tile was initialized meaningfully for the actual game because=
=20
> they were all initialized meaninglessly at the start.
>
Again, any decent testing framework ought to be able to test whether the=20
given input produces the expected output. If your test suite is reasonably=
=20
comprehensive, then there's nothing to validate is there?
Wanting validity by default is setting a low standard for validity. It=E2=
=80=99s=20
> easy (and good) to define each sense of emptiness in a program, so we don=
=E2=80=99t=20
> need (and shouldn=E2=80=99t want) std::monostate. It=E2=80=99s easy to de=
fine your own=20
> class derived from variant and default-constructing it a particular way.
That only brings us back to this question: Do my visitors have to check the=
=20
empty state?
If so, then I have to write a bunch of meaningless code, even with your =20
"derived class" solution. If not, then my emptyable variants are *unsafe to=
=20
use*, since visitation won't force me to check the empty state. And=20
remember: static validation is like half the point of visitors.
Nobody seems to recognize that catch-22. Do people who use emptyable=20
variants simply not care about visitation? I mention that because I noticed=
=20
that Eggs.Variant doesn't have a visitation framework. Indeed, most variant=
=20
types out there don't.
=20
> It=E2=80=99s less easy to take an automatically-=E2=80=9Cvalid=E2=80=9D v=
ariant and set the error=20
> state as the default.
>
Error states don't make sense if you have the strong exception guarantee.=
=20
Which we have proven `variant` can provide with minimal overhead.
--=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_331_1622396992.1443540126634
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Tuesday, September 29, 2015 at 3:38:16 AM UTC-4, David Krauss wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;"> <br><div><blockquote><=
div>On 2015=E2=80=9309=E2=80=9329, at 4:37 AM, Nicol Bolas <<a target=3D=
"_blank" rel=3D"nofollow">jmck...@gmail.com</a>> wrote:</div><br><div><s=
pan style=3D"font-family:Helvetica;font-size:12px;font-style:normal;font-va=
riant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;te=
xt-align:start;text-indent:0px;text-transform:none;white-space:normal;word-=
spacing:0px;float:none;display:inline!important">To
me, I see that as a strength. You can tell the difference between=20
"broken due to exception" and "empty, as set by user". =
I like that.</span><br style=3D"font-family:Helvetica;font-size:12px;font-s=
tyle:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;li=
ne-height:normal;text-align:start;text-indent:0px;text-transform:none;white=
-space:normal;word-spacing:0px"><br style=3D"font-family:Helvetica;font-siz=
e:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spac=
ing:normal;line-height:normal;text-align:start;text-indent:0px;text-transfo=
rm:none;white-space:normal;word-spacing:0px"><span style=3D"font-family:Hel=
vetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:nor=
mal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0=
px;text-transform:none;white-space:normal;word-spacing:0px;float:none;displ=
ay:inline!important">And
with the construct-first paradigm, your default constructed=20
`variant<monostate, ...>` will start in the valid-but-empty state,
which is what you generally want.</span></div></blockquote></div><br><div>=
That doesn=E2=80=99t make sense. If it represents brokenness due to an exce=
ption, then there should be an <font face=3D"Courier">exception_ptr</font>.=
What difference does it make why there is no valid value? It sounds evil t=
o use=C2=A0<font face=3D"Courier">monostate</font> to represent values of u=
nrelated stateless types.</div><div><br></div><div>Say
I have a configuration file, mapping variable names to values. Each=20
value can be a string, a number, or empty (the variable is merely=20
present), according to a dynamic file format. Should the empty values be
represented by <font face=3D"Courier">monostate</font>? Having an empty=20
value in a string variable is just as broken as having an exceptional=20
state. Having an empty-by-default value in an empty variable would be=20
incorrect, since =E2=80=9Cempty=E2=80=9D is actually a record that the vari=
able was=20
present in the file.</div><div><br></div><div>Default construction=20
should not make guesses (or encourage the user to make educated guesses)
for convenience. Default construct into the invalid state and let the=20
object be validated when the program has done the actual work to make it
valid.</div></blockquote><div><br>After thinking about this some more, I&#=
39;m not really sure what the context here is.<br><br>If
I have a function that parses text and returns a variant representing=20
the content of that text, I have no reason to assume that this=20
function will return an invalid variant. That function will have post-condi=
tions, presumably ones that says the return is valid. In a
well-behaved program, that function will <i>statically</i> ensure that the=
variant is initialized, in accord with the data from the file.<br><br>For
my receiving code to be constantly testing such post-conditions=20
represents a level of defensive programming that is... ludicrous. Do you
test reference variables to see if they're NULL? Of course not. The=20
same goes here; if the function did its job, then the variant will have=20
the appropriate value based on the text in question.<br><br>There's a d=
ifference between defensive programming and <i>paranoia</i>. What you'r=
e talking about is the latter.<br><br>To me, the only code that needs to (c=
onceptually) tell the difference between the two is the code that <i>tests<=
/i> the parser.<br><br>And
even that doesn't really need to recognize the difference between=20
default constructed and specifically initialized with a type. Why?=20
Because all it's interested in is whether the function produces the=20
expected results. If you pass in a variable with no assignment, it gets=20
the empty state. Whether that happened by default construction or not is
an irrelevant implementation detail. So long as every reasonable=20
syntactically correct input string produces the correct output, who=20
cares how it happened?<br>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div>Say
there=E2=80=99s a completely unrelated variant elsewhere in the program,=
=20
representing tiles on a game board. Some tiles in this game are empty.=20
Should they be monostate? It seems reasonable to default-construct an=20
empty board. But then, the type of an empty tile is really the same as=20
the type of a merely-present config variable. That=E2=80=99s nonsense. And =
we=20
can=E2=80=99t validate that every tile was initialized meaningfully for the=
=20
actual game because they were all initialized meaninglessly at the=20
start.</div></blockquote><div><br>Again, any decent testing framework=20
ought to be able to test whether the given input produces the expected=20
output. If your test suite is reasonably comprehensive, then there's=20
nothing to validate is there?<br><br></div><blockquote style=3D"margin: 0px=
0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1e=
x;" class=3D"gmail_quote">Wanting validity by default is setting a low stan=
dard for validity. It=E2=80=99s
easy (and good) to define each sense of emptiness in a program, so we=20
don=E2=80=99t need (and shouldn=E2=80=99t want)=C2=A0<font face=3D"Courier"=
>std::monostate</font>. It=E2=80=99s easy to define your own class derived =
from <font face=3D"Courier">variant</font>
and default-constructing it a particular way.</blockquote><div><br>That on=
ly brings us back to this question: Do my visitors have to check the empty =
state?<br><br>If
so, then I have to write a bunch of meaningless code, even with your=C2=A0=
=20
"derived class" solution. If not, then my emptyable variants are =
<i>unsafe to use</i>, since visitation won't force me to check the empt=
y state. And remember: static validation is like half the point of visitors=
..<br><br>Nobody
seems to recognize that catch-22. Do people who use emptyable variants=20
simply not care about visitation? I mention that because I noticed that=20
Eggs.Variant doesn't have a visitation framework. Indeed, most variant=
=20
types out there don't.<br>=C2=A0</div><blockquote style=3D"margin: 0px =
0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex=
;" class=3D"gmail_quote"> It=E2=80=99s less easy to take an
automatically-=E2=80=9Cvalid=E2=80=9D variant and set the error state as t=
he default.<br></blockquote><div><br>Error states don't make sense if y=
ou have the strong exception guarantee. Which we have proven `variant` can =
provide with minimal overhead.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_331_1622396992.1443540126634--
------=_Part_330_275200763.1443540126634--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 12:03:49 -0700
Raw View
--047d7b33d3186543820520e7798d
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tue, Sep 29, 2015 at 12:37 AM, David Krauss <potswa@gmail.com> wrote:
>
> That doesn=E2=80=99t make sense. If it represents brokenness due to an ex=
ception,
> then there should be an exception_ptr.
>
Why should it be an exception_ptr, either? You don't need some additional
state for this. Even regarding existing practice, neither of these cases,
"invalid" nor "exception_ptr," are used for other standard library types
when one of their functions throws an exception (thankfully), nor notably
for Boost types. Such states are not needed and just weaken the invariants
of the type by introducing additional kinds of states that require special
handling both in the intrinsic functions of the type and in user code. Why
are people asserting that "variant" is somehow different from other types
and needs to be special here with an invalid state upon exception? The
reason, though one that I still disagree with, is that we consider an
invalid state because, given the suggested requirements of field types, we
would not otherwise be able to satisfy even the basic guarantee for
assignment. Again, my personal thoughts here are that we are simply trying
to force incorrect requirements on the assignment operation and are thereby
creating an unnecessary problem. The resolve this, we are now making our
type more complicated. Instead, maybe we should rethink those requirements.
Whenever you implement a generic function or type, at least if you buy into
the generic programming paradigm used by the STL, you start with an
implementation and you lift out the requirements of the types involved from
that. You cannot start with requirements that simply would be nice to have,
though which may or may not be feasible for the datastructure and the
operations in question, and then expect to be able to actually implement
that hypothetical ideal facility in full and without issue. What we've done
here is we've prematurely decided that *all* operations *must* work
out-of-the-box even when field types have move-constructors that can throw,
and that we *must not* use a field type as a fallback state (I haven't
actually heard the rationale for why we don't want to fallback to a field,
other than that people voted no -- what was the reasoning here, as I was
not there for that discussion? have people considered a field with trivial
special member functions as opposed to simply one that is
noexcept-default-constructible?). IMO, we really should be considering that
the requirements that we started may just be unreasonable. If you implement
assignment and lift out those requirements for assignment, you are only
constraining those particular operations, and notably, in this case the
constraints are easily met *anyway, *without even modifying existing field
types, and it amounts to either explicitly adding the equivalent of an
invalid state (by way of a user just explicitly adding a field that can act
as a fallback), or by alternate means, such as my suggestion regarding
optional.
On Tue, Sep 29, 2015 at 12:37 AM, David Krauss <potswa@gmail.com> wrote:
> Default construction should not make guesses (or encourage the user to
> make educated guesses) for convenience. Default construct into the invali=
d
> state and let the object be validated when the program has done the actua=
l
> work to make it valid.
>
It's not any kind of a guess, it's just a subjective choice that is fully
specified. This is always true of any default, whether it be a
default-constructed value, or a default comparison behavior for something
like std::sort. A variant that initialize to something that isn't "invalid"
is also perfectly fine for construct/init later patterns, but
realistically, users already have the (IMO much better) alternative of
initializing the variable directly upon construction rather than
constructing and initializing later. This is prevents "forgetting" to
further set the value after construction. Especially with lambdas, this
solution is not very difficult for users and it doesn't introduce an
invalid state into your type.
On Tue, Sep 29, 2015 at 12:37 AM, David Krauss <potswa@gmail.com> wrote:
> Wanting validity by default is setting a low standard for validity. It=E2=
=80=99s
> easy (and good) to define each sense of emptiness in a program, so we don=
=E2=80=99t
> need (and shouldn=E2=80=99t want) std::monostate. It=E2=80=99s easy to de=
fine your own
> class derived from variant and default-constructing it a particular way.
> It=E2=80=99s less easy to take an automatically-=E2=80=9Cvalid=E2=80=9D v=
ariant and set the error
> state as the default.
>
It is not setting a low standard for validity. The user is still explicitly
constructing their object and the state is fully specified. If they don't
want a "valid" object then they shouldn't be constructing the object at
that point at all. If you assert that a default-constructed object should
be valid, do you also assert that a std::vector should be invalid instead
of empty on construction (or any other container)? By that logic, such a
type is currently setting a "low standard for validity" too. A user could
simply be using the default-construct and initialize pattern with a vector
just like you suggest someone may do for a variant. You shouldn't be
thinking it's somehow a low standard for validity at all -- what it
actually is is a high standard for strictness of invariants. Just don't
construct the object if you don't want a "valid" object. Initialize upon
construction.
--=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/.
--047d7b33d3186543820520e7798d
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=
ue, Sep 29, 2015 at 12:37 AM, David Krauss <span dir=3D"ltr"><<a href=3D=
"mailto:potswa@gmail.com" target=3D"_blank">potswa@gmail.com</a>></span>=
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 style=3D"word-wrap:break-word"><div>That doesn=
=E2=80=99t make sense. If it represents brokenness due to an exception, the=
n there should be an <font face=3D"Courier">exception_ptr</font>.</div></di=
v></blockquote><div><br></div><div>Why should it be an exception_ptr, eithe=
r? You don't need some additional state for this. Even regarding existi=
ng practice, neither of these cases, "invalid" nor "exceptio=
n_ptr," are used for other standard library types when one of their fu=
nctions throws an exception (thankfully), nor notably for Boost types. Such=
states are not needed and just weaken the invariants of the type by introd=
ucing additional kinds of states that require special handling both in the =
intrinsic functions of the type and in user code. Why are people asserting =
that "variant" is somehow different from other types and needs to=
be special here with an invalid state upon exception? The reason, though o=
ne that I still disagree with, is that we consider an invalid state because=
, given the suggested requirements of field types, we would not otherwise b=
e able to satisfy even the basic guarantee for assignment. Again, my person=
al thoughts here are that we are simply trying to force incorrect requireme=
nts on the assignment operation and are thereby creating an unnecessary pro=
blem. The resolve this, we are now making our type more complicated. Instea=
d, maybe we should rethink those requirements.</div><div><br></div><div>Whe=
never you implement a generic function or type, at least if you buy into th=
e generic programming paradigm used by the STL, you start with an implement=
ation and you lift out the requirements of the types involved from that. Yo=
u cannot start with requirements that=C2=A0simply=C2=A0would be nice to hav=
e, though which may or may not be feasible for the datastructure and the op=
erations in question, and then expect to be able to actually implement that=
hypothetical ideal facility in full and without issue. What we've done=
here is we've prematurely decided that <i>all</i> operations <i>must</=
i>=C2=A0work out-of-the-box even when field types have move-constructors th=
at can throw, and that we <i>must not</i> use a field type as a fallback st=
ate (I haven't actually heard the rationale for why we don't want t=
o fallback to a field, other than that people voted no -- what was the reas=
oning here, as I was not there for that discussion? have people considered =
a field with trivial special member functions as opposed to simply one that=
is noexcept-default-constructible?). IMO, we really should be considering =
that the requirements that we started may just be unreasonable. If you impl=
ement assignment and lift out those requirements for assignment, you are on=
ly constraining those particular operations, and=C2=A0notably, in this case=
the constraints are easily met <i>anyway,=C2=A0</i>without even modifying =
existing field types, and it amounts to either explicitly=C2=A0adding the e=
quivalent of an invalid state (by way of a user just explicitly adding a fi=
eld that can act as a fallback), or by alternate means, such as my suggesti=
on regarding optional.</div><div><br></div><div>On Tue, Sep 29, 2015 at 12:=
37 AM, David Krauss=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:potswa@gma=
il.com" target=3D"_blank">potswa@gmail.com</a>></span>=C2=A0wrote:</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;p=
adding-left:1ex"><div style=3D"word-wrap:break-word"><div>Default construct=
ion should not make guesses (or encourage the user to make educated guesses=
) for convenience. Default construct into the invalid state and let the obj=
ect be validated when the program has done the actual work to make it valid=
..</div></div></blockquote><div><br></div><div>It's not any kind of a gu=
ess, it's just a subjective choice that is fully specified. This is alw=
ays true of any default, whether it be a default-constructed value, or a de=
fault comparison behavior for something like std::sort. A variant that init=
ialize to something that isn't "invalid" is also perfectly fi=
ne for construct/init later patterns, but realistically, users already have=
the (IMO much better) alternative of initializing the variable directly up=
on construction rather than constructing and initializing later. This is pr=
events "forgetting" to further set the value after construction. =
Especially with lambdas, this solution is not very difficult for users and =
it doesn't introduce an invalid state into your type.</div><div><br></d=
iv><div>=C2=A0On Tue, Sep 29, 2015 at 12:37 AM, David Krauss=C2=A0<span dir=
=3D"ltr"><<a href=3D"mailto:potswa@gmail.com" target=3D"_blank">potswa@g=
mail.com</a>></span>=C2=A0wrote:</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"><div style=3D"wor=
d-wrap:break-word"><div></div><div>Wanting validity by default is setting a=
low standard for validity. It=E2=80=99s easy (and good) to define each sen=
se of emptiness in a program, so we don=E2=80=99t need (and shouldn=E2=80=
=99t want)=C2=A0<font face=3D"Courier">std::monostate</font>. It=E2=80=99s =
easy to define your own class derived from <font face=3D"Courier">variant</=
font> and default-constructing it a particular way. It=E2=80=99s less easy =
to take an automatically-=E2=80=9Cvalid=E2=80=9D variant and set the error =
state as the default.</div></div></blockquote><div><br></div><div>It is not=
setting a low standard for validity. The user is still explicitly construc=
ting their object and the state is fully specified. If they don't want =
a "valid" object then they shouldn't be constructing the obje=
ct at that point at all. If you assert that a default-constructed object sh=
ould be valid, do you also assert that a std::vector should be invalid inst=
ead of empty on construction (or any other container)? By that logic, such =
a type is currently setting a "low standard for validity" too. A =
user could simply be using the default-construct and initialize pattern wit=
h a vector just like you suggest someone may do for a variant. You shouldn&=
#39;t be thinking it's somehow a low standard for validity at all -- wh=
at it actually is is a high standard for strictness of invariants. Just don=
't construct the object if you don't want a "valid" objec=
t. Initialize upon construction.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b33d3186543820520e7798d--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 12:08:51 -0700
Raw View
--001a1137bdd06b9eb20520e78b16
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 8:22 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> Error states don't make sense if you have the strong exception guarantee.
> Which we have proven `variant` can provide with minimal overhead.
>
If we'd proven that then we wouldn't be having this discussion ;)
The strong guarantee definitely does have overhead, it's just that some
people have decided that the overhead is reasonable, which IMO is an
assumption that cannot be properly made at the library level because it is
usage-dependent. People also aren't currently providing the strong
guarantee in implementations -- they're providing "partial" strong
guarantee (aka the basic guarantee). Similarly, for the single-field case,
it has been suggested at least by one that we would not necessarily get the
strong guarantee.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1137bdd06b9eb20520e78b16
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=
ue, Sep 29, 2015 at 8:22 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div>Error states don't make =
sense if you have the strong exception guarantee. Which we have proven `var=
iant` can provide with minimal overhead.<br></div></blockquote><div><br></d=
iv><div>If we'd proven that then we wouldn't be having this discuss=
ion ;)</div><div><br></div><div>The strong guarantee definitely does have o=
verhead, it's just that some people have decided that the overhead is r=
easonable, which IMO is an assumption that cannot be properly made at the l=
ibrary level because it is usage-dependent. People also aren't currentl=
y providing the strong guarantee in implementations -- they're providin=
g "partial" strong guarantee (aka the basic guarantee). Similarly=
, for the single-field case, it has been suggested at least by one that we =
would not necessarily get the strong guarantee.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1137bdd06b9eb20520e78b16--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 29 Sep 2015 16:20:23 -0400
Raw View
--001a1141eeec40b1120520e88b09
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tue, Sep 29, 2015 at 3:03 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Tue, Sep 29, 2015 at 12:37 AM, David Krauss <potswa@gmail.com> wrote:
>>
>> That doesn=E2=80=99t make sense. If it represents brokenness due to an e=
xception,
>> then there should be an exception_ptr.
>>
>
> Why should it be an exception_ptr, either? You don't need some additional
> state for this.
>
Agreed. While it does make some sense to say "this is the exception that
got you into this state", remember that the exception is actually _thrown_,
so if you want to keep it, do it yourself. Variant doesn't need to keep it=
..
> Even regarding existing practice, neither of these cases, "invalid" nor
> "exception_ptr," are used for other standard library types when one of
> their functions throws an exception (thankfully), nor notably for Boost
> types. Such states are not needed and just weaken the invariants of the
> type by introducing additional kinds of states that require special
> handling both in the intrinsic functions of the type and in user code. Wh=
y
> are people asserting that "variant" is somehow different from other types
> and needs to be special here with an invalid state upon exception? The
> reason, though one that I still disagree with, is that we consider an
> invalid state because, given the suggested requirements of field types, w=
e
> would not otherwise be able to satisfy even the basic guarantee for
> assignment. Again, my personal thoughts here are that we are simply tryin=
g
> to force incorrect requirements on the assignment operation and are there=
by
> creating an unnecessary problem. The resolve this, we are now making our
> type more complicated. Instead, maybe we should rethink those requirement=
s.
>
It would be interesting to see some survey of what types would meet the
requirements and which wouldn't. ie variant<list<int>, deque<int>>
(depending on platform??), etc. ie how big of a problem is it?
> Whenever you implement a generic function or type, at least if you buy
> into the generic programming paradigm used by the STL, you start with an
> implementation and you lift out the requirements of the types involved fr=
om
> that. You cannot start with requirements that simply would be nice to hav=
e,
> though which may or may not be feasible for the datastructure and the
> operations in question, and then expect to be able to actually implement
> that hypothetical ideal facility in full and without issue. What we've do=
ne
> here is we've prematurely decided that *all* operations *must* work
> out-of-the-box even when field types have move-constructors that can thro=
w,
> and that we *must not* use a field type as a fallback state (I haven't
> actually heard the rationale for why we don't want to fallback to a field=
,
> other than that people voted no -- what was the reasoning here, as I was
> not there for that discussion?
>
I wasn't there either, but IIUC at least one point was
- When using (ie copying, etc) something like a vector<Shape> (where Shape
is a variant) and having an exception thrown in the middle, it becomes hard
to know _which_ shape needs to be corrected. Thus an explicitly invalid
state (ie Lenexa) might be better. And the other alternative -
variant<explicity_invalid, Circle, Triangle, etc> - becomes invalid toooo
often.
My general feel is that if I try to change a Circle into a Triangle it
shouldn't become a Square. I don't think other things in the STL that
offer the basic guarantee are as "surprising". But that is just a gut
feeling.
Tony
--=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/.
--001a1141eeec40b1120520e88b09
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 29, 2015 at 3:03 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"lt=
r"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D"">O=
n Tue, Sep 29, 2015 at 12:37 AM, David Krauss <span dir=3D"ltr"><<a href=
=3D"mailto:potswa@gmail.com" target=3D"_blank">potswa@gmail.com</a>></sp=
an> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style=3D"w=
ord-wrap:break-word"><div>That doesn=E2=80=99t make sense. If it represents=
brokenness due to an exception, then there should be an <font face=3D"Cour=
ier">exception_ptr</font>.</div></div></blockquote><div><br></div></span><d=
iv>Why should it be an exception_ptr, either? You don't need some addit=
ional state for this. </div></div></div></div></blockquote><div><br></div><=
div>Agreed. While it does make some sense to say "this is the exceptio=
n that got you into this state", remember that the exception is actual=
ly _thrown_, so if you want to keep it, do it yourself.=C2=A0 Variant doesn=
't need to keep it.<br><br></div><div>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(20=
4,204,204);padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><d=
iv class=3D"gmail_quote"><div>Even regarding existing practice, neither of =
these cases, "invalid" nor "exception_ptr," are used fo=
r other standard library types when one of their functions throws an except=
ion (thankfully), nor notably for Boost types. Such states are not needed a=
nd just weaken the invariants of the type by introducing additional kinds o=
f states that require special handling both in the intrinsic functions of t=
he type and in user code. Why are people asserting that "variant"=
is somehow different from other types and needs to be special here with an=
invalid state upon exception? The reason, though one that I still disagree=
with, is that we consider an invalid state because, given the suggested re=
quirements of field types, we would not otherwise be able to satisfy even t=
he basic guarantee for assignment. Again, my personal thoughts here are tha=
t we are simply trying to force incorrect requirements on the assignment op=
eration and are thereby creating an unnecessary problem. The resolve this, =
we are now making our type more complicated. Instead, maybe we should rethi=
nk those requirements.</div></div></div></div></blockquote><div><br></div><=
div>It would be interesting to see some survey of what types would meet the=
requirements and which wouldn't.=C2=A0 ie variant<list<int>, =
deque<int>> (depending on platform??), etc.=C2=A0 ie how big of a =
problem is it? <br><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1=
ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<div><br></div><div>Whenever you implement a generic function or type, at l=
east if you buy into the generic programming paradigm used by the STL, you =
start with an implementation and you lift out the requirements of the types=
involved from that. You cannot start with requirements that=C2=A0simply=C2=
=A0would be nice to have, though which may or may not be feasible for the d=
atastructure and the operations in question, and then expect to be able to =
actually implement that hypothetical ideal facility in full and without iss=
ue. What we've done here is we've prematurely decided that <i>all</=
i> operations <i>must</i>=C2=A0work out-of-the-box even when field types ha=
ve move-constructors that can throw, and that we <i>must not</i> use a fiel=
d type as a fallback state (I haven't actually heard the rationale for =
why we don't want to fallback to a field, other than that people voted =
no -- what was the reasoning here, as I was not there for that discussion?<=
/div></div></div></div></blockquote><div><br></div><div>I wasn't there =
either, but IIUC at least one point was<br><br>- When using (ie copying, et=
c) something like a vector<Shape> (where Shape is a variant) and havi=
ng an exception thrown in the middle, it becomes hard to know _which_ shape=
needs to be corrected.=C2=A0 Thus an explicitly invalid state (ie Lenexa) =
might be better.=C2=A0 And the other alternative - variant<explicity_inv=
alid, Circle, Triangle, etc> - becomes invalid toooo often.<br><br>My ge=
neral feel is that if I try to change a Circle into a Triangle it shouldn&#=
39;t become a Square.=C2=A0 I don't think other things in the STL that =
offer the basic guarantee are as "surprising".=C2=A0 But that is =
just a gut feeling.<br></div><div></div><br></div>Tony<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1141eeec40b1120520e88b09--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 14:12:00 -0700
Raw View
--001a11c2e462cc79910520e94392
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
> It would be interesting to see some survey of what types would meet the
> requirements and which wouldn't. ie variant<list<int>, deque<int>>
> (depending on platform??), etc. ie how big of a problem is it?
>
Okay, agreed.
Do we really need portability between implementations that vary on noexcept
and non-noexcept? Why is this even considered acceptable, as in, isn't this
a defect? This has much more subtle problems in other areas where we
wouldn't at least have the benefit of seeing a compile error. If it's
*not* considered
a defect, the user could put in a fallback type when they need/want such
portability.
On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvaneerd@gmail.com> wrote:
> I wasn't there either, but IIUC at least one point was
>
> - When using (ie copying, etc) something like a vector<Shape> (where Shape
> is a variant) and having an exception thrown in the middle, it becomes hard
> to know _which_ shape needs to be corrected. Thus an explicitly invalid
> state (ie Lenexa) might be better. And the other alternative -
> variant<explicity_invalid, Circle, Triangle, etc> - becomes invalid toooo
> often.
>
IIUC, you cannot portably deal with copy-assignment exceptions for vector
or other containers in this manner to begin with (someone correct me if I'm
wrong, here). Even if you could, this consideration would exist for types
other than variant.
On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvaneerd@gmail.com> wrote:
> My general feel is that if I try to change a Circle into a Triangle it
> shouldn't become a Square. I don't think other things in the STL that
> offer the basic guarantee are as "surprising". But that is just a gut
> feeling.
>
Perhaps surprising if anyone cared to know, but users either do not observe
it, or if they do observe it, they explicitly should not care. It's only a
curiosity. This is the nature of the basic exception guarantee. You're not
going to be relying on the object being in any specific state after the
exception is thrown from the operation. In practice that usually means that
programmers either ignore the value entirely when the exception makes it to
them (as is usually the case when the exception further propagates beyond
the lifetime of the object in question), or the user sets the value of the
object to something else while handling the exception at that point in the
stack. In either case, it doesn't matter what state the object is in
initially when propagation starts. It is irrelevant, which is why the basic
exception guarantee "works" as a guarantee and doesn't require weakening
the invariants of the type. Users aren't depending on that state being
anything in particular.
So yeah, it might sound weird or unexpected, since people might not
immediately understand *why* it could end up like that during exception
propagation, but it is ultimately irrelevant.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2e462cc79910520e94392
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=
ue, Sep 29, 2015 at 1:20 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mail=
to:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>It would be interesting to see some survey of what =
types would meet the requirements and which wouldn't.=C2=A0 ie variant&=
lt;list<int>, deque<int>> (depending on platform??), etc.=C2=
=A0 ie how big of a problem is it?<br></div></div></div></div></blockquote>=
<div><br></div><div>Okay, agreed.</div><div><br></div><div>Do we really nee=
d portability between implementations that vary on noexcept and non-noexcep=
t? Why is this even considered acceptable, as in, isn't this a defect? =
This has much more subtle problems in other areas where we wouldn't at =
least have the benefit of seeing a compile error. If it's <i>not</i>=C2=
=A0considered a defect, the user could put in a fallback type when they nee=
d/want such portability.</div><div><br></div><div>On Tue, Sep 29, 2015 at 1=
:20 PM, Tony V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmai=
l.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:</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"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D=
"gmail_quote"><div>I wasn't there either, but IIUC at least one point w=
as<br><br>- When using (ie copying, etc) something like a vector<Shape&g=
t; (where Shape is a variant) and having an exception thrown in the middle,=
it becomes hard to know _which_ shape needs to be corrected.=C2=A0 Thus an=
explicitly invalid state (ie Lenexa) might be better.=C2=A0 And the other =
alternative - variant<explicity_invalid, Circle, Triangle, etc> - bec=
omes invalid toooo often.<br></div></div></div></div></blockquote><div><br>=
</div><div>IIUC, you cannot portably deal with copy-assignment exceptions f=
or vector or other containers in this manner to begin with (someone correct=
me if I'm wrong, here). Even if you could, this consideration would ex=
ist for types other than variant.</div><div><br></div><div>On Tue, Sep 29, =
2015 at 1:20 PM, Tony V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvan=
eerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wr=
ote:=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-le=
ft-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra=
"><div class=3D"gmail_quote"><div>My general feel is that if I try to chang=
e a Circle into a Triangle it shouldn't become a Square.=C2=A0 I don=
9;t think other things in the STL that offer the basic guarantee are as &qu=
ot;surprising".=C2=A0 But that is just a gut feeling.</div></div></div=
></div></blockquote><div><br></div><div>Perhaps surprising if anyone cared =
to know, but users either do not observe it, or if they do observe it, they=
explicitly should not care. It's only a curiosity. This is the nature =
of the basic exception guarantee. You're not going to be relying on the=
object being in any specific state after the exception is thrown from the =
operation. In practice that usually means that programmers either ignore th=
e value entirely when the exception makes it to them (as is usually the cas=
e when the exception further propagates beyond the lifetime of the object i=
n question), or the user sets the value of the object to something else whi=
le handling the exception at that point in the stack. In either case, it do=
esn't matter what state the object is in initially when propagation sta=
rts. It is irrelevant, which is why the basic exception guarantee "wor=
ks" as a guarantee and doesn't require weakening the invariants of=
the type. Users aren't depending on that state being anything in parti=
cular.</div><div><br></div><div>So yeah, it might sound weird or unexpected=
, since people might not immediately understand <i>why</i> it could end up =
like that during exception propagation, but it is ultimately irrelevant.</d=
iv></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2e462cc79910520e94392--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Tue, 29 Sep 2015 18:14:57 -0300
Raw View
On 9/29/2015 12:22 PM, Nicol Bolas wrote:
> If so, then I have to write a bunch of meaningless code, even with your
> "derived class" solution. If not, then my emptyable variants are /unsafe
> to use/, since visitation won't force me to check the empty state. And
> remember: static validation is like half the point of visitors.
>
> Nobody seems to recognize that catch-22. Do people who use emptyable
> variants simply not care about visitation? I mention that because I
> noticed that Eggs.Variant doesn't have a visitation framework. Indeed,
> most variant types out there don't.
Doesn't `apply` cut it as a visitation framework? It's there mostly as=20
an experiment on O(1) visitation, and multi-visitation. I consider it=20
akin to `get<T>`, which is not something I would really expect from a=20
(core) discriminated union.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 Sep 2015 14:17:28 -0700 (PDT)
Raw View
------=_Part_958_1067068696.1443561448950
Content-Type: multipart/alternative;
boundary="----=_Part_959_1256645097.1443561448950"
------=_Part_959_1256645097.1443561448950
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 29, 2015 at 3:08:55 PM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 29, 2015 at 8:22 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>>
>> Error states don't make sense if you have the strong exception guarantee.
>> Which we have proven `variant` can provide with minimal overhead.
>>
>
> If we'd proven that then we wouldn't be having this discussion ;)
>
But that's not the discussion you're about to have. The discussion you're
talking about is not whether it is *possible* with minimal overhead. It's
whether the minimal overhead is sufficiently minimal enough to use.
That's a different discussion. We now have a new minimum amount of
overhead. The question now is whether that's small enough.
The strong guarantee definitely does have overhead, it's just that some
> people have decided that the overhead is reasonable, which IMO is an
> assumption that cannot be properly made at the library level because it is
> usage-dependent.
>
Why? We decided that the overhead for std::list having a constant-time
`size` was "reasonable", despite adding burden to `splice`. The standards
committee makes decisions about overhead all the time. Sometimes they favor
some people, and othertimes they favor others. Someone wins, someone loses.
The committee decides that small-string optimization is *possible*, but
does not standardize that it must be provided or how big a "small string"
is. Similarly, the committee allows `function` and `any` to perform small
object optimizations, but does not require them to nor does it declare how
big that buffer must be.
For some people, these lack of requirements are a deal-breaker. They need a
string with a specific small-size optimization. Or they want `function` to
be able to optimize larger objects. Or smaller ones. Or whatever. So they
write their own versions.
No single type will ever be all things to all people. The committee should,
as always, pick a reasonable default. Not one that satisfies everyone, but
one that satisfies most people.
And I believe that the optimized strong-exception-guarantee-without-invalid
variant is the option that satisfies the most people, while imposing the
least burden on those on the other side of the issue.
As for the question of overhead, consider the fact that il-behaved types
are not exactly common. They're not *uncommon*, but most types are properly
behaved (noexcept moveable). So what is the likelihood that users will come
upon this overhead? Even then, if you have a large type with a
noexcept-move, the overhead can be entirely avoided.
For some people, any overhead is a dealbreaker. But I feel no more sympathy
to their plight than I do for those users who need to specify how many
characters a "small string" is. Everyone has their special needs, and some
people just have to accept the short straw.
Similarly, for the single-field case, it has been suggested at least by one
> that we would not necessarily get the strong guarantee.
>
That's not a question of *possibility* though. That's a question of whether
the type ought to provide that functionality. It certainly can. But you
lose one of the optimizations in doing so.
The question is one of design, mostly: is it reasonable for `variant<X> =
variant<X>` to yield a different result from `x = x`? There are arguments
from both sides here, and they're not generally based on the optimization
question.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_959_1256645097.1443561448950
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, September 29, 2015 at 3:08:55 PM UTC-4, Matt C=
alabrese 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=
"><div><div class=3D"gmail_quote">On Tue, Sep 29, 2015 at 8:22 AM, Nicol Bo=
las <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obf=
uscated-mailto=3D"bZeAh04NCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">jmck...@gmail.com</a>></span> wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div>Error states don't make sense if you have the st=
rong exception guarantee. Which we have proven `variant` can provide with m=
inimal overhead.<br></div></blockquote><div><br></div><div>If we'd prov=
en that then we wouldn't be having this discussion ;)</div></div></div>=
</div></blockquote><div><br>But that's not the discussion you're ab=
out to have. The discussion you're talking about is not whether it is <=
i>possible</i> with minimal overhead. It's whether the minimal overhead=
is sufficiently minimal enough to use.<br><br>That's a different discu=
ssion. We now have a new minimum amount of overhead. The question now is wh=
ether that's small enough.<br><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><=
div>The strong guarantee definitely does have overhead, it's just that =
some people have decided that the overhead is reasonable, which IMO is an a=
ssumption that cannot be properly made at the library level because it is u=
sage-dependent.</div></div></div></div></blockquote><div><br>Why? We decide=
d that the overhead for std::list having a constant-time `size` was "r=
easonable", despite adding burden to `splice`. The standards committee=
makes decisions about overhead all the time. Sometimes they favor some peo=
ple, and othertimes they favor others. Someone wins, someone loses.<br><br>=
The committee decides that small-string optimization is <i>possible</i>, bu=
t does not standardize that it must be provided or how big a "small st=
ring" is. Similarly, the committee allows `function` and `any` to perf=
orm small object optimizations, but does not require them to nor does it de=
clare how big that buffer must be.<br><br>For some people, these lack of re=
quirements are a deal-breaker. They need a string with a specific small-siz=
e optimization. Or they want `function` to be able to optimize larger objec=
ts. Or smaller ones. Or whatever. So they write their own versions.<br><br>=
No single type will ever be all things to all people. The committee should,=
as always, pick a reasonable default. Not one that satisfies everyone, but=
one that satisfies most people.<br><br>And I believe that the optimized st=
rong-exception-guarantee-without-invalid variant is the option that satisfi=
es the most people, while imposing the least burden on those on the other s=
ide of the issue.<br><br>As for the question of overhead, consider the fact=
that il-behaved types are not exactly common. They're not <i>uncommon<=
/i>, but most types are properly behaved (noexcept moveable). So what is th=
e likelihood that users will come upon this overhead? Even then, if you hav=
e a large type with a noexcept-move, the overhead can be entirely avoided.<=
br><br>For some people, any overhead is a dealbreaker. But I feel no more s=
ympathy to their plight than I do for those users who need to specify how m=
any characters a "small string" is. Everyone has their special ne=
eds, and some people just have to accept the short straw.<br><br></div><blo=
ckquote 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><div class=
=3D"gmail_quote"><div>Similarly, for the single-field case, it has been sug=
gested at least by one that we would not necessarily get the strong guarant=
ee.</div></div></div></div></blockquote><div><br>That's not a question =
of <i>possibility</i> though. That's a question of whether the type oug=
ht to provide that functionality. It certainly can. But you lose one of the=
optimizations in doing so.<br><br>The question is one of design, mostly: i=
s it reasonable for `variant<X> =3D variant<X>` to yield a diff=
erent result from `x =3D x`? There are arguments from both sides here, and =
they're not generally based on the optimization question.<br></div></di=
v>
<p></p>
-- <br />
<br />
--- <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 />
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_959_1256645097.1443561448950--
------=_Part_958_1067068696.1443561448950--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 29 Sep 2015 17:26:04 -0400
Raw View
--089e0141a71825c1500520e97633
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 5:12 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvaneerd@gmail.com> wrote:
>>
>> It would be interesting to see some survey of what types would meet the
>> requirements and which wouldn't. ie variant<list<int>, deque<int>>
>> (depending on platform??), etc. ie how big of a problem is it?
>>
>
> Okay, agreed.
>
> Do we really need portability between implementations that vary on
> noexcept and non-noexcept? Why is this even considered acceptable, as in,
> isn't this a defect? This has much more subtle problems in other areas
> where we wouldn't at least have the benefit of seeing a compile error. If
> it's *not* considered a defect, the user could put in a fallback type
> when they need/want such portability.
>
> On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> I wasn't there either, but IIUC at least one point was
>>
>> - When using (ie copying, etc) something like a vector<Shape> (where
>> Shape is a variant) and having an exception thrown in the middle, it
>> becomes hard to know _which_ shape needs to be corrected. Thus an
>> explicitly invalid state (ie Lenexa) might be better. And the other
>> alternative - variant<explicity_invalid, Circle, Triangle, etc> - becomes
>> invalid toooo often.
>>
>
> IIUC, you cannot portably deal with copy-assignment exceptions for vector
> or other containers in this manner to begin with (someone correct me if I'm
> wrong, here). Even if you could, this consideration would exist for types
> other than variant.
>
> On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
>> My general feel is that if I try to change a Circle into a Triangle it
>> shouldn't become a Square. I don't think other things in the STL that
>> offer the basic guarantee are as "surprising". But that is just a gut
>> feeling.
>>
>
> Perhaps surprising if anyone cared to know, but users either do not
> observe it, or if they do observe it, they explicitly should not care. It's
> only a curiosity. This is the nature of the basic exception guarantee.
> You're not going to be relying on the object being in any specific state
> after the exception is thrown from the operation. In practice that usually
> means that programmers either ignore the value entirely when the exception
> makes it to them (as is usually the case when the exception further
> propagates beyond the lifetime of the object in question), or the user sets
> the value of the object to something else while handling the exception at
> that point in the stack. In either case, it doesn't matter what state the
> object is in initially when propagation starts. It is irrelevant, which is
> why the basic exception guarantee "works" as a guarantee and doesn't
> require weakening the invariants of the type. Users aren't depending on
> that state being anything in particular.
>
> So yeah, it might sound weird or unexpected, since people might not
> immediately understand *why* it could end up like that during exception
> propagation, but it is ultimately irrelevant.
>
Summary: Most results of the basic guarantee don't live long enough to
matter. They just need to be valid enough to die.
I will agree there is some validity in 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0141a71825c1500520e97633
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 29, 2015 at 5:12 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Tue, Sep 29, 2015=
at 1:20 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmai=
l.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> wrote:<blockquot=
e 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-lef=
t:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quot=
e"><div>It would be interesting to see some survey of what types would meet=
the requirements and which wouldn't.=C2=A0 ie variant<list<int&g=
t;, deque<int>> (depending on platform??), etc.=C2=A0 ie how big o=
f a problem is it?<br></div></div></div></div></blockquote><div><br></div><=
/span><div>Okay, agreed.</div><div><br></div><div>Do we really need portabi=
lity between implementations that vary on noexcept and non-noexcept? Why is=
this even considered acceptable, as in, isn't this a defect? This has =
much more subtle problems in other areas where we wouldn't at least hav=
e the benefit of seeing a compile error. If it's <i>not</i>=C2=A0consid=
ered a defect, the user could put in a fallback type when they need/want su=
ch portability.</div><span class=3D""><div><br></div><div>On Tue, Sep 29, 2=
015 at 1:20 PM, Tony V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvane=
erd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wro=
te:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div =
class=3D"gmail_quote"><div>I wasn't there either, but IIUC at least one=
point was<br><br>- When using (ie copying, etc) something like a vector<=
;Shape> (where Shape is a variant) and having an exception thrown in the=
middle, it becomes hard to know _which_ shape needs to be corrected.=C2=A0=
Thus an explicitly invalid state (ie Lenexa) might be better.=C2=A0 And th=
e other alternative - variant<explicity_invalid, Circle, Triangle, etc&g=
t; - becomes invalid toooo often.<br></div></div></div></div></blockquote><=
div><br></div></span><div>IIUC, you cannot portably deal with copy-assignme=
nt exceptions for vector or other containers in this manner to begin with (=
someone correct me if I'm wrong, here). Even if you could, this conside=
ration would exist for types other than variant.</div><span class=3D""><div=
><br></div><div>On Tue, Sep 29, 2015 at 1:20 PM, Tony V E=C2=A0<span dir=3D=
"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@=
gmail.com</a>></span>=C2=A0wrote:=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"><div dir=
=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>My gene=
ral feel is that if I try to change a Circle into a Triangle it shouldn'=
;t become a Square.=C2=A0 I don't think other things in the STL that of=
fer the basic guarantee are as "surprising".=C2=A0 But that is ju=
st a gut feeling.</div></div></div></div></blockquote><div><br></div></span=
><div>Perhaps surprising if anyone cared to know, but users either do not o=
bserve it, or if they do observe it, they explicitly should not care. It=
9;s only a curiosity. This is the nature of the basic exception guarantee. =
You're not going to be relying on the object being in any specific stat=
e after the exception is thrown from the operation. In practice that usuall=
y means that programmers either ignore the value entirely when the exceptio=
n makes it to them (as is usually the case when the exception further propa=
gates beyond the lifetime of the object in question), or the user sets the =
value of the object to something else while handling the exception at that =
point in the stack. In either case, it doesn't matter what state the ob=
ject is in initially when propagation starts. It is irrelevant, which is wh=
y the basic exception guarantee "works" as a guarantee and doesn&=
#39;t require weakening the invariants of the type. Users aren't depend=
ing on that state being anything in particular.</div><div><br></div><div>So=
yeah, it might sound weird or unexpected, since people might not immediate=
ly understand <i>why</i> it could end up like that during exception propaga=
tion, but it is ultimately irrelevant.</div></div></div></div></blockquote>=
<div><br></div><div>Summary: Most results of the basic guarantee don't =
live long enough to matter. They just need to be valid enough to die.<br><b=
r></div><div>I will agree there is some validity in that.<br>=C2=A0<br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0141a71825c1500520e97633--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 29 Sep 2015 17:33:04 -0400
Raw View
--089e0158c00e2f718f0520e98ff8
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 5:17 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, September 29, 2015 at 3:08:55 PM UTC-4, Matt Calabrese wrote:
>>
>> On Tue, Sep 29, 2015 at 8:22 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>> Error states don't make sense if you have the strong exception
>>> guarantee. Which we have proven `variant` can provide with minimal overhead.
>>>
>>
>> If we'd proven that then we wouldn't be having this discussion ;)
>>
>
> But that's not the discussion you're about to have. The discussion you're
> talking about is not whether it is *possible* with minimal overhead. It's
> whether the minimal overhead is sufficiently minimal enough to use.
>
> That's a different discussion. We now have a new minimum amount of
> overhead. The question now is whether that's small enough.
>
Some of us may have been interpreting "minimal" as a value statement, like
"there is not much overhead, it is minimal, you can ignore it", instead of
we have defined/determined a minimum, that could, in some cases, be very
large.
Or "the amount of cases where double buffering is necessary is minimal"
(implying not very often, instead of implying we've determined some number
somehow).
I don't want to argue which was meant when and where, just pointing out
that it was ambiguous.
> The question is one of design, mostly: is it reasonable for `variant<X> =
> variant<X>` to yield a different result from `x = x`? There are arguments
> from both sides here, and they're not generally based on the optimization
> question.
>
Design-wise, I think it is WRONG for variant<X> = variant<X> to be
different from x = x. No question.
The only question, to me, is whether this (and the fact that it might only
be the basic guarantee), means that the strong guarantee when switching
types X = Y is not worth it.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0158c00e2f718f0520e98ff8
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 29, 2015 at 5:17 PM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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">On T=
uesday, September 29, 2015 at 3:08:55 PM UTC-4, Matt Calabrese wrote:<span>=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D=
"gmail_quote">On Tue, Sep 29, 2015 at 8:22 AM, Nicol Bolas <span dir=3D"ltr=
"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div>Error states don't make sense if you have the=
strong exception guarantee. Which we have proven `variant` can provide wit=
h minimal overhead.<br></div></blockquote><div><br></div><div>If we'd p=
roven that then we wouldn't be having this discussion ;)</div></div></d=
iv></div></blockquote></span><div><br>But that's not the discussion you=
're about to have. The discussion you're talking about is not wheth=
er it is <i>possible</i> with minimal overhead. It's whether the minima=
l overhead is sufficiently minimal enough to use.<br><br>That's a diffe=
rent discussion. We now have a new minimum amount of overhead. The question=
now is whether that's small enough.<br></div></div></blockquote><div><=
br></div><div><br>Some of us may have been interpreting "minimal"=
as a value statement, like "there is not much overhead, it is minimal=
, you can ignore it", instead of we have defined/determined a minimum,=
that could, in some cases, be very large.<br><br></div><div>Or "the a=
mount of cases where double buffering is necessary is minimal" (implyi=
ng not very often, instead of implying we've determined some number som=
ehow).<br><br></div><div>I don't want to argue which was meant when and=
where, just pointing out that it was ambiguous.<br></div><div><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><div>The question is one =
of design, mostly: is it reasonable for `variant<X> =3D variant<X&=
gt;` to yield a different result from `x =3D x`? There are arguments from b=
oth sides here, and they're not generally based on the optimization que=
stion.<br></div></div></blockquote><div><br></div><div>Design-wise, I think=
it is WRONG for variant<X> =3D variant<X> to be different from=
x =3D x.=C2=A0 No question.<br></div><div><br>The only question, to me, is=
whether this (and the fact that it might only be the basic guarantee), mea=
ns that the strong guarantee when switching types X =3D Y is not worth it. =
<br><br></div><div>Tony<br></div></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0158c00e2f718f0520e98ff8--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 Sep 2015 14:33:57 -0700 (PDT)
Raw View
------=_Part_107_89195309.1443562437366
Content-Type: multipart/alternative;
boundary="----=_Part_108_687036145.1443562437367"
------=_Part_108_687036145.1443562437367
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 29, 2015 at 5:12:06 PM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvan...@gmail.com <javascript:>
> > wrote:
>
>> My general feel is that if I try to change a Circle into a Triangle it
>> shouldn't become a Square. I don't think other things in the STL that
>> offer the basic guarantee are as "surprising". But that is just a gut
>> feeling.
>>
>
> Perhaps surprising if anyone cared to know, but users either do not
> observe it, or if they do observe it, they explicitly should not care. It's
> only a curiosity. This is the nature of the basic exception guarantee.
> You're not going to be relying on the object being in any specific state
> after the exception is thrown from the operation. In practice that usually
> means that programmers either ignore the value entirely when the exception
> makes it to them (as is usually the case when the exception further
> propagates beyond the lifetime of the object in question), or the user sets
> the value of the object to something else while handling the exception at
> that point in the stack. In either case, it doesn't matter what state the
> object is in initially when propagation starts. It is irrelevant, which is
> why the basic exception guarantee "works" as a guarantee and doesn't
> require weakening the invariants of the type. Users aren't depending on
> that state being anything in particular.
>
That's circular logic. You're trying to argue why we don't need the strong
exception guarantee by saying that everyone writes code for objects with
the basic exception guarantee.
Duh, because that's what those objects provide! People wouldn't reset
objects to a known state if those objects weren't in a
"valid-but-unspecified" state due to the basic exception guarantee.
The question is not whether we could get buy with the basic exception
guarantee. The question is whether we *should*. And what it's worth to do
so.
The cost of invalid is clearly evident in this thread. The very *minute*
people started talking about a variant with an invalid state, even one that
could only be reached through a failure, they started to try to effectively
enforce an empty-able variant. They instantly tried to turn
"never-empty-but-possibly-broken" into "possibly-empty", typically through
making default construction yield invalid.
To me, the biggest downside of an invalid state is that it gives the
"possibly-empty" variant people a wedge to drive their design into the
type. I support the strong exception guarantee for many reasons, but one of
the big ones is that it is the *only way* to get a never-empty variant
*without* people trying to transform it into an empty-able variant.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_108_687036145.1443562437367
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 29, 2015 at 5:12:06 PM UTC-4, Matt Calabrese wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"></div></div></div></blockquote><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></d=
iv></div></div></div></blockquote><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><div class=3D"gmail_quote"><div>On Tue, Sep 29,=
2015 at 1:20 PM, Tony V E=C2=A0<span dir=3D"ltr"><<a href=3D"javascript=
:" target=3D"_blank" gdf-obfuscated-mailto=3D"8MZHRQcUCgAJ" rel=3D"nofollow=
" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D=
"this.href=3D'javascript:';return true;">tvan...@gmail.com</a>><=
/span>=C2=A0wrote:=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,=
204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"><div>My general feel is that if I try to change a Circ=
le into a Triangle it shouldn't become a Square.=C2=A0 I don't thin=
k other things in the STL that offer the basic guarantee are as "surpr=
ising".=C2=A0 But that is just a gut feeling.</div></div></div></div><=
/blockquote><div><br></div><div>Perhaps surprising if anyone cared to know,=
but users either do not observe it, or if they do observe it, they explici=
tly should not care. It's only a curiosity. This is the nature of the b=
asic exception guarantee. You're not going to be relying on the object =
being in any specific state after the exception is thrown from the operatio=
n. In practice that usually means that programmers either ignore the value =
entirely when the exception makes it to them (as is usually the case when t=
he exception further propagates beyond the lifetime of the object in questi=
on), or the user sets the value of the object to something else while handl=
ing the exception at that point in the stack. In either case, it doesn'=
t matter what state the object is in initially when propagation starts. It =
is irrelevant, which is why the basic exception guarantee "works"=
as a guarantee and doesn't require weakening the invariants of the typ=
e. Users aren't depending on that state being anything in particular.</=
div></div></div></div></blockquote><div><br>That's circular logic. You&=
#39;re trying to argue why we don't need the strong exception guarantee=
by saying that everyone writes code for objects with the basic exception g=
uarantee.<br><br>Duh, because that's what those objects provide! People=
wouldn't reset objects to a known state if those objects weren't i=
n a "valid-but-unspecified" state due to the basic exception guar=
antee.<br><br>The question is not whether we could get buy with the basic e=
xception guarantee. The question is whether we <i>should</i>. And what it&#=
39;s worth to do so.<br><br>The cost of invalid is clearly evident in this =
thread. The very <i>minute</i> people started talking about a variant with =
an invalid state, even one that could only be reached through a failure, th=
ey started to try to effectively enforce an empty-able variant. They instan=
tly tried to turn "never-empty-but-possibly-broken" into "po=
ssibly-empty", typically through making default construction yield inv=
alid.<br><br>To me, the biggest downside of an invalid state is that it giv=
es the "possibly-empty" variant people a wedge to drive their des=
ign into the type. I support the strong exception guarantee for many reason=
s, but one of the big ones is that it is the <i>only way</i> to get a never=
-empty variant <i>without</i> people trying to transform it into an empty-a=
ble variant.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_108_687036145.1443562437367--
------=_Part_107_89195309.1443562437366--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 14:41:33 -0700
Raw View
--001a1137bdd0811ebe0520e9ad62
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 2:26 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
> Summary: Most results of the basic guarantee don't live long enough to
> matter. They just need to be valid enough to die.
>
> I will agree there is some validity in that.
>
Well, a little bit more than that, though usually I do personally find that
to be the case. The alternate is that the object can keep living perfectly
fine, but in practice, in that case, the object is usually set to some
other value (such as, in this case, a user setting it to something else in
a way that cannot throw an exception, i.e. via a noexcept emplace, which
can be fine for some situations). If there is no way to do *that*, then
yeah, you usually either handle the issue further up the stack, outside of
the life-time of the object, or you can also do something more akin to
double-buffering at a higher-level, outside of the implementation of the
object itself.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1137bdd0811ebe0520e9ad62
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=
ue, Sep 29, 2015 at 2:26 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mail=
to:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_e=
xtra"><div class=3D"gmail_quote"><div>Summary: Most results of the basic gu=
arantee don't live long enough to matter. They just need to be valid en=
ough to die.<br><br></div><div>I will agree there is some validity in that.=
</div></div></div></div></blockquote><div><br></div><div>Well, a little bit=
more than that, though usually I do personally find that to be the case. T=
he alternate is that the object can keep living perfectly fine, but in prac=
tice, in that case, the object is usually set to some other value (such as,=
in this case, a user setting it to something else in a way that cannot thr=
ow an exception, i.e. via a noexcept emplace, which can be fine for some si=
tuations). If there is no way to do <i>that</i>, then yeah, you usually eit=
her handle the issue further up the stack, outside of the life-time of the =
object, or you can also do something more akin to double-buffering at a hig=
her-level, outside of the implementation of the object itself.<br></div></d=
iv></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1137bdd0811ebe0520e9ad62--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 Sep 2015 14:45:39 -0700 (PDT)
Raw View
------=_Part_6323_249290837.1443563139636
Content-Type: multipart/alternative;
boundary="----=_Part_6324_32504238.1443563139636"
------=_Part_6324_32504238.1443563139636
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 29, 2015 at 5:33:07 PM UTC-4, Tony V E wrote:
>
> On Tue, Sep 29, 2015 at 5:17 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Tuesday, September 29, 2015 at 3:08:55 PM UTC-4, Matt Calabrese wrote:
>>>
>>> On Tue, Sep 29, 2015 at 8:22 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>>
>>>> Error states don't make sense if you have the strong exception
>>>> guarantee. Which we have proven `variant` can provide with minimal overhead.
>>>>
>>>
>>> If we'd proven that then we wouldn't be having this discussion ;)
>>>
>>
>> But that's not the discussion you're about to have. The discussion you're
>> talking about is not whether it is *possible* with minimal overhead.
>> It's whether the minimal overhead is sufficiently minimal enough to use.
>>
>> That's a different discussion. We now have a new minimum amount of
>> overhead. The question now is whether that's small enough.
>>
>
>
> Some of us may have been interpreting "minimal" as a value statement, like
> "there is not much overhead, it is minimal, you can ignore it", instead of
> we have defined/determined a minimum, that could, in some cases, be very
> large.
>
> Or "the amount of cases where double buffering is necessary is minimal"
> (implying not very often, instead of implying we've determined some number
> somehow).
>
> I don't want to argue which was meant when and where, just pointing out
> that it was ambiguous.
>
Yes, to clarify, I didn't mean that in an objective way. Only that this was
the most minimal we've seen from implementations: using a double buffer,
but only in the cases where it is necessary, and only large enough to be
necessary.
Though I think it the question of how often the overhead comes into play is
worth investigating. How many throwing-move types do we have out there? How
many of these types are liable to wind up inside a `variant`? Do
throwing-move types tend to be small?
std::list with a throwing move is implemented by having a pointer to a head
node which must be allocated (hence the throwing part of the move). That is
in contrast to implementations that put the head node into the std::list
object itself. The former implementation only takes up a pointer and a
size_t (for the size). The latter implementation requires a size_t and 3
pointers (at least).
So if you had a hypothetical variant<std::throwmove_list<T>,
std::noexcept_list<T>>, it turns out that the overhead from
`throwmove_list` is... zero. Even if we provide the fully strong exception
guarantee, the size of noexcept_list is twice as big as the size of
throwmove_list.
Therefore zero overhead.
That's obviously an artificial case. But even if it were a
`variant<throwmove_list<T>, vector<T>`, the overhead would be at most 8
bytes.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6324_32504238.1443563139636
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, September 29, 2015 at 5:33:07 PM UTC-4, Tony V E wrote:<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"><div><div class=3D"gm=
ail_quote">On Tue, Sep 29, 2015 at 5:17 PM, Nicol Bolas <span dir=3D"ltr">&=
lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"34Y81=
CwVCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';=
return true;" onclick=3D"this.href=3D'javascript:';return true;">jm=
ck...@gmail.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"><di=
v dir=3D"ltr">On Tuesday, September 29, 2015 at 3:08:55 PM UTC-4, Matt Cala=
brese wrote:<span><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"ltr">=
<div><div class=3D"gmail_quote">On Tue, Sep 29, 2015 at 8:22 AM, Nicol Bola=
s <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span=
> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div>Error states don't make sen=
se if you have the strong exception guarantee. Which we have proven `varian=
t` can provide with minimal overhead.<br></div></blockquote><div><br></div>=
<div>If we'd proven that then we wouldn't be having this discussion=
;)</div></div></div></div></blockquote></span><div><br>But that's not =
the discussion you're about to have. The discussion you're talking =
about is not whether it is <i>possible</i> with minimal overhead. It's =
whether the minimal overhead is sufficiently minimal enough to use.<br><br>=
That's a different discussion. We now have a new minimum amount of over=
head. The question now is whether that's small enough.<br></div></div><=
/blockquote><div><br></div><div><br>Some of us may have been interpreting &=
quot;minimal" as a value statement, like "there is not much overh=
ead, it is minimal, you can ignore it", instead of we have defined/det=
ermined a minimum, that could, in some cases, be very large.<br><br></div><=
div>Or "the amount of cases where double buffering is necessary is min=
imal" (implying not very often, instead of implying we've determin=
ed some number somehow).<br><br></div><div>I don't want to argue which =
was meant when and where, just pointing out that it was ambiguous.<br></div=
></div></div></div></blockquote><div><br>Yes, to clarify, I didn't mean=
that in an objective way. Only that this was the most minimal we've se=
en from implementations: using a double buffer, but only in the cases where=
it is necessary, and only large enough to be necessary.<br><br>Though I th=
ink it the question of how often the overhead comes into play is worth inve=
stigating. How many throwing-move types do we have out there? How many of t=
hese types are liable to wind up inside a `variant`? Do throwing-move types=
tend to be small?<br><br>std::list with a throwing move is implemented by =
having a pointer to a head node which must be allocated (hence the throwing=
part of the move). That is in contrast to implementations that put the hea=
d node into the std::list object itself. The former implementation only tak=
es up a pointer and a size_t (for the size). The latter implementation requ=
ires a size_t and 3 pointers (at least).<br><br>So if you had a hypothetica=
l variant<std::throwmove_list<T>, std::noexcept_list<T>>,=
it turns out that the overhead from `throwmove_list` is... zero. Even if w=
e provide the fully strong exception guarantee, the size of noexcept_list i=
s twice as big as the size of throwmove_list.<br><br>Therefore zero overhea=
d.<br><br>That's obviously an artificial case. But even if it were a `v=
ariant<throwmove_list<T>, vector<T>`, the overhead would be =
at most 8 bytes.</div>
<p></p>
-- <br />
<br />
--- <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 />
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_6324_32504238.1443563139636--
------=_Part_6323_249290837.1443563139636--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 14:55:48 -0700
Raw View
--94eb2c0961c47d82940520e9e08c
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 2:33 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
> Design-wise, I think it is WRONG for variant<X> = variant<X> to be
> different from x = x. No question.
>
> The only question, to me, is whether this (and the fact that it might only
> be the basic guarantee), means that the strong guarantee when switching
> types X = Y is not worth it.
>
Okay I think you and I at least are somewhat in agreement on this
particular point. My personal thoughts are that, whatever we do, it should
have a consistent rule for variant<T...> even when sizeof...(T) is 1.
Otherwise, when T... is dependent, you wouldn't be able to rely on the
strong guarantee anyway, unless you branched off for the sizeof(T) == 1
case (or I guess you could also disallow a variant with 1 field for your
particular template if that were an acceptable choice). IMO, thinking about
this in the generic sense where T... is dependent is an extremely important
consideration here, since that is precisely when a variant with exactly one
field type tends to come up. By that I mean, if T... wasn't dependent, then
you probably would have just used T directly instead of variant<T> to begin
with. Explicitly writing variant<int> isn't common in real-world code
because users could simply use an int in most cases. However, people might
do variant<T...> where T... happens to end up being a size 1 variadic list
of types, and where that type just so happens to be int. In this case, if
behavior weren't consistent between sizeof...(T) == 1, and sizeof...(T) >
1, then it would be difficult for them to write generic code that could
rely on the more strict guarantee. They'd either have to do complex
branching and have code to handle the weaker guarantee anyway, or they'd
just handle it by way of the weaker guarantee in all cases so as to avoid
the complicated branching.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--94eb2c0961c47d82940520e9e08c
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=
ue, Sep 29, 2015 at 2:33 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mail=
to:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_e=
xtra"><div class=3D"gmail_quote"><div>Design-wise, I think it is WRONG for =
variant<X> =3D variant<X> to be different from x =3D x.=C2=A0 N=
o question.<br></div><div><br>The only question, to me, is whether this (an=
d the fact that it might only be the basic guarantee), means that the stron=
g guarantee when switching types X =3D Y is not worth it.<br></div></div></=
div></div></blockquote><div><br></div><div>Okay I think you and I at least =
are somewhat in agreement on this particular point. My personal thoughts ar=
e that, whatever we do, it should have a consistent rule for variant<T..=
..> even when sizeof...(T) is 1. Otherwise, when T... is dependent, you w=
ouldn't be able to rely on the strong guarantee anyway, unless you bran=
ched off for the sizeof(T) =3D=3D 1 case (or I guess you could also disallo=
w a variant with 1 field for your particular template if that were an accep=
table choice). IMO, thinking about this in the generic sense where T... is =
dependent is an extremely important consideration here, since that is preci=
sely when a variant with exactly one field type tends to come up. By that I=
mean, if T... wasn't dependent, then you probably would have just used=
T directly instead of variant<T> to begin with. Explicitly writing v=
ariant<int> isn't common in real-world code because users could s=
imply use an int in most cases. However, people might do variant<T...>=
; where T... happens to end up being a size 1 variadic list of types, and w=
here that type just so happens to be int. In this case, if behavior weren&#=
39;t consistent between sizeof...(T) =3D=3D 1, and sizeof...(T) > 1, the=
n it would be difficult for them to write generic code that could rely on t=
he more strict guarantee. They'd either have to do complex branching an=
d have code to handle the weaker guarantee anyway, or they'd just handl=
e it by way of the weaker guarantee in all cases so as to avoid the complic=
ated branching.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--94eb2c0961c47d82940520e9e08c--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 15:13:03 -0700
Raw View
--001a11c2e4622137240520ea1eca
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, September 29, 2015 at 5:12:06 PM UTC-4, Matt Calabrese wrote:
>>
>> On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvan...@gmail.com> wrote:
>>
>>> My general feel is that if I try to change a Circle into a Triangle it
>>> shouldn't become a Square. I don't think other things in the STL that
>>> offer the basic guarantee are as "surprising". But that is just a gut
>>> feeling.
>>>
>>
>> Perhaps surprising if anyone cared to know, but users either do not
>> observe it, or if they do observe it, they explicitly should not care. It's
>> only a curiosity. This is the nature of the basic exception guarantee.
>> You're not going to be relying on the object being in any specific state
>> after the exception is thrown from the operation. In practice that usually
>> means that programmers either ignore the value entirely when the exception
>> makes it to them (as is usually the case when the exception further
>> propagates beyond the lifetime of the object in question), or the user sets
>> the value of the object to something else while handling the exception at
>> that point in the stack. In either case, it doesn't matter what state the
>> object is in initially when propagation starts. It is irrelevant, which is
>> why the basic exception guarantee "works" as a guarantee and doesn't
>> require weakening the invariants of the type. Users aren't depending on
>> that state being anything in particular.
>>
>
> That's circular logic. You're trying to argue why we don't need the strong
> exception guarantee by saying that everyone writes code for objects with
> the basic exception guarantee.
>
Where is the circular logic? I'm only describing *what* the basic guarantee
is and why code can and is written correctly when only the basic guarantee
is provided for a specific operation. If you understand that and the
explanation then you should also understand that you don't "need" the
strong guarantee. You never strictly need the strong guarantee. The strong
guarantee just makes things easier for some kinds of exception handling in
the case that it happens to exist.
On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> The question is not whether we could get buy with the basic exception
> guarantee. The question is whether we *should*. And what it's worth to do
> so.
>
I don't see why this is the consideration here. It's not been recommended
practice since the the exception guarantees were first introduced to force
a strong guarantee where it doesn't naturally fit. Further, the solutions
described here for providing the strong guarantee are either only providing
a "partial" strong guarantee (aka the basic guarantee) or are required to
do things like make all instances of the object itself take up something
comparable to double the storage space just in case an exception is thrown.
I still think that doing this is better than having an invalid state, I
just feel it's *really* unnecessary and provides a drawback that might
prevent people from being able or willing to use the type for their
scenario. It's perfectly fine for an operation that throws an exception to
specify the basic exception guarantee. We shouldn't be afraid of 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c2e4622137240520ea1eca
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=
ue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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">On Tuesday, September 29, 2015 at 5:12:06 P=
M UTC-4, Matt Calabrese wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,=
204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"></div></div></div></blockquote><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div></div></div></div></div></b=
lockquote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"=
><div>On Tue, Sep 29, 2015 at 1:20 PM, Tony V E=C2=A0<span dir=3D"ltr"><=
<a rel=3D"nofollow">tvan...@gmail.com</a>></span>=C2=A0wrote:=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"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>My =
general feel is that if I try to change a Circle into a Triangle it shouldn=
't become a Square.=C2=A0 I don't think other things in the STL tha=
t offer the basic guarantee are as "surprising".=C2=A0 But that i=
s just a gut feeling.</div></div></div></div></blockquote><div><br></div><d=
iv>Perhaps surprising if anyone cared to know, but users either do not obse=
rve it, or if they do observe it, they explicitly should not care. It's=
only a curiosity. This is the nature of the basic exception guarantee. You=
're not going to be relying on the object being in any specific state a=
fter the exception is thrown from the operation. In practice that usually m=
eans that programmers either ignore the value entirely when the exception m=
akes it to them (as is usually the case when the exception further propagat=
es beyond the lifetime of the object in question), or the user sets the val=
ue of the object to something else while handling the exception at that poi=
nt in the stack. In either case, it doesn't matter what state the objec=
t is in initially when propagation starts. It is irrelevant, which is why t=
he basic exception guarantee "works" as a guarantee and doesn'=
;t require weakening the invariants of the type. Users aren't depending=
on that state being anything in particular.</div></div></div></div></block=
quote><div><br>That's circular logic. You're trying to argue why we=
don't need the strong exception guarantee by saying that everyone writ=
es code for objects with the basic exception guarantee.<br></div></blockquo=
te><div><br></div><div>Where is the circular logic? I'm only describing=
<i>what</i> the basic guarantee is and why code can and is written correct=
ly when only the basic guarantee is provided for a specific operation. If y=
ou understand that and the explanation then you should also understand that=
you don't "need" the strong guarantee. You never strictly ne=
ed the strong guarantee. The strong guarantee just makes things easier for =
some kinds of exception handling in the case that it happens to exist.</div=
><div><br></div><div>On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas=C2=A0<spa=
n dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">=
jmckesson@gmail.com</a>></span>=C2=A0wrote:</div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>T=
he question is not whether we could get buy with the basic exception guaran=
tee. The question is whether we <i>should</i>. And what it's worth to d=
o so.<br></div></blockquote><div><br></div><div>I don't see why this is=
the consideration here. It's not been recommended practice since the t=
he exception guarantees were first introduced to force a strong guarantee w=
here it doesn't naturally fit. Further, the solutions described here fo=
r providing the strong guarantee are either only providing a "partial&=
quot; strong guarantee (aka the basic guarantee) or are required to do thin=
gs like make all instances of the object itself take up something comparabl=
e to double the storage space just in case an exception is thrown.</div><di=
v><br></div><div>I still think that doing this is better than having an inv=
alid state, I just feel it's <i>really</i>=C2=A0unnecessary and provide=
s a drawback that might prevent people from being able or willing to use th=
e type for their scenario. It's perfectly fine for an operation that th=
rows an exception to specify the basic exception guarantee. We shouldn'=
t be afraid of that.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2e4622137240520ea1eca--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 29 Sep 2015 18:01:58 -0500
Raw View
--001a1143a3e8728a7f0520eacf64
Content-Type: text/plain; charset=UTF-8
On 29 September 2015 at 16:45, Nicol Bolas <jmckesson@gmail.com> wrote:
> Yes, to clarify, I didn't mean that in an objective way. Only that this
> was the most minimal we've seen from implementations: using a double
> buffer, but only in the cases where it is necessary, and only large enough
> to be necessary.
>
That is only the space overhead. What about the runtime overhead of having
a bunch more moves? We can, of course, avoid that by double buffering in
more cases. Then we can start asking about the impact of double buffering
on processor and memory caches. And then there is the issue brought up in
n4542 about the address of the internal storage changing, which is also
something you have to hand wave away as Not Important because it interferes
with the One True Design.
std::list with a throwing move is implemented by having a pointer to a head
> node which must be allocated (hence the throwing part of the move). That is
> in contrast to implementations that put the head node into the std::list
> object itself. The former implementation only takes up a pointer and a
> size_t (for the size). The latter implementation requires a size_t and 3
> pointers (at least).
>
And what about every type that aggregates a std::list? I use variants for
stateful states in a state machine, and they can get quite a lot of
members. I don't sit around agonizing over whether or not each member has
a throwing move; rather, the rest of the code assumes that the aggregate
can throw unless I *document* otherwise. I may be able to live with the
double buffering provided there is no heap allocation, but please don't
hand wave away the cost of such a beast, because others may not be able to
afford it.
What amazes me are the sheer number of people who somehow know (yet
unsurprisingly cannot agree on) what the One True Variant should look like,
yet have never bothered to implement anything close to it and put it into
production systems.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143a3e8728a7f0520eacf64
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 29 September 2015 at 16:45, Nicol Bolas <span dir=3D"lt=
r"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@g=
mail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"=
gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div>Yes, to clarify, I didn=
9;t mean that in an objective way. Only that this was the most minimal we&#=
39;ve seen from implementations: using a double buffer, but only in the cas=
es where it is necessary, and only large enough to be necessary.<br></div><=
/blockquote><div><br></div><div>That is only the space overhead.=C2=A0 What=
about the runtime overhead of having a bunch more moves?=C2=A0 We can, of =
course, avoid that by double buffering in more cases.=C2=A0 Then we can sta=
rt asking about the impact of double buffering on processor and memory cach=
es.=C2=A0 And then there is the issue brought up in n4542 about the address=
of the internal storage changing, which is also something you have to hand=
wave away as Not Important because it interferes with the One True Design.=
</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>std::list with a t=
hrowing move is implemented by having a pointer to a head node which must b=
e allocated (hence the throwing part of the move). That is in contrast to i=
mplementations that put the head node into the std::list object itself. The=
former implementation only takes up a pointer and a size_t (for the size).=
The latter implementation requires a size_t and 3 pointers (at least).<br>=
</div></blockquote><div><br></div><div>And what about every type that aggre=
gates a std::list?=C2=A0 I use variants for stateful states in a state mach=
ine, and they can get quite a lot of members.=C2=A0 I don't sit around =
agonizing over whether or not each member has a throwing move; rather, the =
rest of the code assumes that the aggregate can throw unless I <i>document<=
/i> otherwise.=C2=A0 I may be able to live with the double buffering provid=
ed there is no heap allocation, but please don't hand wave away the cos=
t of such a beast, because others may not be able to afford it.</div><div><=
br></div><div>What amazes me are the sheer number of people who somehow kno=
w (yet unsurprisingly cannot agree on) what the One True Variant should loo=
k like, yet have never bothered to implement anything close to it and put i=
t into production systems.</div><div>--=C2=A0<br></div></div><div>=C2=A0Nev=
in ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverl=
ord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 <a href=3D"=
tel:%28847%29%20691-1404" value=3D"+18476911404" target=3D"_blank">(847) 69=
1-1404</a></div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143a3e8728a7f0520eacf64--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 16:57:10 -0700
Raw View
--001a11c182267682d30520eb924b
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 4:01 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
>
> And what about every type that aggregates a std::list? I use variants for
> stateful states in a state machine, and they can get quite a lot of members.
>
At least we have similar use-cases (or perhaps that's not good assuming we
really want a wider-variety of use-cases to consider). I've found variant
invaluable for this kind of thing, even when compared to existing libraries
whose explicit purpose is the creation of state machines and that perform
state management behind the scenes.
On Tue, Sep 29, 2015 at 4:01 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> I don't sit around agonizing over whether or not each member has a
> throwing move; rather, the rest of the code assumes that the aggregate can
> throw unless I *document* otherwise. I may be able to live with the
> double buffering provided there is no heap allocation, but please don't
> hand wave away the cost of such a beast, because others may not be able to
> afford it.
>
Okay, so we're also somewhat in agreement in that respect -- heap
allocation in the manner that Boost.Variant does it is not really an option
here (I'd personally say it's not desirable even if it had some kind of
allocator support). Ultimately, my personal assessment is that if the
language had a facility like noexcept specifications and the noexcept
operator back then, Boost.Variant may have even been different and not
settled on the dynamic allocation solution (though that is admittedly just
an educated guess based on my understanding of the Boost hive mind and of
Dave A's thinking, which is ultimately what led to the dynamic allocation
solution, and which was much more reasonable at the time). When
Boost.Variant was introduced, requirements as based around nothrow
operations just weren't very feasible because it would have required
pessimistic traits that users would have had to manually specialize for
each of their field types (and that especially is unfortunate if you are
only instantiating a variant as an internal detail to something else and
the field types are coming from another user who may not have specialized
those traits). If we used the double storage solution at the time, we would
have effectively always been taking the hit even if copy-assignment
couldn't logically throw (keep in mind that this was well before we had
moves in the language and even well before move emulation existed in
Boost). At least now we'd be able to isolate double storage to when
move-constructors can throw, assuming that it is decided that people really
want the strong exception guarantee, if it were ultimately decided that we
really are okay with that double storage.
Regarding not caring about if members of your state can throw or not, I
agree that this is unfortunate, but I would say that in this case there are
alternative solutions that do not involve introducing an invalid state to
variant and yet are still functionally equivalent. For instance, regarding
a state-machine containing a variant of the states, a user can just
instantiate the variant explicitly with a fallback state (rather than
making invalid an intrinsic part of the type). This, IMO, is less than
ideal in this particular case because then you'd have to handle that state
within each visitor. Alternatively, though, the change to optional that I
suggest would simply work and be assignable, regardless of whether or not
your members have moves that can throw. I've seen some strong push-back
against that latter suggestion, but I really do think it's a solid approach
and has strong benefits that should not be excluded from consideration
simply because it is non-obvious. It effectively gives you the functional
equivalent of the invalid state but without the need to describe or handle
that state in the variant abstraction itself, and users who don't need it
(or who hold a dereferenced optional) are still able to work with a
non-empty type.
On Tue, Sep 29, 2015 at 4:01 PM, Nevin Liber <nevin@eviloverlord.com>
wrote:
> What amazes me are the sheer number of people who somehow know (yet
> unsurprisingly cannot agree on) what the One True Variant should look like,
> yet have never bothered to implement anything close to it and put it into
> production systems.
>
FWIW, I do have such a variant that I use in personal projects, though I
too am very hesitant to use that alone as evidence of the nature of certain
ideas being sound. The only way to really show that a design is sound, IMO,
is to have a solid and convincing explanation as to *why* it works and an
enumeration of common scenarios. Without that explanation, even a library
that is in widespread use can potentially come into question regarding
correctness/soundness of design since bugs or design issues can be latent.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c182267682d30520eb924b
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=
ue, Sep 29, 2015 at 4:01 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> 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-l=
eft-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extr=
a"><div class=3D"gmail_quote"><div>And what about every type that aggregate=
s a std::list?=C2=A0 I use variants for stateful states in a state machine,=
and they can get quite a lot of members.</div></div></div></div></blockquo=
te><div><br></div><div>At least we have similar use-cases (or perhaps that&=
#39;s not good assuming we really want a wider-variety of use-cases to cons=
ider). I've found variant invaluable for this kind of thing, even when =
compared to existing libraries whose explicit purpose is the creation of st=
ate machines and that perform state management behind the scenes.</div><div=
><br></div><div>On Tue, Sep 29, 2015 at 4:01 PM, Nevin Liber=C2=A0<span dir=
=3D"ltr"><<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">ne=
vin@eviloverlord.com</a>></span>=C2=A0wrote:<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div=
>I don't sit around agonizing over whether or not each member has a thr=
owing move; rather, the rest of the code assumes that the aggregate can thr=
ow unless I <i>document</i> otherwise.=C2=A0 I may be able to live with the=
double buffering provided there is no heap allocation, but please don'=
t hand wave away the cost of such a beast, because others may not be able t=
o afford it.</div></div></div></div></blockquote><div><br></div><div>Okay, =
so we're also somewhat in agreement in that respect -- heap allocation =
in the manner that Boost.Variant does it is not really an option here (I=
9;d personally say it's not desirable even if it had some kind of alloc=
ator support). Ultimately, my personal assessment is that if the language h=
ad a facility like noexcept specifications and the noexcept operator back t=
hen, Boost.Variant may have even been different and not settled on the dyna=
mic allocation solution (though that is admittedly just an educated guess b=
ased on my understanding of the Boost hive mind and of Dave A's thinkin=
g, which is ultimately what led to the dynamic allocation solution, and whi=
ch was much more reasonable at the time). When Boost.Variant was introduced=
, requirements as based around nothrow operations just weren't very fea=
sible because it would have required pessimistic traits that users would ha=
ve had to manually specialize for each of their field types (and that espec=
ially is unfortunate if you are only instantiating a variant as an internal=
detail to something else and the field types are coming from another user =
who may not have specialized those traits). If we used the double storage s=
olution at the time, we would have effectively always been taking the hit e=
ven if copy-assignment couldn't logically throw (keep in mind that this=
was well before we had moves in the language and even well before move emu=
lation existed in Boost). At least now we'd be able to isolate double s=
torage to when move-constructors can throw, assuming that it is decided tha=
t people really want the strong exception guarantee, if it were ultimately =
decided that we really are okay with that double storage.</div><div><br></d=
iv><div>Regarding not caring about if members of your state can throw or no=
t, I agree that this is unfortunate, but I would say that in this case ther=
e are alternative solutions that do not involve introducing an invalid stat=
e to variant and yet are still functionally equivalent. For instance, regar=
ding a state-machine containing a variant of the states, a user can just in=
stantiate the variant explicitly with a fallback state (rather than making =
invalid an intrinsic part of the type). This, IMO, is less than ideal in th=
is particular case because then you'd have to handle that state within =
each visitor. Alternatively, though, the change to optional that I suggest =
would simply work and be assignable, regardless of whether or not your memb=
ers have moves that can throw. I've seen some strong push-back against =
that latter suggestion, but I really do think it's a solid approach and=
has strong benefits that should not be excluded from consideration simply =
because it is non-obvious. It effectively gives you the functional equivale=
nt of the invalid state but without the need to describe or handle that sta=
te in the variant abstraction itself, and users who don't need it (or w=
ho hold a dereferenced optional) are still able to work with a non-empty ty=
pe.</div><div>=C2=A0</div><div>On Tue, Sep 29, 2015 at 4:01 PM, Nevin Liber=
=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:nevin@eviloverlord.com" targe=
t=3D"_blank">nevin@eviloverlord.com</a>></span>=C2=A0wrote:=C2=A0</div><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"g=
mail_quote"><div></div><div>What amazes me are the sheer number of people w=
ho somehow know (yet unsurprisingly cannot agree on) what the One True Vari=
ant should look like, yet have never bothered to implement anything close t=
o it and put it into production systems.</div></div></div></div></blockquot=
e><div><br></div><div>FWIW, I do have such a variant that I use in personal=
projects, though I too am very hesitant to use that alone as evidence of t=
he nature of certain ideas being sound. The only way to really show that a =
design is sound, IMO, is to have a solid and convincing explanation as to <=
i>why</i>=C2=A0it works and an enumeration of common scenarios. Without tha=
t explanation, even a library that is in widespread use can potentially com=
e into question regarding correctness/soundness of design since bugs or des=
ign issues can be latent.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c182267682d30520eb924b--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 Sep 2015 19:00:11 -0700 (PDT)
Raw View
------=_Part_1414_69728611.1443578411511
Content-Type: multipart/alternative;
boundary="----=_Part_1415_936500165.1443578411512"
------=_Part_1415_936500165.1443578411512
Content-Type: text/plain; charset=UTF-8
On Tuesday, September 29, 2015 at 6:13:05 PM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Tuesday, September 29, 2015 at 5:12:06 PM UTC-4, Matt Calabrese wrote:
>>>
>>> On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvan...@gmail.com> wrote:
>>>
>>>> My general feel is that if I try to change a Circle into a Triangle it
>>>> shouldn't become a Square. I don't think other things in the STL that
>>>> offer the basic guarantee are as "surprising". But that is just a gut
>>>> feeling.
>>>>
>>>
>>> Perhaps surprising if anyone cared to know, but users either do not
>>> observe it, or if they do observe it, they explicitly should not care. It's
>>> only a curiosity. This is the nature of the basic exception guarantee.
>>> You're not going to be relying on the object being in any specific state
>>> after the exception is thrown from the operation. In practice that usually
>>> means that programmers either ignore the value entirely when the exception
>>> makes it to them (as is usually the case when the exception further
>>> propagates beyond the lifetime of the object in question), or the user sets
>>> the value of the object to something else while handling the exception at
>>> that point in the stack. In either case, it doesn't matter what state the
>>> object is in initially when propagation starts. It is irrelevant, which is
>>> why the basic exception guarantee "works" as a guarantee and doesn't
>>> require weakening the invariants of the type. Users aren't depending on
>>> that state being anything in particular.
>>>
>>
>> That's circular logic. You're trying to argue why we don't need the
>> strong exception guarantee by saying that everyone writes code for objects
>> with the basic exception guarantee.
>>
>
> Where is the circular logic? I'm only describing *what* the basic
> guarantee is and why code can and is written correctly when only the basic
> guarantee is provided for a specific operation. If you understand that and
> the explanation then you should also understand that you don't "need" the
> strong guarantee. You never strictly need the strong guarantee. The strong
> guarantee just makes things easier for some kinds of exception handling in
> the case that it happens to exist.
>
On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> The question is not whether we could get buy with the basic exception
>> guarantee. The question is whether we *should*. And what it's worth to
>> do so.
>>
>
> I don't see why this is the consideration here. It's not been recommended
> practice since the the exception guarantees were first introduced to force
> a strong guarantee where it doesn't naturally fit. Further, the solutions
> described here for providing the strong guarantee are either only providing
> a "partial" strong guarantee (aka the basic guarantee) or are required to
> do things like make all instances of the object itself take up something
> comparable to double the storage space just in case an exception is thrown.
>
Um, no. The Williams optimization that offered what you call the "partial"
strong guarantee simply meant that you didn't have to double-buffer if only
one types wasn't nothrow moveable. Even if you undo that and therefore have
to double-buffer with only one throwing-move type... you still only pay
extra storage space if:
1) You actually use throwing-move types. Shocking though this may be to
some people... not everyone does.
2) The size of the largest nothrow moveable type is less than twice the
size of the largest throwing move type. That was the whole point of my
std::list example.
I would not call that "comparable to double the storage space" without
evidence that people use a lot of variants that would significantly
increase in size under this paradigm.
I still think that doing this is better than having an invalid state, I
> just feel it's *really* unnecessary and provides a drawback that might
> prevent people from being able or willing to use the type for their
> scenario. It's perfectly fine for an operation that throws an exception to
> specify the basic exception guarantee. We shouldn't be afraid of that.
>
OK, here is a list of all the theoretical permutations of implementing a
variant:
1 Never-empty, with strong exception guarantee.
2) Never-empty, with the basic exception guarantee.
3) Never-empty, with an invalid state on exceptions.
4) Never-empty, with no exception guarantee.
5) Possibly-empty, with the empty state on exceptions.
What you seem to be advocating is #2. But the fact is this: that is *not
implementable*.
Without an actual invalid state, there is no way to offer any kind of
exception guarantee. Not for any typelist. So long as those types do not
have a noexcept default constructor, there is no way to put the variant in
a valid-but-unspecified state.
Now, you could essentially split the difference between #2 and #4. You
could say that, on exceptions, one of the types that is noexcept default
constructible will be called. And if none are... you're SOL. There was also
the suggestion that you could implement #2 by gimping variant's interface,
making it impossible to issue throwing operations if there is no valid
default constructible fallback state.
I hope we can agree that these options are unacceptable.
The only way to have never-empty and the basic exception guarantee is #3:
an actual, detectable fallback state reachable only on exceptions.
But if you want a genuinely, never-empty-no-matter-what variant, the only
way to get that is through the strong exception guarantee.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1415_936500165.1443578411512
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Tuesday, September 29, 2015 at 6:13:05 PM UTC-4, Matt Calabrese =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote">On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <span=
dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-m=
ailto=3D"WLQ-MVsXCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'jav=
ascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;borde=
r-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On =
Tuesday, September 29, 2015 at 5:12:06 PM UTC-4, Matt Calabrese wrote:<bloc=
kquote 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;paddin=
g-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"></div></div></=
div></blockquote><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-l=
eft-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail=
_quote"><div></div></div></div></div></blockquote><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div>On Tue, Sep 29, 2015 at 1:20 =
PM, Tony V E=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">tvan...@gmail.c=
om</a>></span>=C2=A0wrote:=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"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div>My general feel is that if I try to ch=
ange a Circle into a Triangle it shouldn't become a Square.=C2=A0 I don=
't think other things in the STL that offer the basic guarantee are as =
"surprising".=C2=A0 But that is just a gut feeling.</div></div></=
div></div></blockquote><div><br></div><div>Perhaps surprising if anyone car=
ed to know, but users either do not observe it, or if they do observe it, t=
hey explicitly should not care. It's only a curiosity. This is the natu=
re of the basic exception guarantee. You're not going to be relying on =
the object being in any specific state after the exception is thrown from t=
he operation. In practice that usually means that programmers either ignore=
the value entirely when the exception makes it to them (as is usually the =
case when the exception further propagates beyond the lifetime of the objec=
t in question), or the user sets the value of the object to something else =
while handling the exception at that point in the stack. In either case, it=
doesn't matter what state the object is in initially when propagation =
starts. It is irrelevant, which is why the basic exception guarantee "=
works" as a guarantee and doesn't require weakening the invariants=
of the type. Users aren't depending on that state being anything in pa=
rticular.</div></div></div></div></blockquote><div><br>That's circular =
logic. You're trying to argue why we don't need the strong exceptio=
n guarantee by saying that everyone writes code for objects with the basic =
exception guarantee.<br></div></blockquote><div><br></div><div>Where is the=
circular logic? I'm only describing <i>what</i> the basic guarantee is=
and why code can and is written correctly when only the basic guarantee is=
provided for a specific operation. If you understand that and the explanat=
ion then you should also understand that you don't "need" the=
strong guarantee. You never strictly need the strong guarantee. The strong=
guarantee just makes things easier for some kinds of exception handling in=
the case that it happens to exist.</div></div></div></div></blockquote><di=
v><br><br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>On Tue, Sep 29, 20=
15 at 2:33 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"javascript=
:" target=3D"_blank" gdf-obfuscated-mailto=3D"WLQ-MVsXCgAJ" rel=3D"nofollow=
" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D=
"this.href=3D'javascript:';return true;">jmck...@gmail.com</a>><=
/span>=C2=A0<wbr>wrote:</div><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"><div>The question is not whet=
her we could get buy with the basic exception guarantee. The question is wh=
ether we <i>should</i>. And what it's worth to do so.<br></div></blockq=
uote><div><br></div><div>I don't see why this is the consideration here=
.. It's not been recommended practice since the the exception guarantees=
were first introduced to force a strong guarantee where it doesn't nat=
urally fit. Further, the solutions described here for providing the strong =
guarantee are either only providing a "partial" strong guarantee =
(aka the basic guarantee) or are required to do things like make all instan=
ces of the object itself take up something comparable to double the storage=
space just in case an exception is thrown.</div></div></div></div></blockq=
uote><div><br>Um, no. The Williams optimization that offered what you call =
the "partial" strong guarantee simply meant that you didn't h=
ave to double-buffer if only one types wasn't nothrow moveable. Even if=
you undo that and therefore have to double-buffer with only one throwing-m=
ove type... you still only pay extra storage space if:<br><br>1) You actual=
ly use throwing-move types. Shocking though this may be to some people... n=
ot everyone does.<br><br>2) The size of the largest nothrow moveable type i=
s less than twice the size of the largest throwing move type. That was the =
whole point of my std::list example.<br><br>I would not call that "com=
parable to double the storage space" without evidence that people use =
a lot of variants that would significantly increase in size under this para=
digm.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><div><div class=3D"gmail_quote"><div></div><div>I still think that do=
ing this is better than having an invalid state, I just feel it's <i>re=
ally</i>=C2=A0unnecessary and provides a drawback that might prevent people=
from being able or willing to use the type for their scenario. It's pe=
rfectly fine for an operation that throws an exception to specify the basic=
exception guarantee. We shouldn't be afraid of that.</div></div></div>=
</div></blockquote><div><br>OK, here is a list of all the theoretical permu=
tations of implementing a variant:<br><br>1 Never-empty, with strong except=
ion guarantee.<br><br>2) Never-empty, with the basic exception guarantee.<b=
r><br>3) Never-empty, with an invalid state on exceptions.<br><br>4) Never-=
empty, with no exception guarantee.<br><br>5) Possibly-empty, with the empt=
y state on exceptions.<br><br>What you seem to be advocating is #2. But the=
fact is this: that is <i>not implementable</i>.<br><br>Without
an actual invalid state, there is no way to offer any kind of exception
guarantee. Not for any typelist. So long as those types do not have a=20
noexcept default constructor, there is no way to put the variant in a=20
valid-but-unspecified state.<br><br>Now, you could essentially split the
difference between #2 and #4. You could say that, on exceptions, one of
the types that is noexcept default constructible will be called. And if
none are... you're SOL. There was also the suggestion that you could i=
mplement #2 by gimping variant's interface, making it impossible to iss=
ue throwing operations if there is no valid default constructible fallback =
state.<br><br>I hope we can agree that these options are unacceptable.<br><=
br>The
only way to have never-empty and the basic exception guarantee is #3:=20
an actual, detectable fallback state reachable only on exceptions.<br><br>B=
ut=20
if you want a genuinely, never-empty-no-matter-what variant, the only=20
way to get that is through the strong exception guarantee. <br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_1415_936500165.1443578411512--
------=_Part_1414_69728611.1443578411511--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 30 Sep 2015 03:50:34 -0000
Raw View
--001a11c223aa487bc10520eed587
Content-Type: text/plain; charset=UTF-8
> I hope we can agree that these options are unacceptable
Since Matt has been suggesting one of those options (ie the 'gimping'
option) I doubt he will agree.
Other than that, I like your breakdown. You might want to add some
asterisks and fine print (explaining that gimping may be required, or that
strong may be seen as just strong-ish, sometimes requires extra space etc)
but it is a useful summary.
Sent from my portable Analytical Engine
------------------------------
*From:* "Nicol Bolas" <jmckesson@gmail.com>
*To:* "ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
*Sent:* 29 September, 2015 10:00 PM
*Subject:* Re: [std-proposals] Thoughts on N4542 std::variant
On Tuesday, September 29, 2015 at 6:13:05 PM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Tuesday, September 29, 2015 at 5:12:06 PM UTC-4, Matt Calabrese wrote:
>>>
>>> On Tue, Sep 29, 2015 at 1:20 PM, Tony V E <tvan...@gmail.com> wrote:
>>>
>>>> My general feel is that if I try to change a Circle into a Triangle it
>>>> shouldn't become a Square. I don't think other things in the STL that
>>>> offer the basic guarantee are as "surprising". But that is just a gut
>>>> feeling.
>>>>
>>>
>>> Perhaps surprising if anyone cared to know, but users either do not
>>> observe it, or if they do observe it, they explicitly should not care. It's
>>> only a curiosity. This is the nature of the basic exception guarantee.
>>> You're not going to be relying on the object being in any specific state
>>> after the exception is thrown from the operation. In practice that usually
>>> means that programmers either ignore the value entirely when the exception
>>> makes it to them (as is usually the case when the exception further
>>> propagates beyond the lifetime of the object in question), or the user sets
>>> the value of the object to something else while handling the exception at
>>> that point in the stack. In either case, it doesn't matter what state the
>>> object is in initially when propagation starts. It is irrelevant, which is
>>> why the basic exception guarantee "works" as a guarantee and doesn't
>>> require weakening the invariants of the type. Users aren't depending on
>>> that state being anything in particular.
>>>
>>
>> That's circular logic. You're trying to argue why we don't need the
>> strong exception guarantee by saying that everyone writes code for objects
>> with the basic exception guarantee.
>>
>
> Where is the circular logic? I'm only describing *what* the basic
> guarantee is and why code can and is written correctly when only the basic
> guarantee is provided for a specific operation. If you understand that and
> the explanation then you should also understand that you don't "need" the
> strong guarantee. You never strictly need the strong guarantee. The strong
> guarantee just makes things easier for some kinds of exception handling in
> the case that it happens to exist.
>
On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> The question is not whether we could get buy with the basic exception
>> guarantee. The question is whether we *should*. And what it's worth to
>> do so.
>>
>
> I don't see why this is the consideration here. It's not been recommended
> practice since the the exception guarantees were first introduced to force
> a strong guarantee where it doesn't naturally fit. Further, the solutions
> described here for providing the strong guarantee are either only providing
> a "partial" strong guarantee (aka the basic guarantee) or are required to
> do things like make all instances of the object itself take up something
> comparable to double the storage space just in case an exception is thrown.
>
Um, no. The Williams optimization that offered what you call the "partial"
strong guarantee simply meant that you didn't have to double-buffer if only
one types wasn't nothrow moveable. Even if you undo that and therefore have
to double-buffer with only one throwing-move type... you still only pay
extra storage space if:
1) You actually use throwing-move types. Shocking though this may be to
some people... not everyone does.
2) The size of the largest nothrow moveable type is less than twice the
size of the largest throwing move type. That was the whole point of my
std::list example.
I would not call that "comparable to double the storage space" without
evidence that people use a lot of variants that would significantly
increase in size under this paradigm.
I still think that doing this is better than having an invalid state, I
> just feel it's *really* unnecessary and provides a drawback that might
> prevent people from being able or willing to use the type for their
> scenario. It's perfectly fine for an operation that throws an exception to
> specify the basic exception guarantee. We shouldn't be afraid of that.
>
OK, here is a list of all the theoretical permutations of implementing a
variant:
1 Never-empty, with strong exception guarantee.
2) Never-empty, with the basic exception guarantee.
3) Never-empty, with an invalid state on exceptions.
4) Never-empty, with no exception guarantee.
5) Possibly-empty, with the empty state on exceptions.
What you seem to be advocating is #2. But the fact is this: that is *not
implementable*.
Without an actual invalid state, there is no way to offer any kind of
exception guarantee. Not for any typelist. So long as those types do not
have a noexcept default constructor, there is no way to put the variant in
a valid-but-unspecified state.
Now, you could essentially split the difference between #2 and #4. You
could say that, on exceptions, one of the types that is noexcept default
constructible will be called. And if none are... you're SOL. There was also
the suggestion that you could implement #2 by gimping variant's interface,
making it impossible to issue throwing operations if there is no valid
default constructible fallback state.
I hope we can agree that these options are unacceptable.
The only way to have never-empty and the basic exception guarantee is #3:
an actual, detectable fallback state reachable only on exceptions.
But if you want a genuinely, never-empty-no-matter-what variant, the only
way to get that is through the strong exception guarantee.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c223aa487bc10520eed587
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html><head></head><body>>=C2=A0I hope we can agree that these options a=
re unacceptable<div><br></div><div>Since Matt has been suggesting one of th=
ose options (ie the 'gimping' option) I doubt he will agree.</div><=
div><br></div><div>Other than that, I like your breakdown. You might want t=
o add some asterisks and fine print (explaining that gimping may be require=
d, =C2=A0or that strong may be seen as just strong-ish, sometimes requires =
extra space etc) but it is a useful summary.=C2=A0</div><div><br></div><div=
><div id=3D"1330154144936-sig-id">Sent from my portable Analytical Engine <=
/div><br><hr><div><strong>From:</strong> "Nicol Bolas" <<a hre=
f=3D"mailto:jmckesson@gmail.com">jmckesson@gmail.com</a>><br><strong>To:=
</strong> "ISO C++ Standard - Future Proposals" <<a href=3D"ma=
ilto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>><br><strong>=
Sent:</strong> 29 September, 2015 10:00 PM<br><strong>Subject:</strong> Re:=
[std-proposals] Thoughts on N4542 std::variant<br></div><br><br><br>On Tue=
sday, September 29, 2015 at 6:13:05 PM UTC-4, Matt Calabrese wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_q=
uote">On Tue, Sep 29, 2015 at 2:33 PM, Nicol Bolas <span dir=3D"ltr"><<a=
href=3D"javascript:" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"thi=
s.href=3D'javascript:';return true;" onclick=3D"this.href=3D'ja=
vascript:';return true;">jmck...@gmail.com</a>></span> wrote:<br><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padd=
ing-left:1ex">On Tuesday, September 29, 2015 at 5:12:06 PM UTC-4, Matt Cala=
brese 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-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quot=
e"></div></div></div></blockquote><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>=
<div class=3D"gmail_quote"><div></div></div></div></div></blockquote><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w=
idth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding=
-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>On Tue, Se=
p 29, 2015 at 1:20 PM, Tony V E=C2=A0<span dir=3D"ltr"><<a rel=3D"nofoll=
ow">tvan...@gmail.com</a>></span>=C2=A0wrote:=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>My general feel is =
that if I try to change a Circle into a Triangle it shouldn't become a =
Square.=C2=A0 I don't think other things in the STL that offer the basi=
c guarantee are as "surprising".=C2=A0 But that is just a gut fee=
ling.</div></div></div></div></blockquote><div><br></div><div>Perhaps surpr=
ising if anyone cared to know, but users either do not observe it, or if th=
ey do observe it, they explicitly should not care. It's only a curiosit=
y. This is the nature of the basic exception guarantee. You're not goin=
g to be relying on the object being in any specific state after the excepti=
on is thrown from the operation. In practice that usually means that progra=
mmers either ignore the value entirely when the exception makes it to them =
(as is usually the case when the exception further propagates beyond the li=
fetime of the object in question), or the user sets the value of the object=
to something else while handling the exception at that point in the stack.=
In either case, it doesn't matter what state the object is in initiall=
y when propagation starts. It is irrelevant, which is why the basic excepti=
on guarantee "works" as a guarantee and doesn't require weake=
ning the invariants of the type. Users aren't depending on that state b=
eing anything in particular.</div></div></div></div></blockquote><div><br>T=
hat's circular logic. You're trying to argue why we don't need =
the strong exception guarantee by saying that everyone writes code for obje=
cts with the basic exception guarantee.<br></div></blockquote><div><br></di=
v><div>Where is the circular logic? I'm only describing <i>what</i> the=
basic guarantee is and why code can and is written correctly when only the=
basic guarantee is provided for a specific operation. If you understand th=
at and the explanation then you should also understand that you don't &=
quot;need" the strong guarantee. You never strictly need the strong gu=
arantee. The strong guarantee just makes things easier for some kinds of ex=
ception handling in the case that it happens to exist.</div></div></div></d=
iv></blockquote><div><br><br><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>On Tue=
, Sep 29, 2015 at 2:33 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=
=3D"javascript:" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">jmck...@gmail.com</a>></span>=C2=A0wrote:</div><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa=
dding-left:1ex"><div>The question is not whether we could get buy with the =
basic exception guarantee. The question is whether we <i>should</i>. And wh=
at it's worth to do so.<br></div></blockquote><div><br></div><div>I don=
't see why this is the consideration here. It's not been recommende=
d practice since the the exception guarantees were first introduced to forc=
e a strong guarantee where it doesn't naturally fit. Further, the solut=
ions described here for providing the strong guarantee are either only prov=
iding a "partial" strong guarantee (aka the basic guarantee) or a=
re required to do things like make all instances of the object itself take =
up something comparable to double the storage space just in case an excepti=
on is thrown.</div></div></div></div></blockquote><div><br>Um, no. The Will=
iams optimization that offered what you call the "partial" strong=
guarantee simply meant that you didn't have to double-buffer if only o=
ne types wasn't nothrow moveable. Even if you undo that and therefore h=
ave to double-buffer with only one throwing-move type... you still only pay=
extra storage space if:<br><br>1) You actually use throwing-move types. Sh=
ocking though this may be to some people... not everyone does.<br><br>2) Th=
e size of the largest nothrow moveable type is less than twice the size of =
the largest throwing move type. That was the whole point of my std::list ex=
ample.<br><br>I would not call that "comparable to double the storage =
space" without evidence that people use a lot of variants that would s=
ignificantly increase in size under this paradigm.<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><div class=3D"gmail_quot=
e"><div></div><div>I still think that doing this is better than having an i=
nvalid state, I just feel it's <i>really</i>=C2=A0unnecessary and provi=
des a drawback that might prevent people from being able or willing to use =
the type for their scenario. It's perfectly fine for an operation that =
throws an exception to specify the basic exception guarantee. We shouldn=
9;t be afraid of that.</div></div></div></div></blockquote><div><br>OK, her=
e is a list of all the theoretical permutations of implementing a variant:<=
br><br>1 Never-empty, with strong exception guarantee.<br><br>2) Never-empt=
y, with the basic exception guarantee.<br><br>3) Never-empty, with an inval=
id state on exceptions.<br><br>4) Never-empty, with no exception guarantee.=
<br><br>5) Possibly-empty, with the empty state on exceptions.<br><br>What =
you seem to be advocating is #2. But the fact is this: that is <i>not imple=
mentable</i>.<br><br>Without
an actual invalid state, there is no way to offer any kind of exception
guarantee. Not for any typelist. So long as those types do not have a=20
noexcept default constructor, there is no way to put the variant in a=20
valid-but-unspecified state.<br><br>Now, you could essentially split the
difference between #2 and #4. You could say that, on exceptions, one of
the types that is noexcept default constructible will be called. And if
none are... you're SOL. There was also the suggestion that you could i=
mplement #2 by gimping variant's interface, making it impossible to iss=
ue throwing operations if there is no valid default constructible fallback =
state.<br><br>I hope we can agree that these options are unacceptable.<br><=
br>The
only way to have never-empty and the basic exception guarantee is #3:=20
an actual, detectable fallback state reachable only on exceptions.<br><br>B=
ut=20
if you want a genuinely, never-empty-no-matter-what variant, the only=20
way to get that is through the strong exception guarantee. <br></div>
<p></p>
-- <br>
<br>
--- <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>
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>
</div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--001a11c223aa487bc10520eed587--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 Sep 2015 21:20:45 -0700
Raw View
--001a11c18226281f280520ef4145
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> On Tuesday, September 29, 2015 at 6:13:05 PM UTC-4, Matt Calabrese wrote:
>>
>> I don't see why this is the consideration here. It's not been recommended
>> practice since the the exception guarantees were first introduced to force
>> a strong guarantee where it doesn't naturally fit. Further, the solutions
>> described here for providing the strong guarantee are either only providing
>> a "partial" strong guarantee (aka the basic guarantee) or are required to
>> do things like make all instances of the object itself take up something
>> comparable to double the storage space just in case an exception is thrown.
>>
>
> Um, no. The Williams optimization that offered what you call the "partial"
> strong guarantee simply meant that you didn't have to double-buffer if only
> one types wasn't nothrow moveable.
>
I'm not sure I'm following what your "Um, no." is referring to. I'm only
stating, in the first case, that the solution doesn't actually provide the
strong exception guarantee (which has already been acknowledged), though it
is feasible to create something that would provide it when possible, as
both Anthony and I have previously stated. "Comparable to double storage"
doesn't mean "exactly double storage." That's specifically why I use the
word comparable. A variant, *without* trying to enforce the strong
exception guarantee and allowing a fallback on assignment (either to a
field type or invalid, as the storage requirements don't differ here,
excluding somewhat outlandish circumstances) in practice takes up a
discriminator and the max size of the fields, properly aligned for all
types. With the double buffering or partial double buffering that would be
required when a move constructor can throw and you are avoiding some kind
of fallback, you'd take up at least an additional amount of storage as big
as one of those field types (exactly which ones are required depends more
specifically on the situation). They're certainly comparable in the general
sense, and especially so in the worst-case scenario.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Even if you undo that and therefore have to double-buffer with only one
> throwing-move type... you still only pay extra storage space if:
>
> 1) You actually use throwing-move types. Shocking though this may be to
> some people... not everyone does.
>
I agree, and I try to avoid them at all costs, but they do (unfortunately)
come up.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> I would not call that "comparable to double the storage space" without
> evidence that people use a lot of variants that would significantly
> increase in size under this paradigm.
>
I'm just not making an assumption about the exact size, even though it
approaches double in the worst case (or at least double - discriminator).
That's why I say "comparable." Since this is a general utility, we can only
talk about specific kinds of situations that can come up and put bounds on
the worst case scenario.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> OK, here is a list of all the theoretical permutations of implementing a
> variant:
>
> 1) Never-empty, with strong exception guarantee.
>
> 2) Never-empty, with the basic exception guarantee.
>
> 3) Never-empty, with an invalid state on exceptions.
>
> 4) Never-empty, with no exception guarantee.
>
> 5) Possibly-empty, with the empty state on exceptions.
>
For clarity, 2) and 3) and 5) are *all* the basic guarantee, and "no
exception guarantee" is synonymous with "bug," so I think we all agree that
that one, at least, is not ever a valid option.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> What you seem to be advocating is #2. But the fact is this: that is *not
> implementable*.
>
Huh? Sure it is, both via my suggestion and also via a more Anthony-style
solution (though mine has more strict constraints on assignment). Even if
you didn't already understand that, this is trivially provable, since 1) is
a subset of the solutions of 2). We've talked about what it would take to
turn Anthony's current solution into something that *actually* satisfies
the strong guarantee, but it currently only satisfies the basic guarantee,
and as I've stated and as Anthony has also stated, it requires yet more
consideration to make it satisfy the strong guarantee and implies further
potential for inefficiency. I would personally be more okay with an
Anthony-like solution and a never-empty guarantee than any solution with an
invalid state, I just think it's unnecessary to even do double-buffering or
partial double-buffering, and only comes up because we are artificially
trying to *under*-constrain the operation of assignment.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Without an actual invalid state, there is no way to offer any kind of
> exception guarantee. Not for any typelist. So long as those types do not
> have a noexcept default constructor, there is no way to put the variant in
> a valid-but-unspecified state.
>
That's because you're defining your requirements separate from what the
datastructure would imply. Instead we should l*ift* the requirements from
the implementation of the datastructure and its intrinsic functions. I've
always been stating "with a fallback" or via the "optional" solution. The
suggestion is that if neither of these cases are satisfied, you've not met
the concept requirements of the assignment operation. Instead of weakening
the type's invariants and also complicating the contracts of all functions
involved, a user could simply use one of the suggested solutions.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> There was also the suggestion that you could implement #2 by gimping
> variant's interface, making it impossible to issue throwing operations if
> there is no valid default constructible fallback state.
>
> I hope we can agree that these options are unacceptable.
>
I certainly disagree, assuming that by "gimping" the interface you mean
"accurately reflecting the requirements of assignment in a way that
wouldn't imply inflating the type's size or weakening the type's
invariants."
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> But if you want a genuinely, never-empty-no-matter-what variant, the only
> way to get that is through the strong exception guarantee.
>
Again, this is simply not true.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c18226281f280520ef4145
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=
ue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> 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-st=
yle:solid;padding-left:1ex">On Tuesday, September 29, 2015 at 6:13:05 PM UT=
C-4, Matt Calabrese wrote:<span class=3D""><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><div class=3D"gmail_quote"><div>I don't see why this is the cons=
ideration here. It's not been recommended practice since the the except=
ion guarantees were first introduced to force a strong guarantee where it d=
oesn't naturally fit. Further, the solutions described here for providi=
ng the strong guarantee are either only providing a "partial" str=
ong guarantee (aka the basic guarantee) or are required to do things like m=
ake all instances of the object itself take up something comparable to doub=
le the storage space just in case an exception is thrown.</div></div></div>=
</div></blockquote></span><div><br>Um, no. The Williams optimization that o=
ffered what you call the "partial" strong guarantee simply meant =
that you didn't have to double-buffer if only one types wasn't noth=
row moveable.</div></blockquote><div><br></div><div>I'm not sure I'=
m following what your "Um, no." is referring to. I'm only sta=
ting, in the first case, that the solution doesn't actually provide the=
strong exception guarantee (which has already been acknowledged), though i=
t is feasible to create something that would provide it when possible, as b=
oth Anthony and I have previously stated. "Comparable to double storag=
e" doesn't mean "exactly double storage." That's spe=
cifically why I use the word comparable. A variant, <i>without</i> trying t=
o enforce the strong exception guarantee and allowing a fallback on assignm=
ent (either to a field type or invalid, as the storage requirements don'=
;t differ here, excluding somewhat outlandish circumstances) in practice ta=
kes up a discriminator and the max size of the fields, properly aligned for=
all types. With the double buffering or partial double buffering that woul=
d be required when a move constructor can throw and you are avoiding some k=
ind of fallback, you'd take up at least an additional amount of storage=
as big as one of those field types (exactly which ones are required depend=
s more specifically on the situation). They're certainly comparable in =
the general sense, and especially so in the worst-case scenario.</div><div>=
<br></div><div>=C2=A0On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<spa=
n dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">=
jmckesson@gmail.com</a>></span>=C2=A0wrote:</div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div> =
Even if you undo that and therefore have to double-buffer with only one thr=
owing-move type... you still only pay extra storage space if:</div></blockq=
uote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div><br>1) You actually use throwing-move types. Sho=
cking though this may be to some people... not everyone does.<br></div></bl=
ockquote><div><br></div><div>I agree, and I try to avoid them at all costs,=
but they do (unfortunately) come up.</div><div><br></div><div>On Tue, Sep =
29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mail=
to:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span=
>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border=
-left-style:solid;padding-left:1ex"><div>I would not call that "compar=
able to double the storage space" without evidence that people use a l=
ot of variants that would significantly increase in size under this paradig=
m.<br></div></blockquote><div><br></div><div>I'm just not making an ass=
umption about the exact size, even though it approaches double in the worst=
case (or at least double - discriminator). That's why I say "comp=
arable." Since this is a general utility, we can only talk about speci=
fic kinds of situations that can come up and put bounds on the worst case s=
cenario.</div><div><br></div><div>On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bo=
las=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" targe=
t=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:</div><blockquot=
e 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-lef=
t:1ex"><div>OK, here is a list of all the theoretical permutations of imple=
menting a variant:<br><br>1) Never-empty, with strong exception guarantee.<=
br><br>2) Never-empty, with the basic exception guarantee.<br><br>3) Never-=
empty, with an invalid state on exceptions.<br><br>4) Never-empty, with no =
exception guarantee.<br><br>5) Possibly-empty, with the empty state on exce=
ptions.<br></div></blockquote><div><br></div><div>For clarity, 2) and 3) an=
d 5) are=C2=A0<i>all</i>=C2=A0the basic guarantee, and "no exception g=
uarantee" is synonymous with "bug," so I think we all agree =
that that one, at least, is not ever a valid option.</div><div><br></div><d=
iv>On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><=
<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.co=
m</a>></span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div>What you seem to =
be advocating is #2. But the fact is this: that is <i>not implementable</i>=
..</div></blockquote><div><br></div><div>Huh? Sure it is, both via my sugges=
tion and also via a more Anthony-style solution (though mine has more stric=
t constraints on assignment). Even if you didn't already understand tha=
t, this is trivially provable, since 1) is a subset of the solutions of 2).=
We've talked about what it would take to turn Anthony's current so=
lution into something that <i>actually</i>=C2=A0satisfies the strong guaran=
tee, but it currently only satisfies the basic guarantee, and as I've s=
tated and as Anthony has also stated, it requires yet more consideration to=
make it satisfy the strong guarantee and implies further potential for ine=
fficiency. I would personally be more okay with an Anthony-like solution an=
d a never-empty guarantee than any solution with an invalid state, I just t=
hink it's unnecessary to even do double-buffering or partial double-buf=
fering, and only comes up because we are artificially trying to <i>under</i=
>-constrain the operation of assignment.</div><div><br></div><div>On Tue, S=
ep 29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan>=C2=A0wrote:</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);bor=
der-left-style:solid;padding-left:1ex"><div>Without
an actual invalid state, there is no way to offer any kind of exception
guarantee. Not for any typelist. So long as those types do not have a noex=
cept default constructor, there is no way to put the variant in a valid-but=
-unspecified state.</div></blockquote><div><br></div><div>That's becaus=
e you're defining your requirements separate from what the datastructur=
e would imply. Instead we should l<i>ift</i>=C2=A0the requirements from the=
implementation of the datastructure and its intrinsic functions.=C2=A0I=
9;ve always been stating "with a fallback" or via the "optio=
nal" solution. The suggestion is that if neither of these cases are sa=
tisfied, you've not met the concept requirements of the assignment oper=
ation. Instead of weakening the type's invariants and also complicating=
the contracts of all functions involved, a user could simply use one of th=
e suggested solutions.</div><div><br></div><div>=C2=A0On Tue, Sep 29, 2015 =
at 7:00 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckes=
son@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wr=
ote:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div>There was also the suggestion that you coul=
d implement #2 by gimping variant's interface, making it impossible to =
issue throwing operations if there is no valid default constructible fallba=
ck state.<br><br>I hope we can agree that these options are unacceptable.<b=
r></div></blockquote><div><br></div><div>I certainly disagree, assuming tha=
t by "gimping" the interface you mean "accurately reflecting=
the requirements of assignment in a way that wouldn't imply inflating =
the type's size or weakening the type's invariants."</div><div=
><br></div><div>=C2=A0On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<sp=
an dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank"=
>jmckesson@gmail.com</a>></span>=C2=A0wrote:</div><blockquote class=3D"g=
mail_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>=
But=20
if you want a genuinely, never-empty-no-matter-what variant, the only=20
way to get that is through the strong exception guarantee.<br></div></block=
quote><div><br></div><div>Again, this is simply not true.</div></div></div>=
</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c18226281f280520ef4145--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 30 Sep 2015 11:02:24 -0400
Raw View
--001a11403322df8be70520f83752
Content-Type: text/plain; charset=UTF-8
On Tue, Sep 29, 2015 at 5:55 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Tue, Sep 29, 2015 at 2:33 PM, Tony V E <tvaneerd@gmail.com> wrote:
>>
>> Design-wise, I think it is WRONG for variant<X> = variant<X> to be
>> different from x = x. No question.
>>
>> The only question, to me, is whether this (and the fact that it might
>> only be the basic guarantee), means that the strong guarantee when
>> switching types X = Y is not worth it.
>>
>
> Okay I think you and I at least are somewhat in agreement on this
> particular point. My personal thoughts are that, whatever we do, it should
> have a consistent rule for variant<T...> even when sizeof...(T) is 1.
> Otherwise, when T... is dependent, you wouldn't be able to rely on the
> strong guarantee anyway, unless you branched off for the sizeof(T) == 1
> case (or I guess you could also disallow a variant with 1 field for your
> particular template if that were an acceptable choice). IMO, thinking about
> this in the generic sense where T... is dependent is an extremely important
> consideration here, since that is precisely when a variant with exactly one
> field type tends to come up. By that I mean, if T... wasn't dependent, then
> you probably would have just used T directly instead of variant<T> to begin
> with. Explicitly writing variant<int> isn't common in real-world code
> because users could simply use an int in most cases. However, people might
> do variant<T...> where T... happens to end up being a size 1 variadic list
> of types, and where that type just so happens to be int. In this case, if
> behavior weren't consistent between sizeof...(T) == 1, and sizeof...(T) >
> 1, then it would be difficult for them to write generic code that could
> rely on the more strict guarantee. They'd either have to do complex
> branching and have code to handle the weaker guarantee anyway, or they'd
> just handle it by way of the weaker guarantee in all cases so as to avoid
> the complicated branching.
>
> --
>
To be clear, I don't just mean variant<X> = variant<X>, I mean
X x1, x2;
variant<X,Y>(x1) = variant<X,Y>(x2)
That should be the same as (if I got the syntax right in an email)
get<X&>(variant<X,Y>(x1)) = x2
ie any time you are not switching types, variant should get out of the way
and let X do whatever it does.
Variant's job is managing the type switch (and access to the current
type+value). When there is no type-switch, variant shouldn't be involved.
(That's why, for me, from variant's perspective Wiliams variant does offer
the strong guarantee - the variant portion (the discriminator) is unchanged)
Tony
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11403322df8be70520f83752
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Sep 29, 2015 at 5:55 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote">On Tue, Sep 29, 2015 at 2:33 PM, Tony=
V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"=
_blank">tvaneerd@gmail.com</a>></span> wrote:<blockquote class=3D"gmail_=
quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<div>Design-wise, I think it is WRONG for variant<X> =3D variant<X=
> to be different from x =3D x.=C2=A0 No question.<br></div><div><br>The=
only question, to me, is whether this (and the fact that it might only be =
the basic guarantee), means that the strong guarantee when switching types =
X =3D Y is not worth it.<br></div></div></div></div></blockquote><div><br><=
/div><div>Okay I think you and I at least are somewhat in agreement on this=
particular point. My personal thoughts are that, whatever we do, it should=
have a consistent rule for variant<T...> even when sizeof...(T) is 1=
.. Otherwise, when T... is dependent, you wouldn't be able to rely on th=
e strong guarantee anyway, unless you branched off for the sizeof(T) =3D=3D=
1 case (or I guess you could also disallow a variant with 1 field for your=
particular template if that were an acceptable choice). IMO, thinking abou=
t this in the generic sense where T... is dependent is an extremely importa=
nt consideration here, since that is precisely when a variant with exactly =
one field type tends to come up. By that I mean, if T... wasn't depende=
nt, then you probably would have just used T directly instead of variant<=
;T> to begin with. Explicitly writing variant<int> isn't commo=
n in real-world code because users could simply use an int in most cases. H=
owever, people might do variant<T...> where T... happens to end up be=
ing a size 1 variadic list of types, and where that type just so happens to=
be int. In this case, if behavior weren't consistent between sizeof...=
(T) =3D=3D 1, and sizeof...(T) > 1, then it would be difficult for them =
to write generic code that could rely on the more strict guarantee. They=
9;d either have to do complex branching and have code to handle the weaker =
guarantee anyway, or they'd just handle it by way of the weaker guarant=
ee in all cases so as to avoid the complicated branching.</div></div></div>=
</div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br></div></div></blockquote><div><br></div><div>To be clear, I don'=
t just mean variant<X> =3D variant<X>, I mean<br><br></div><div=
>=C2=A0=C2=A0=C2=A0 X x1, x2;<br></div><div>=C2=A0 =C2=A0 variant<X,Y>=
;(x1) =3D variant<X,Y>(x2)<br><br></div><div>That should be the same =
as (if I got the syntax right in an email)<br><br></div><div>=C2=A0 =C2=A0 =
get<X&>(variant<X,Y>(x1)) =3D x2 <br></div><div><br></div><=
div>ie any time you are not switching types, variant should get out of the =
way and let X do whatever it does.<br></div><div>Variant's job is manag=
ing the type switch (and access to the current type+value).=C2=A0 When ther=
e is no type-switch, variant shouldn't be involved.<br><br></div><div>(=
That's why, for me, from variant's perspective Wiliams variant does=
offer the strong guarantee - the variant portion (the discriminator) is un=
changed)<br><br></div><div>Tony<br></div><div><br><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5">
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11403322df8be70520f83752--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 Sep 2015 08:03:16 -0700 (PDT)
Raw View
------=_Part_5938_886071807.1443625396920
Content-Type: multipart/alternative;
boundary="----=_Part_5939_668755935.1443625396921"
------=_Part_5939_668755935.1443625396921
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 30, 2015 at 12:20:47 AM UTC-4, Matt Calabrese wrote:
>
> On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>>
>> On Tuesday, September 29, 2015 at 6:13:05 PM UTC-4, Matt Calabrese wrote:
>>>
>>> I don't see why this is the consideration here. It's not been
>>> recommended practice since the the exception guarantees were first
>>> introduced to force a strong guarantee where it doesn't naturally fit.
>>> Further, the solutions described here for providing the strong guarantee
>>> are either only providing a "partial" strong guarantee (aka the basic
>>> guarantee) or are required to do things like make all instances of the
>>> object itself take up something comparable to double the storage space just
>>> in case an exception is thrown.
>>>
>>
>> Um, no. The Williams optimization that offered what you call the
>> "partial" strong guarantee simply meant that you didn't have to
>> double-buffer if only one types wasn't nothrow moveable.
>>
>
> I'm not sure I'm following what your "Um, no." is referring to. I'm only
> stating, in the first case, that the solution doesn't actually provide the
> strong exception guarantee (which has already been acknowledged), though it
> is feasible to create something that would provide it when possible, as
> both Anthony and I have previously stated. "Comparable to double storage"
> doesn't mean "exactly double storage." That's specifically why I use the
> word comparable. A variant, *without* trying to enforce the strong
> exception guarantee and allowing a fallback on assignment (either to a
> field type or invalid, as the storage requirements don't differ here,
> excluding somewhat outlandish circumstances) in practice takes up a
> discriminator and the max size of the fields, properly aligned for all
> types. With the double buffering or partial double buffering that would be
> required when a move constructor can throw and you are avoiding some kind
> of fallback, you'd take up at least an additional amount of storage as big
> as one of those field types (exactly which ones are required depends more
> specifically on the situation). They're certainly comparable in the general
> sense, and especially so in the worst-case scenario.
>
> On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> Even if you undo that and therefore have to double-buffer with only one
>> throwing-move type... you still only pay extra storage space if:
>>
>
>> 1) You actually use throwing-move types. Shocking though this may be to
>> some people... not everyone does.
>>
>
> I agree, and I try to avoid them at all costs, but they do (unfortunately)
> come up.
>
> On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> I would not call that "comparable to double the storage space" without
>> evidence that people use a lot of variants that would significantly
>> increase in size under this paradigm.
>>
>
> I'm just not making an assumption about the exact size, even though it
> approaches double in the worst case (or at least double - discriminator).
> That's why I say "comparable." Since this is a general utility, we can only
> talk about specific kinds of situations that can come up and put bounds on
> the worst case scenario.
>
> On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> OK, here is a list of all the theoretical permutations of implementing a
>> variant:
>>
>> 1) Never-empty, with strong exception guarantee.
>>
>> 2) Never-empty, with the basic exception guarantee.
>>
>> 3) Never-empty, with an invalid state on exceptions.
>>
>> 4) Never-empty, with no exception guarantee.
>>
>> 5) Possibly-empty, with the empty state on exceptions.
>>
>
> For clarity, 2) and 3) and 5) are *all* the basic guarantee, and "no
> exception guarantee" is synonymous with "bug," so I think we all agree that
> that one, at least, is not ever a valid option.
>
Well, you've made the case that #4 is at least reasonable. After all, one
of your prior claims was that most people don't bother to use the variant
after assignment failures. Thus, they don't really care what state it is
in; they just let the object die.
If that's true, that's a good argument for not even bothering with the
basic guarantee.
Granted, that's a terrible idea, but it's a terrible idea because I don't
buy your argument that most people don't care.
>
> On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> What you seem to be advocating is #2. But the fact is this: that is *not
>> implementable*.
>>
>
> Huh? Sure it is, both via my suggestion and also via a more Anthony-style
> solution (though mine has more strict constraints on assignment). Even if
> you didn't already understand that, this is trivially provable, since 1) is
> a subset of the solutions of 2). We've talked about what it would take to
> turn Anthony's current solution into something that *actually* satisfies
> the strong guarantee, but it currently only satisfies the basic guarantee,
>
That's one way to see it. Another way to see it is that it satisfies *at
least* the guarantee that the objects themselves provide. If your
throwing-move types provide a basic guarantee, then variant will not fix
that for you. If your throwing-move types provide the strong guarantee,
then variant will ensure that a variant containing them will *also* provide
that guarantee.
So it's incorrect to say that such a `variant` only satisfies the basic
guarantee. Just as its incorrect to say that `variant` is not copyable or
not moveable.
A variant is whatever its types say that it is. That's the point of
`variant`: it offers the intersection of functionality for the types you
provide. If all the types but one are copyable, then the entire object is
non-copyable. If all of the types but one are moveable, then the entire
object is non-moveable.
And if all of the types but one offer the strong guarantee, then variant
doesn't offer the strong guarantee.
Variant should express the behavior of its typelist as much as possible.
And that should include exception guarantees. If the typelist is all
strong, the `variant` of them should be no less than strong. If the
typelist is basic, the `variant` of them should be no less than basic.
It may be more in some cases, but it should never be less.
I have moral objections with a variant interfering with the behavior of its
typelist.
That's why I like `optional`'s exception guarantee: It is exactly the
behavior of T. If T offers the basic guarantee, so too does `optional<T>`.
If it offers the strong guarantee, so too does `optional<T>`.
It puts the onus on the *types*, not the type acting as a proxy.
> I would personally be more okay with an Anthony-like solution and a
> never-empty guarantee than any solution with an invalid state, I just think
> it's unnecessary to even do double-buffering or partial double-buffering,
> and only comes up because we are artificially trying to *under*-constrain
> the operation of assignment.
>
No, we are trying to allow variant to express the intersection behavior of
its typelist.
> On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> Without an actual invalid state, there is no way to offer any kind of
>> exception guarantee. Not for any typelist. So long as those types do not
>> have a noexcept default constructor, there is no way to put the variant in
>> a valid-but-unspecified state.
>>
>
> That's because you're defining your requirements separate from what the
> datastructure would imply. Instead we should l*ift* the requirements from
> the implementation of the datastructure and its intrinsic functions. I've
> always been stating "with a fallback" or via the "optional" solution. The
> suggestion is that if neither of these cases are satisfied, you've not met
> the concept requirements of the assignment operation. Instead of weakening
> the type's invariants and also complicating the contracts of all functions
> involved, a user could simply use one of the suggested solutions.
>
Solutions that *do not exist*. Remember: no version of `optional` works the
way you need it to in order to be a valid solution (ie: switch to nullopt
on exception failure and synthesize operations that T does not allow). And
if the typelist doesn't contain a "fallback" state, then you have a gimped
type *with no recourse* to fix it.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> There was also the suggestion that you could implement #2 by gimping
>> variant's interface, making it impossible to issue throwing operations if
>> there is no valid default constructible fallback state.
>>
>> I hope we can agree that these options are unacceptable.
>>
>
> I certainly disagree, assuming that by "gimping" the interface you mean
> "accurately reflecting the requirements of assignment in a way that
> wouldn't imply inflating the type's size or weakening the type's
> invariants."
>
If you make it so that the variant cannot reflect the operations that are
possible on a type, then you are gimping the interface of the variant. If
you prevent a variant from being copyable/moveable/emplace-constructable
even if the types all support that option, then you have gimped the
interface.
Again, `variant<X> = variant<X>` should be equivalent to `x = x`. So if the
type is copyable, a `variant` of that type should be *just as copyable*
(and if it throws, the result should be the same). Otherwise, you have
gimped the interface.
The "requirements of assignment" that variant should provide are "do what
the type allows." If they're copyable, the variant is copyable. If they are
noexcept copyable, the variant is noexcept copyable. And so on.
If a variant doesn't do what the types (as an aggregate) permit, then it is
not "accurately reflecting the requirements of assignment." That's why I
call it "gimping the interface"; you're arbitrarily handicapping the use of
an object.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> But if you want a genuinely, never-empty-no-matter-what variant, the only
>> way to get that is through the strong exception guarantee.
>>
>
> Again, this is simply not true.
>
OK, if you want a genuinely, never-empty-no-matter-what variant with a
fully functional interface, the only way to get that is through the strong
exception guarantee.
But I assumed that having a type that actually does what it is *supposed*
to do went without saying.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5939_668755935.1443625396921
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Wednesday, September 30, 2015 at 12:20:47 AM UTC-4, Matt Calabre=
se 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"><div=
><div class=3D"gmail_quote">On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <s=
pan dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscate=
d-mailto=3D"Vac0CWwrCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;return true;">jmck...@gmail.com</a>></span> 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">On T=
uesday, September 29, 2015 at 6:13:05 PM UTC-4, Matt Calabrese wrote:<span>=
<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;p=
adding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>I do=
n't see why this is the consideration here. It's not been recommend=
ed practice since the the exception guarantees were first introduced to for=
ce a strong guarantee where it doesn't naturally fit. Further, the solu=
tions described here for providing the strong guarantee are either only pro=
viding a "partial" strong guarantee (aka the basic guarantee) or =
are required to do things like make all instances of the object itself take=
up something comparable to double the storage space just in case an except=
ion is thrown.</div></div></div></div></blockquote></span><div><br>Um, no. =
The Williams optimization that offered what you call the "partial"=
; strong guarantee simply meant that you didn't have to double-buffer i=
f only one types wasn't nothrow moveable.</div></blockquote><div><br></=
div><div>I'm not sure I'm following what your "Um, no." i=
s referring to. I'm only stating, in the first case, that the solution =
doesn't actually provide the strong exception guarantee (which has alre=
ady been acknowledged), though it is feasible to create something that woul=
d provide it when possible, as both Anthony and I have previously stated. &=
quot;Comparable to double storage" doesn't mean "exactly doub=
le storage." That's specifically why I use the word comparable. A =
variant, <i>without</i> trying to enforce the strong exception guarantee an=
d allowing a fallback on assignment (either to a field type or invalid, as =
the storage requirements don't differ here, excluding somewhat outlandi=
sh circumstances) in practice takes up a discriminator and the max size of =
the fields, properly aligned for all types. With the double buffering or pa=
rtial double buffering that would be required when a move constructor can t=
hrow and you are avoiding some kind of fallback, you'd take up at least=
an additional amount of storage as big as one of those field types (exactl=
y which ones are required depends more specifically on the situation). They=
're certainly comparable in the general sense, and especially so in the=
worst-case scenario.</div><div><br></div><div>=C2=A0On Tue, Sep 29, 2015 a=
t 7:00 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" t=
arget=3D"_blank" gdf-obfuscated-mailto=3D"Vac0CWwrCgAJ" rel=3D"nofollow" on=
mousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"thi=
s.href=3D'javascript:';return true;">jmck...@gmail.com</a>></spa=
n>=C2=A0<wbr>wrote:</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"><div> Even if you undo that and t=
herefore have to double-buffer with only one throwing-move type... you stil=
l only pay extra storage space if:</div></blockquote><blockquote class=3D"g=
mail_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>=
<br>1) You actually use throwing-move types. Shocking though this may be to=
some people... not everyone does.<br></div></blockquote><div><br></div><di=
v>I agree, and I try to avoid them at all costs, but they do (unfortunately=
) come up.</div><div><br></div><div>On Tue, Sep 29, 2015 at 7:00 PM, Nicol =
Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"Vac0CWwrCgAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrot=
e:</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"><div>I would not call that "comparable to dou=
ble the storage space" without evidence that people use a lot of varia=
nts that would significantly increase in size under this paradigm.<br></div=
></blockquote><div><br></div><div>I'm just not making an assumption abo=
ut the exact size, even though it approaches double in the worst case (or a=
t least double - discriminator). That's why I say "comparable.&quo=
t; Since this is a general utility, we can only talk about specific kinds o=
f situations that can come up and put bounds on the worst case scenario.</d=
iv><div><br></div><div>On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<s=
pan dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscate=
d-mailto=3D"Vac0CWwrCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;return true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:</div><bloc=
kquote 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;paddin=
g-left:1ex"><div>OK, here is a list of all the theoretical permutations of =
implementing a variant:<br><br>1) Never-empty, with strong exception guaran=
tee.<br><br>2) Never-empty, with the basic exception guarantee.<br><br>3) N=
ever-empty, with an invalid state on exceptions.<br><br>4) Never-empty, wit=
h no exception guarantee.<br><br>5) Possibly-empty, with the empty state on=
exceptions.<br></div></blockquote><div><br></div><div>For clarity, 2) and =
3) and 5) are=C2=A0<i>all</i>=C2=A0the basic guarantee, and "no except=
ion guarantee" is synonymous with "bug," so I think we all a=
gree that that one, at least, is not ever a valid option.</div></div></div>=
</div></blockquote><div><br>Well, you've made the case that #4 is at le=
ast reasonable. After all, one of your prior claims was that most people do=
n't bother to use the variant after assignment failures. Thus, they don=
't really care what state it is in; they just let the object die.<br><b=
r>If that's true, that's a good argument for not even bothering wit=
h the basic guarantee.<br><br>Granted, that's a terrible idea, but it&#=
39;s a terrible idea because I don't buy your argument that most people=
don't care.<br>=C2=A0</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><div class=3D"gmail_quote"><div><br></div><div>On T=
ue, Sep 29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"Vac0CWwrCgAJ" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return tru=
e;" onclick=3D"this.href=3D'javascript:';return true;">jmck...@gmai=
l.com</a>></span>=C2=A0<wbr>wrote:</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"><div>What you s=
eem to be advocating is #2. But the fact is this: that is <i>not implementa=
ble</i>.</div></blockquote><div><br></div><div>Huh? Sure it is, both via my=
suggestion and also via a more Anthony-style solution (though mine has mor=
e strict constraints on assignment). Even if you didn't already underst=
and that, this is trivially provable, since 1) is a subset of the solutions=
of 2). We've talked about what it would take to turn Anthony's cur=
rent solution into something that <i>actually</i>=C2=A0satisfies the strong=
guarantee, but it currently only satisfies the basic guarantee,</div></div=
></div></div></blockquote><div><br>That's one way to see it. Another wa=
y to see it is that it satisfies <i>at least</i> the guarantee that the obj=
ects themselves provide. If your throwing-move types provide a basic guaran=
tee, then variant will not fix that for you. If your throwing-move types pr=
ovide the strong guarantee, then variant will ensure that a variant contain=
ing them will <i>also</i> provide that guarantee.<br><br>So it's incorr=
ect to say that such a `variant` only satisfies the basic guarantee. Just a=
s its incorrect to say that `variant` is not copyable or not moveable.<br><=
br>A variant is whatever its types say that it is. That's the point of =
`variant`: it offers the intersection of functionality for the types you pr=
ovide. If all the types but one are copyable, then the entire object is non=
-copyable. If all of the types but one are moveable, then the entire object=
is non-moveable.<br><br>And if all of the types but one offer the strong g=
uarantee, then variant doesn't offer the strong guarantee.<br><br>Varia=
nt should express the behavior of its typelist as much as possible. And tha=
t should include exception guarantees. If the typelist is all strong, the `=
variant` of them should be no less than strong. If the typelist is basic, t=
he `variant` of them should be no less than basic.<br><br>It may be more in=
some cases, but it should never be less.<br><br>I have moral objections wi=
th a variant interfering with the behavior of its typelist.<br><br>That'=
;s why I like `optional`'s exception guarantee: It is exactly the behav=
ior of T. If T offers the basic guarantee, so too does `optional<T>`.=
If it offers the strong guarantee, so too does `optional<T>`.<br><br=
>It puts the onus on the <i>types</i>, not the type acting as a proxy.<br>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><div class=3D"gmail_quote"><div>I would personally be more okay with an=
Anthony-like solution and a never-empty guarantee than any solution with a=
n invalid state, I just think it's unnecessary to even do double-buffer=
ing or partial double-buffering, and only comes up because we are artificia=
lly trying to <i>under</i>-constrain the operation of assignment.</div></di=
v></div></div></blockquote><div><br>No, we are trying to allow variant to e=
xpress the intersection behavior of its typelist.<br>=C2=A0</div><blockquot=
e 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><div class=3D"gmai=
l_quote"><div>On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas=C2=A0<span dir=
=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailt=
o=3D"Vac0CWwrCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex"><div>Without
an actual invalid state, there is no way to offer any kind of exception
guarantee. Not for any typelist. So long as those types do not have a noex=
cept default constructor, there is no way to put the variant in a valid-but=
-unspecified state.</div></blockquote><div><br></div><div>That's becaus=
e you're defining your requirements separate from what the datastructur=
e would imply. Instead we should l<i>ift</i>=C2=A0the requirements from the=
implementation of the datastructure and its intrinsic functions.=C2=A0I=
9;ve always been stating "with a fallback" or via the "optio=
nal" solution. The suggestion is that if neither of these cases are sa=
tisfied, you've not met the concept requirements of the assignment oper=
ation. Instead of weakening the type's invariants and also complicating=
the contracts of all functions involved, a user could simply use one of th=
e suggested solutions.</div></div></div></div></blockquote><div><br>Solutio=
ns that <i>do not exist</i>. Remember: no version of `optional` works the w=
ay you need it to in order to be a valid solution (ie: switch to nullopt on=
exception failure and synthesize operations that T does not allow). And if=
the typelist doesn't contain a "fallback" state, then you ha=
ve a gimped type <i>with no recourse</i> to fix it.<br><br></div><blockquot=
e 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><div class=3D"gmai=
l_quote"><div></div><div>=C2=A0On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas=
=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-o=
bfuscated-mailto=3D"Vac0CWwrCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:</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>There was also the suggestion that you could imple=
ment #2 by gimping variant's interface, making it impossible to issue t=
hrowing operations if there is no valid default constructible fallback stat=
e.<br><br>I hope we can agree that these options are unacceptable.<br></div=
></blockquote><div><br></div><div>I certainly disagree, assuming that by &q=
uot;gimping" the interface you mean "accurately reflecting the re=
quirements of assignment in a way that wouldn't imply inflating the typ=
e's size or weakening the type's invariants."</div></div></div=
></div></blockquote><div><br>If you make it so that the variant cannot refl=
ect the operations that are possible on a type, then you are gimping the in=
terface of the variant. If you prevent a variant from being copyable/moveab=
le/emplace-constructable even if the types all support that option, then yo=
u have gimped the interface.<br><br>Again, `variant<X> =3D variant<=
;X>` should be equivalent to `x =3D x`. So if the type is copyable, a `v=
ariant` of that type should be <i>just as copyable</i> (and if it throws, t=
he result should be the same). Otherwise, you have gimped the interface.<br=
><br>The "requirements of assignment" that variant should provide=
are "do what the type allows." If they're copyable, the vari=
ant is copyable. If they are noexcept copyable, the variant is noexcept cop=
yable. And so on.<br><br>If a variant doesn't do what the types (as an =
aggregate) permit, then it is not "accurately reflecting the requireme=
nts of assignment." That's why I call it "gimping the interfa=
ce"; you're arbitrarily handicapping the use of an object.<br><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote"><div></div><div>=C2=A0On Tue, Sep 29, 2015 at 7:00=
PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"Vac0CWwrCgAJ" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hre=
f=3D'javascript:';return true;">jmck...@gmail.com</a>></span>=C2=
=A0<wbr>wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);borde=
r-left-style:solid;padding-left:1ex"><div>But=20
if you want a genuinely, never-empty-no-matter-what variant, the only=20
way to get that is through the strong exception guarantee.<br></div></block=
quote><div><br></div><div>Again, this is simply not true.</div></div></div>=
</div></blockquote><div><br>OK, if you want a genuinely, never-empty-no-mat=
ter-what variant with a fully functional interface, the only=20
way to get that is through the strong exception guarantee.<br><br>But I ass=
umed that having a type that actually does what it is <i>supposed</i> to do=
went without saying.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_5939_668755935.1443625396921--
------=_Part_5938_886071807.1443625396920--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Wed, 30 Sep 2015 10:18:17 -0500
Raw View
--001a114363acfae9960520f87294
Content-Type: text/plain; charset=UTF-8
On 30 September 2015 at 10:02, Tony V E <tvaneerd@gmail.com> wrote:
> That should be the same as (if I got the syntax right in an email)
>
> get<X&>(variant<X,Y>(x1)) = x2
>
> ie any time you are not switching types, variant should get out of the way
> and let X do whatever it does.
> Variant's job is managing the type switch (and access to the current
> type+value). When there is no type-switch, variant shouldn't be involved.
>
> (That's why, for me, from variant's perspective Wiliams variant does offer
> the strong guarantee - the variant portion (the discriminator) is unchanged)
>
It's great that you have your own personal definitions for things, but if
you take the definitions given at <
http://www.boost.org/community/exception_safety.html>:
- The *basic* guarantee: that the invariants of the component are
preserved, and no resources are leaked.
- The *strong* guarantee: that the operation has either completed
successfully or thrown an exception, leaving the program state exactly as
it was before the operation started.
- The *no-throw* guarantee: that the operation will not throw an
exception.
In general, I don't see how that meets anything except the basic guarantee
(well, not even that, if you have an insane assignment operator for your
type).
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a114363acfae9960520f87294
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 30 September 2015 at 10:02, Tony V E <span dir=3D"ltr">=
<<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.=
com</a>></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">That should be the same as (if I =
got the syntax right in an email)<br><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div><br></div><div>=C2=A0 =C2=A0 get<X&>(varian=
t<X,Y>(x1)) =3D x2 <br></div><div><br></div><div>ie any time you are =
not switching types, variant should get out of the way and let X do whateve=
r it does.<br></div><div>Variant's job is managing the type switch (and=
access to the current type+value).=C2=A0 When there is no type-switch, var=
iant shouldn't be involved.<br><br></div><div>(That's why, for me, =
from variant's perspective Wiliams variant does offer the strong guaran=
tee - the variant portion (the discriminator) is unchanged)</div></div></di=
v></div></blockquote><div><br></div><div>It's great that you have your =
own personal definitions for things, but if you take the definitions given =
at <<a href=3D"http://www.boost.org/community/exception_safety.html" tar=
get=3D"_blank">http://www.boost.org/community/exception_safety.html</a>>=
:</div><div><br></div><div><ul style=3D"margin:0em 0em 1.5em;padding:0em;fo=
nt-size:13px;list-style:circle;color:rgb(0,0,0);font-family:sans-serif"><li=
style=3D"margin:0em 0em 0em 1.25em;padding:0em;text-indent:0em">The=C2=A0<=
i style=3D"margin:0px;padding:0px">basic</i>=C2=A0guarantee: that the invar=
iants of the component are preserved, and no resources are leaked.</li><li =
style=3D"margin:0em 0em 0em 1.25em;padding:0em;text-indent:0em">The=C2=A0<i=
style=3D"margin:0px;padding:0px">strong</i>=C2=A0guarantee: that the opera=
tion has either completed successfully or thrown an exception, leaving the =
program state exactly as it was before the operation started.</li><li style=
=3D"margin:0em 0em 0em 1.25em;padding:0em;text-indent:0em">The=C2=A0<i styl=
e=3D"margin:0px;padding:0px">no-throw</i>=C2=A0guarantee: that the operatio=
n will not throw an exception.</li></ul><div><font color=3D"#000000" face=
=3D"sans-serif">In general, I don't see how that meets anything except =
the basic guarantee (well, not even that, if you have an insane assignment =
operator for your type).</font></div></div></div>-- <br><div>=C2=A0Nevin &q=
uot;:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.c=
om" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 <a href=3D"tel:%=
28847%29%20691-1404" value=3D"+18476911404" target=3D"_blank">(847) 691-140=
4</a></div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a114363acfae9960520f87294--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Wed, 30 Sep 2015 10:21:22 -0500
Raw View
--001a11415d1c01d5eb0520f87ec6
Content-Type: text/plain; charset=UTF-8
On 30 September 2015 at 10:03, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> Well, you've made the case that #4 is at least reasonable. After all, one
> of your prior claims was that most people don't bother to use the variant
> after assignment failures. Thus, they don't really care what state it is
> in; they just let the object die.
>
> If that's true, that's a good argument for not even bothering with the
> basic guarantee.
>
Given the definitions given at <
http://www.boost.org/community/exception_safety.html>:
- The *basic* guarantee: that the invariants of the component are
preserved, and no resources are leaked.
- The *strong* guarantee: that the operation has either completed
successfully or thrown an exception, leaving the program state exactly as
it was before the operation started.
- The *no-throw* guarantee: that the operation will not throw an
exception.
-
- If you aren't providing at least the basic guarantee, you cannot even
reliably destroy the object.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11415d1c01d5eb0520f87ec6
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 30 September 2015 at 10:03, Nicol Bolas <span dir=3D"lt=
r"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@g=
mail.com</a>></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"><br>Well, you've made the case that #4 is=
at least reasonable. After all, one of your prior claims was that most peo=
ple don't bother to use the variant after assignment failures. Thus, th=
ey don't really care what state it is in; they just let the object die.=
<br><div><br>If that's true, that's a good argument for not even bo=
thering with the basic guarantee.<br></div></blockquote><div><br></div><div=
><div>Given the definitions given at <<a href=3D"http://www.boost.org/co=
mmunity/exception_safety.html">http://www.boost.org/community/exception_saf=
ety.html</a>>:</div><div><br></div><div><ul style=3D"margin:0em 0em 1.5e=
m;padding:0em;list-style:circle"><li style=3D"color:rgb(0,0,0);font-family:=
sans-serif;font-size:13px;margin:0em 0em 0em 1.25em;padding:0em;text-indent=
:0em">The=C2=A0<i style=3D"margin:0px;padding:0px">basic</i>=C2=A0guarantee=
: that the invariants of the component are preserved, and no resources are =
leaked.</li><li style=3D"color:rgb(0,0,0);font-family:sans-serif;font-size:=
13px;margin:0em 0em 0em 1.25em;padding:0em;text-indent:0em">The=C2=A0<i sty=
le=3D"margin:0px;padding:0px">strong</i>=C2=A0guarantee: that the operation=
has either completed successfully or thrown an exception, leaving the prog=
ram state exactly as it was before the operation started.</li><li style=3D"=
color:rgb(0,0,0);font-family:sans-serif;font-size:13px;margin:0em 0em 0em 1=
..25em;padding:0em;text-indent:0em">The=C2=A0<i style=3D"margin:0px;padding:=
0px">no-throw</i>=C2=A0guarantee: that the operation will not throw an exce=
ption.</li><li style=3D"color:rgb(0,0,0);font-family:sans-serif;font-size:1=
3px"><span style=3D"font-family:arial,sans-serif;font-size:small;color:rgb(=
34,34,34)"><br></span></li><li><font color=3D"#000000" face=3D"sans-serif">=
If you aren't providing at least the basic guarantee, you cannot even r=
eliably destroy the object.</font></li></ul></div></div></div>-- <br><div c=
lass=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=C2=A0 <mailto=
:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@evilover=
lord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11415d1c01d5eb0520f87ec6--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 Sep 2015 08:26:04 -0700 (PDT)
Raw View
------=_Part_7021_1743543752.1443626764918
Content-Type: multipart/alternative;
boundary="----=_Part_7022_2030564119.1443626764918"
------=_Part_7022_2030564119.1443626764918
Content-Type: text/plain; charset=UTF-8
Here's an idea that should be rather non-controvertial.
Currently, N4542 variants allow emplacement construction and assignment.
However, the assignment only works via construction calls. So if you have
this type:
struct agg
{
int foo;
std::string bar;
};
variant<agg, ...> x(emplaced_type<agg>, 5, "string");
That won't work. `agg` has no 2 element constructor to call. And we don't
want the emplacement constructor to use {} initialization, because that
opens up dozens of cans of worms.
This remains a problem in the standard with allocator::construct (I think
there's an issue on it, but searching through that webpage is terrible).
However, since we have to use a tag to identify the constructor anyway, we
can therefore also allow for different forms of initialization:
variant<agg, ...> x(uniform_type<agg>, 5, "string");
This will use the expression `{std::forward<Args>(args)...}` to initialize
it rather than the constructor syntax.
Obviously, there should be a similar syntax for indices.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7022_2030564119.1443626764918
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Here's an idea that should be rather non-controvertial=
..<br><br>Currently, N4542 variants allow emplacement construction and assig=
nment. However, the assignment only works via construction calls. So if you=
have this type:<br><br><div class=3D"prettyprint" style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> agg<br></span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">in=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 std</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> bar</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br><br>variant</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">agg</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...></s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> x</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">emplaced_type</span><span st=
yle=3D"color: #080;" class=3D"styled-by-prettify"><agg></span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #06=
6;" class=3D"styled-by-prettify">5</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: #080;" class=3D"styled-by-pret=
tify">"string"</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">);</span></div></code></div><br>That won't work. `agg` ha=
s no 2 element constructor to call. And we don't want the emplacement c=
onstructor to use {} initialization, because that opens up dozens of cans o=
f worms.<br><br>This remains a problem in the standard with allocator::cons=
truct (I think there's an issue on it, but searching through that webpa=
ge is terrible). However, since we have to use a tag to identify the constr=
uctor anyway, we can therefore also allow for different forms of initializa=
tion:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250,=
250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-w=
idth: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">variant</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
<</span><span style=3D"color: #000;" class=3D"styled-by-prettify">agg</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">...></span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">uniform_type</span><span style=3D"color: #080;" cla=
ss=3D"styled-by-prettify"><agg></span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-p=
rettify">5</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #080;" class=3D"styled-by-prettify">"string"=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><=
/div></code></div><br>This will use the expression=C2=A0 `{std::forward<=
Args>(args)...}` to initialize it rather than the constructor syntax.<br=
><br>Obviously, there should be a similar syntax for indices.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_7022_2030564119.1443626764918--
------=_Part_7021_1743543752.1443626764918--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 30 Sep 2015 12:47:17 -0300
Raw View
On 9/30/2015 12:26 PM, Nicol Bolas wrote:
> Here's an idea that should be rather non-controvertial.
>
> Currently, N4542 variants allow emplacement construction and assignment.
> However, the assignment only works via construction calls. So if you
> have this type:
>
> |
> structagg
> {
> intfoo;
> std::stringbar;
> };
>
> variant<agg,...>x(emplaced_type<agg>,5,"string");
> |
>
> That won't work. `agg` has no 2 element constructor to call. And we
> don't want the emplacement constructor to use {} initialization, because
> that opens up dozens of cans of worms.
>
> This remains a problem in the standard with allocator::construct (I
> think there's an issue on it, but searching through that webpage is
> terrible). However, since we have to use a tag to identify the
> constructor anyway, we can therefore also allow for different forms of
> initialization:
>
> |
> variant<agg,...>x(uniform_type<agg>,5,"string");
> |
>
> This will use the expression `{std::forward<Args>(args)...}` to
> initialize it rather than the constructor syntax.
>
> Obviously, there should be a similar syntax for indices.
This is N4462 "Towards more perfect forwarding", and is orthogonal to=20
`variant`.
I liked the idea so much that I implemented it (on a branch:=20
https://github.com/eggs-cpp/variant/tree/N4462). I found the duplicated=20
constructor implementation cost manageable, but then I could not=20
complete it as I was lacking an `is_more_perfect_constructible` trait=20
for SFINAE, an `is_nothrow_more_perfect_constructible` trait for=20
`noexcept`, and new power words to describe these on the documentation.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 30 Sep 2015 13:30:53 -0400
Raw View
--089e0141a718e4ba030520fa4adf
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 30, 2015 at 11:18 AM, Nevin Liber <nevin@eviloverlord.com>
wrote:
> On 30 September 2015 at 10:02, Tony V E <tvaneerd@gmail.com> wrote:
>
>> That should be the same as (if I got the syntax right in an email)
>>
>> get<X&>(variant<X,Y>(x1)) = x2
>>
>> ie any time you are not switching types, variant should get out of the
>> way and let X do whatever it does.
>> Variant's job is managing the type switch (and access to the current
>> type+value). When there is no type-switch, variant shouldn't be involved.
>>
>> (That's why, for me, from variant's perspective Wiliams variant does
>> offer the strong guarantee - the variant portion (the discriminator) is
>> unchanged)
>>
>
> It's great that you have your own personal definitions for things, but if
> you take the definitions given at <
> http://www.boost.org/community/exception_safety.html>:
>
>
> - The *basic* guarantee: that the invariants of the component are
> preserved, and no resources are leaked.
> - The *strong* guarantee: that the operation has either completed
> successfully or thrown an exception, leaving the program state exactly as
> it was before the operation started.
>
>
When variant<X,Y>(x1) = x2 throws, variant's operation completed
successfully, while X's operation did not. I see them as 2 separate
operations.
But yes, I understand that might be a bit unconventional.
>
> - The *no-throw* guarantee: that the operation will not throw an
> exception.
>
> In general, I don't see how that meets anything except the basic guarantee
> (well, not even that, if you have an insane assignment operator for your
> type).
> --
> Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0141a718e4ba030520fa4adf
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Sep 30, 2015 at 11:18 AM, Nevin Liber <span dir=3D"ltr"><<a =
href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord=
..com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><span class=3D"">On 30 September 2015 at 10:02, Tony V E <span dir=3D"lt=
r"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gma=
il.com</a>></span> wrote:<br></span><div class=3D"gmail_extra"><div clas=
s=3D"gmail_quote"><span class=3D""><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr">That =
should be the same as (if I got the syntax right in an email)<br><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div><br></div><div>=C2=A0 =C2=
=A0 get<X&>(variant<X,Y>(x1)) =3D x2 <br></div><div><br></d=
iv><div>ie any time you are not switching types, variant should get out of =
the way and let X do whatever it does.<br></div><div>Variant's job is m=
anaging the type switch (and access to the current type+value).=C2=A0 When =
there is no type-switch, variant shouldn't be involved.<br><br></div><d=
iv>(That's why, for me, from variant's perspective Wiliams variant =
does offer the strong guarantee - the variant portion (the discriminator) i=
s unchanged)</div></div></div></div></blockquote><div><br></div></span><div=
>It's great that you have your own personal definitions for things, but=
if you take the definitions given at <<a href=3D"http://www.boost.org/c=
ommunity/exception_safety.html" target=3D"_blank">http://www.boost.org/comm=
unity/exception_safety.html</a>>:</div><div><br></div><div><ul style=3D"=
margin:0em 0em 1.5em;padding:0em;font-size:13px;list-style:circle;color:rgb=
(0,0,0);font-family:sans-serif"><li style=3D"margin:0em 0em 0em 1.25em;padd=
ing:0em;text-indent:0em">The=C2=A0<i style=3D"margin:0px;padding:0px">basic=
</i>=C2=A0guarantee: that the invariants of the component are preserved, an=
d no resources are leaked.</li><li style=3D"margin:0em 0em 0em 1.25em;paddi=
ng:0em;text-indent:0em">The=C2=A0<i style=3D"margin:0px;padding:0px">strong=
</i>=C2=A0guarantee: that the operation has either completed successfully o=
r thrown an exception, leaving the program state exactly as it was before t=
he operation started.</li></ul></div></div></div></div></blockquote><div><b=
r></div><div>When variant<X,Y>(x1) =3D x2 throws, variant's opera=
tion completed successfully, while X's operation did not.=C2=A0 I see t=
hem as 2 separate operations.<br></div><div>But yes, I understand that migh=
t be a bit unconventional.<br></div><div><br>=C2=A0<br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"=
gmail_quote"><div><ul style=3D"margin:0em 0em 1.5em;padding:0em;font-size:1=
3px;list-style:circle;color:rgb(0,0,0);font-family:sans-serif"><li style=3D=
"margin:0em 0em 0em 1.25em;padding:0em;text-indent:0em">The=C2=A0<i style=
=3D"margin:0px;padding:0px">no-throw</i>=C2=A0guarantee: that the operation=
will not throw an exception.</li></ul><div><font face=3D"sans-serif" color=
=3D"#000000">In general, I don't see how that meets anything except the=
basic guarantee (well, not even that, if you have an insane assignment ope=
rator for your type).</font></div></div></div><span class=3D"">-- <br><div>=
=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@=
eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 <a=
href=3D"tel:%28847%29%20691-1404" value=3D"+18476911404" target=3D"_blank"=
>(847) 691-1404</a></div>
</span></div></div>
<p></p>
-- <br><div class=3D"HOEnZb"><div class=3D"h5">
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0141a718e4ba030520fa4adf--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 30 Sep 2015 12:13:01 -0700
Raw View
--001a1134beb227a5100520fbb84b
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> Well, you've made the case that #4 is at least reasonable.
>
I did nothing of the sort. If you write a function and you specify that the
function can throw and yet you don't even offer the basic guarantee, then
you have a bug in your design.
On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> After all, one of your prior claims was that most people don't bother to
> use the variant after assignment failures.
>
Again, I made no such claim and I never would make such a claim. Don't put
words in my mouth. What I described are some of the ways that people handle
exceptions when only the basic guarantee is met for a given operation. I
would hope that this wouldn't have had to be explained given the context of
our discussion, but apparently it really is necessary. Whether you use my
suggestion (that offers the basic guarantee) or the current design that has
an invalid state (which also offers the basic guarantee), then the reality
is that you are dealing with the basic exception guarantee with respect to
assignment failure. Yes, in either of these cases, recovery by going back
to the initial state is more difficult, and I wouldn't argue otherwise, but
recovery doesn't always involve going back to the initial state. In
practice in this specific kind of case, where something as fundamental as a
move operation is failing, if you just go back to the initial state
immediately before the last move, what do you then do? Often you'd be
propagating further because you can't even move (this obviously can't be
proven as it is dependent on the case, but I think it's a pretty reasonable
assessment, unless you have some gripe with it). If you *really* want to go
back to the initial state strictly in all cases, then you need to do
something like double buffering, although notably that doesn't necessarily
have to be something internal to your variant, and it also isn't necessary
for having a well-formed application. Not everybody needs that
functionality and yet it impacts people who don't need it. Entirely
separately, this is my personal reasoning for also not wanting the invalid
state (not everyone needs it and you realistically can instead opt-in for
it at a higher level, but by always having it you impact everyone's
contracts and produces a type with a more complicated interface).
On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Thus, they don't really care what state it is in; they just let the object
> die.
They only don't care what state it is in immediately after the exception.
They can put it into some desired state or they can let the error
propagate. This is simply what the basic guarantee is. This is nothing
special to variant. If you think this is a crazy notion, then you have a
fundamental issue with the basic exception guarantee. And again, this is
true even if you have an invalid state (I'm getting lost with who advocates
what now, so forgive me if you also don't want the invalid state)
On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> If that's true, that's a good argument for not even bothering with the
> basic guarantee.
>
> Granted, that's a terrible idea, but it's a terrible idea because I don't
> buy your argument that most people don't care.
>
We're not talking about "not even bothering with the basic guarantee,"
we're talking specifically about what the basic guarantee is. If you offer
less than the basic guarantee then you don't even get *that* and there is
not really a reliable way to recover from error.
On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> That's one way to see it. Another way to see it is that it satisfies *at
> least* the guarantee that the objects themselves provide. If your
> throwing-move types provide a basic guarantee, then variant will not fix
> that for you. If your throwing-move types provide the strong guarantee,
> then variant will ensure that a variant containing them will *also*
> provide that guarantee.
>
Okay, I accept that assessment and I sold it a little short, but that
leaves you with the case that when one of your operations does *not* obey
the strong guarantee, you are still paying for double buffering anyway,
even though your overall guarantee is basic regardless. All it's really
doing in that case is bloating your type and making access less efficient.
This is how the conversation regarding traits/noexcept describing
strong/basic guarantee arose.
On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> I have moral objections with a variant interfering with the behavior of
> its typelist.
>
You have to understand that with a sum-like type, the correspondence
between what is efficiently implementable does not necessarily directly
correspond to the same operations between field types and overall type in
the way that it usually does for a type like std::vector. Specifically,
things like the assignment operator in a sum-like type depend more on the
move-*constructor* of field types than the move-assignment operator of the
field types. This is why the move-constructor being not noexcept is what's
actually impacting our assignment operation here. It's unintuitive perhaps,
yes, but it's ultimately true and not really something that can be denied.
I think you acknowledge that. This is why I personally suggest constraining
the assignment operation based on the move-constructor being noexcept,
since if we don't, we're effectively requiring changing the implementation
of the overall type in such a circumstance to the point that's it's not
even really the same datastructure internally. If users really want that,
I'd argue they should just use a different type, or meet the constraints
(which can be done non-intrusively to existing field types), or manually do
double-buffering at a higher level.
The way I interpret things is this. My personal stance:
* constrain operations based on what the fundamental the datastructure and
its intrinsic functions require
Alternative:
* constrain operations based on what people might more intuitively expect,
regardless of how it affects the implementation
I view the alternative as a mistake. If the constraints seem unintuitive,
then that's unfortunate, but I don't think we should act like they don't
exist. Doing so leads us to a solution where we either weaken the
invariants of the type (adding invalid states) or a solution where the
internal workings of the type are fundamentally changed for certain
template arguments (double buffering).
There are functional equivalents that don't require us making either of
these sacrifices.
On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> Without an actual invalid state, there is no way to offer any kind of
>>> exception guarantee. Not for any typelist. So long as those types do not
>>> have a noexcept default constructor, there is no way to put the variant in
>>> a valid-but-unspecified state.
>>>
>>
>> That's because you're defining your requirements separate from what the
>> datastructure would imply. Instead we should l*ift* the requirements
>> from the implementation of the datastructure and its intrinsic
>> functions. I've always been stating "with a fallback" or via the "optional"
>> solution. The suggestion is that if neither of these cases are satisfied,
>> you've not met the concept requirements of the assignment operation.
>> Instead of weakening the type's invariants and also complicating the
>> contracts of all functions involved, a user could simply use one of the
>> suggested solutions.
>>
>
> Solutions that *do not exist*. Remember: no version of `optional` works
> the way you need it to in order to be a valid solution (ie: switch to
> nullopt on exception failure and synthesize operations that T does not
> allow). And if the typelist doesn't contain a "fallback" state, then you
> have a gimped type *with no recourse* to fix it.
>
It's not a "gimped" type, you're just not meeting the requirements of that
operation. You choose to not like those requirements because they are
unintuitive to you. If having your intuitive requirements implies
completely changing the inner workings of the type and affects things as
trivial as how the internal field types are accessed, all in the event that
a template argument has a move constructor that can throw, simply to
account for the assignment operation (which notably may or may not be used
and may or may not require the strong guarantee), and doing so makes the
type less efficient regarding space and regarding access, then I think
that's irrational. Just express the requirements of that function, no
matter how intuitive or unintuitive they may seem.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134beb227a5100520fbb84b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> 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-st=
yle:solid;padding-left:1ex"><div>Well, you've made the case that #4 is =
at least reasonable.</div></blockquote><div><br></div><div>I did nothing of=
the sort. If you write a function and you specify that the function can th=
row and yet you don't even offer the basic guarantee, then you have a b=
ug in your design.</div><div><br></div><div>On Wed, Sep 30, 2015 at 8:03 AM=
, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.=
com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:=C2=A0=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div> After all, one of your prior claims was that m=
ost people don't bother to use the variant after assignment failures.<b=
r></div></blockquote><div><br></div><div>Again, I made no such claim and I =
never would make such a claim. Don't put words in my mouth. What I desc=
ribed are some of the ways that people handle exceptions when only the basi=
c guarantee is met for a given operation. I would hope that this wouldn'=
;t have had to be explained given the context of our discussion, but appare=
ntly it really is necessary. Whether you use my suggestion (that offers the=
basic guarantee) or the current design that has an invalid state (which al=
so offers the basic guarantee), then the reality is that you are dealing wi=
th the basic exception guarantee with respect to assignment failure. Yes, i=
n either of these cases, recovery by going back to the initial state is mor=
e difficult, and I wouldn't argue otherwise, but recovery doesn't a=
lways involve going back to the initial state. In practice in this specific=
kind of case, where something as fundamental as a move operation is failin=
g, if you just go back to the initial state immediately before the last mov=
e, what do you then do? Often you'd be propagating further because you =
can't even move (this obviously can't be proven as it is dependent =
on the case, but I think it's a pretty reasonable assessment, unless yo=
u have some gripe with it). If you <i>really</i>=C2=A0want to go back to th=
e initial state strictly in all cases, then you need to do something like d=
ouble buffering, although notably that doesn't necessarily have to be s=
omething internal to your variant, and it also isn't necessary for havi=
ng a well-formed application. Not everybody needs that functionality and ye=
t it impacts people who don't need it. Entirely separately, this is my =
personal reasoning for also not wanting the invalid state (not everyone nee=
ds it and you realistically can instead opt-in for it at a higher level, bu=
t by always having it you impact everyone's contracts and produces a ty=
pe with a more complicated interface).</div><div><br></div><div><div>On Wed=
, Sep 30, 2015 at 8:03 AM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=
=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&g=
t;</span>=C2=A0wrote:=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,2=
04,204);border-left-style:solid;padding-left:1ex">Thus, they don't real=
ly care what state it is in; they just let the object die.</blockquote></di=
v><div>=C2=A0</div><div>They only don't care what state it is in immedi=
ately after the exception. They can put it into some desired state or they =
can let the error propagate. This is simply what the basic guarantee is. Th=
is is nothing special to variant. If you think this is a crazy notion, then=
you have a fundamental issue with the basic exception guarantee. And again=
, this is true even if you have an invalid state (I'm getting lost with=
who advocates what now, so forgive me if you also don't want the inval=
id state)</div><div><br></div><div>On Wed, Sep 30, 2015 at 8:03 AM, Nicol B=
olas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" targ=
et=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padd=
ing-left:1ex"><div>If that's true, that's a good argument for not e=
ven bothering with the basic guarantee.<br><br>Granted, that's a terrib=
le idea, but it's a terrible idea because I don't buy your argument=
that most people don't care.<br></div></blockquote><div><br></div><div=
>We're not talking about "not even bothering with the basic guaran=
tee," we're talking specifically about what the basic guarantee is=
.. If you offer less than the basic guarantee then you don't even get <i=
>that</i> and there is not really a reliable way to recover from error.=C2=
=A0</div><div>=C2=A0</div><div>On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas=
=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=
=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:</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"><div>That's one way to see it. Another way to see it is that it s=
atisfies <i>at least</i> the guarantee that the objects themselves provide.=
If your throwing-move types provide a basic guarantee, then variant will n=
ot fix that for you. If your throwing-move types provide the strong guarant=
ee, then variant will ensure that a variant containing them will <i>also</i=
> provide that guarantee.<br></div></blockquote><div><br></div><div>Okay, I=
accept that assessment and I sold it a little short, but that leaves you w=
ith the case that when one of your operations does <i>not</i>=C2=A0obey the=
strong guarantee, you are still paying for double buffering anyway, even t=
hough your overall guarantee is basic regardless. All it's really doing=
in that case is bloating your type and making access less efficient. This =
is how the conversation regarding traits/noexcept describing strong/basic g=
uarantee arose.</div><div><br></div><div>On Wed, Sep 30, 2015 at 8:03 AM, N=
icol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com=
" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padd=
ing-left:1ex"><div>I have moral objections with a variant interfering with =
the behavior of its typelist.<br></div></blockquote><div><br></div><div>You=
have to understand that with a sum-like type, the correspondence between w=
hat is efficiently implementable does not necessarily directly correspond t=
o the same operations between field types and overall type in the way that =
it usually does for a type like std::vector. Specifically, things like the =
assignment operator in a sum-like type depend more on the move-<i>construct=
or</i> of field types than the move-assignment operator of the field types.=
This is why the move-constructor being not noexcept is what's actually=
impacting our assignment operation here. It's unintuitive perhaps, yes=
, but it's ultimately true and not really something that can be denied.=
I think you acknowledge that. This is why I personally suggest constrainin=
g the assignment operation based on the move-constructor being noexcept, si=
nce if we don't, we're effectively requiring changing the implement=
ation of the overall type in such a circumstance to the point that's it=
's not even really the same datastructure internally. If users really w=
ant that, I'd argue they should just use a different type, or meet the =
constraints (which can be done non-intrusively to existing field types), or=
manually do double-buffering at a higher level.</div><div><br></div><div>T=
he way I interpret things is this. My personal stance:</div><div>* constrai=
n operations based on what the fundamental the datastructure and its intrin=
sic functions require</div><div><br></div><div>Alternative:</div><div>* con=
strain operations based on what people might more intuitively expect, regar=
dless of how it affects the implementation</div><div><br></div><div>I view =
the alternative as a mistake. If the constraints seem unintuitive, then tha=
t's unfortunate, but I don't think we should act like they don'=
t exist. Doing so leads us to a solution where we either weaken the invaria=
nts of the type (adding invalid states) or a solution where the internal wo=
rkings of the type are fundamentally changed for certain template arguments=
(double buffering).</div><div><br></div><div>There are functional equivale=
nts that don't require us making either of these sacrifices.</div><div>=
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><span class=3D""><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote"><div>On Tue, Sep 29, 2015 at 7:00 PM, Ni=
col Bolas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com<=
/a>></span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex"><div>Without
an actual invalid state, there is no way to offer any kind of exception
guarantee. Not for any typelist. So long as those types do not have a noex=
cept default constructor, there is no way to put the variant in a valid-but=
-unspecified state.</div></blockquote><div><br></div><div>That's becaus=
e you're defining your requirements separate from what the datastructur=
e would imply. Instead we should l<i>ift</i>=C2=A0the requirements from the=
implementation of the datastructure and its intrinsic functions.=C2=A0I=
9;ve always been stating "with a fallback" or via the "optio=
nal" solution. The suggestion is that if neither of these cases are sa=
tisfied, you've not met the concept requirements of the assignment oper=
ation. Instead of weakening the type's invariants and also complicating=
the contracts of all functions involved, a user could simply use one of th=
e suggested solutions.</div></div></div></div></blockquote></span><div><br>=
Solutions that <i>do not exist</i>. Remember: no version of `optional` work=
s the way you need it to in order to be a valid solution (ie: switch to nul=
lopt on exception failure and synthesize operations that T does not allow).=
And if the typelist doesn't contain a "fallback" state, then=
you have a gimped type <i>with no recourse</i> to fix it.</div></blockquot=
e><div>=C2=A0</div><div>It's not a "gimped" type, you're =
just not meeting the requirements of that operation. You choose to not like=
those requirements because they are unintuitive to you. If having your int=
uitive requirements implies completely changing the inner workings of the t=
ype and affects things as trivial as how the internal field types are acces=
sed, all in the event that a template argument has a move constructor that =
can throw, simply to account for the assignment operation (which notably ma=
y or may not be used and may or may not require the strong guarantee), and =
doing so makes the type less efficient regarding space and regarding access=
, then I think that's irrational. Just express the requirements of that=
function, no matter how intuitive or unintuitive they may seem.</div></div=
></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134beb227a5100520fbb84b--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 Sep 2015 12:14:15 -0700 (PDT)
Raw View
------=_Part_901_2035428658.1443640455566
Content-Type: multipart/alternative;
boundary="----=_Part_902_1206694240.1443640455567"
------=_Part_902_1206694240.1443640455567
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 30, 2015 at 1:30:55 PM UTC-4, Tony V E wrote:
>
> On Wed, Sep 30, 2015 at 11:18 AM, Nevin Liber <ne...@eviloverlord.com
> <javascript:>> wrote:
>
> On 30 September 2015 at 10:02, Tony V E <tvan...@gmail.com <javascript:>>
> wrote:
>
> That should be the same as (if I got the syntax right in an email)
>
> get<X&>(variant<X,Y>(x1)) = x2
>
> ie any time you are not switching types, variant should get out of the way
> and let X do whatever it does.
> Variant's job is managing the type switch (and access to the current
> type+value). When there is no type-switch, variant shouldn't be involved.
>
> (That's why, for me, from variant's perspective Wiliams variant does offer
> the strong guarantee - the variant portion (the discriminator) is unchanged)
>
>
> It's great that you have your own personal definitions for things, but if
> you take the definitions given at <
> http://www.boost.org/community/exception_safety.html>:
>
>
> - The *basic* guarantee: that the invariants of the component are
> preserved, and no resources are leaked.
> - The *strong* guarantee: that the operation has either completed
> successfully or thrown an exception, leaving the program state exactly as
> it was before the operation started.
>
>
> When variant<X,Y>(x1) = x2 throws, variant's operation completed
> successfully, while X's operation did not. I see them as 2 separate
> operations.
> But yes, I understand that might be a bit unconventional.
>
It's not unconventional at all. Since people love to compare variant to
optional, let's look at that type's behavior.
std::optional<T> provides only the exception guarantee that T does. If T
provides no guarantee, then `opt = T()` provides no guarantees if `opt` is
engaged.
Why should `variant` be any different? Why should `variant` provide
guarantees that its types do not? Alternatively, why should `variant`
*interfere* with the guarantees of its types?
This also makes sense conceptually.
The basic concept of a `variant` is that it is an intersection of the
behavior of its types. If you take a `variant` as a parameter, then your
function is saying that it will adapt to fit any of those object types,
that the functionality it exposes is valid for any of them.
This is enshrined in the behavior of `variant`'s special member functions.
The `noexcept` specification for move construction (from another `variant`)
is noexcept only if *all* of its component types are noexcept move
constructible. It provides the intersection of the behavior of all of its
types. If one of its types is not even move constructible, then a variant
containing that type will not be move constructible, no matter what other
types in that variant say.
Everyone seems to agree that this should be the case. Pretty much every
modern variant implementation, whether never-empty or not, follows this
behavior... until it comes time to talk about exception safety. Suddenly,
people start wanting to break this concept.
The *only reason* given for breaking this concept is implementation
burden/overhead. It's not conceptual, it's purely the pain of properly
intersecting the various exception safety guarantees.
And yet, `variant` still does for one case: noexcept. If your types all
offer the nothrow guarantee for an operation, then `variant` will offer
that guarantee too.
The others, basic and strong, are different for one important reason: the
compiler can't tell the difference. There's no way to ask if all of the
types, for all operations, offer the basic guarantee. Now, `optional` works
because it only has one state; it doesn't have to worry about converting
from state to state in-place. `variant` does.
Which means that, to implement perfect exception guarantee forwarding,
`variant` implementations have to provide the strong guarantee during all
operations that convert the type.
`variant` does not have an exception guarantee. Just as `variant` does not
have a copy or move constructor. Only `variant<T, U>` has these properties.
And by design and by concept, `variant<T, U> should be copy/moveable if T
and U both are. And `variant` should provide the exception guarantees that
both T and U provide.
Nothing less. `variant` should no more manufacture exception guarantees out
of whole cloth than it should manufacture a move assignment operator from
move constructible-only types. That's the problem with *enforcing* the
basic guarantee on `variant`. You're not properly exposing the user to the
behavior of the component types.
I believe in the intersection-of-behavior view of `variant`. That's another
reason why I like Williams.Variant; it offers exception guarantee
forwarding. If all your types are strong, you get strong. If you add one
basic guarantee type in there, you can only rely on getting the basic
guarantee (even though *technically*, most of the time it'll be strong).
If I put only nothrow exception guarantee types in a `variant`, I expect
that variant to also provide that guarantee. And virtually every modern
implementation will.
Why should I *not* get the same behavior with the strong guarantee?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_902_1206694240.1443640455567
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, September 30, 2015 at 1:30:55 PM UTC-4, Tony V E wrote:<block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div>On Wed, S=
ep 30, 2015 at 11:18 AM, Nevin Liber <span dir=3D"ltr"><<a href=3D"javas=
cript:" target=3D"_blank" gdf-obfuscated-mailto=3D"A86gH4pWCgAJ" rel=3D"nof=
ollow" onmousedown=3D"this.href=3D'javascript:';return true;" oncli=
ck=3D"this.href=3D'javascript:';return true;">ne...@eviloverlord.co=
m</a>></span> wrote:<br><blockquote style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span>On 30 September =
2015 at 10:02, Tony V E <span dir=3D"ltr"><<a href=3D"javascript:" targe=
t=3D"_blank" gdf-obfuscated-mailto=3D"A86gH4pWCgAJ" rel=3D"nofollow" onmous=
edown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hr=
ef=3D'javascript:';return true;">tvan...@gmail.com</a>></span> w=
rote:<br></span><div><div><span><blockquote style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr">That should be the same as (if =
I got the syntax right in an email)<br><div><div><div><br></div><div>=C2=A0=
=C2=A0 get<X&>(variant<X,Y>(x1)) =3D x2 <br></div><div><br=
></div><div>ie any time you are not switching types, variant should get out=
of the way and let X do whatever it does.<br></div><div>Variant's job =
is managing the type switch (and access to the current type+value).=C2=A0 W=
hen there is no type-switch, variant shouldn't be involved.<br><br></di=
v><div>(That's why, for me, from variant's perspective Wiliams vari=
ant does offer the strong guarantee - the variant portion (the discriminato=
r) is unchanged)</div></div></div></div></blockquote><div><br></div></span>=
<div>It's great that you have your own personal definitions for things,=
but if you take the definitions given at <<a href=3D"http://www.boost.o=
rg/community/exception_safety.html" target=3D"_blank" rel=3D"nofollow" onmo=
usedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.=
boost.org%2Fcommunity%2Fexception_safety.html\46sa\75D\46sntz\0751\46usg\75=
AFQjCNHt8vUyvL-TZ4a4KW2RpCP9QEos3Q';return true;" onclick=3D"this.href=
=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.boost.org%2Fcommunit=
y%2Fexception_safety.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHt8vUyvL-TZ4a4=
KW2RpCP9QEos3Q';return true;">http://www.boost.org/<wbr>community/excep=
tion_safety.<wbr>html</a>>:</div><div><br></div><div><ul style=3D"margin=
:0em 0em 1.5em;padding:0em;font-size:13px;list-style:circle;color:rgb(0,0,0=
);font-family:sans-serif"><li style=3D"margin:0em 0em 0em 1.25em;padding:0e=
m;text-indent:0em">The=C2=A0<i style=3D"margin:0px;padding:0px">basic</i>=
=C2=A0guarantee: that the invariants of the component are preserved, and no=
resources are leaked.</li><li style=3D"margin:0em 0em 0em 1.25em;padding:0=
em;text-indent:0em">The=C2=A0<i style=3D"margin:0px;padding:0px">strong</i>=
=C2=A0guarantee: that the operation has either completed successfully or th=
rown an exception, leaving the program state exactly as it was before the o=
peration started.</li></ul></div></div></div></div></blockquote><div><br></=
div><div>When variant<X,Y>(x1) =3D x2 throws, variant's operation=
completed successfully, while X's operation did not.=C2=A0 I see them =
as 2 separate operations.<br></div><div>But yes, I understand that might be=
a bit unconventional.<br></div></div></div></div></blockquote><div><br>It&=
#39;s not unconventional at all. Since people love to compare variant to op=
tional, let's look at that type's behavior.<br><br>std::optional<=
;T> provides only the exception guarantee that T does. If T provides no =
guarantee, then `opt =3D T()` provides no guarantees if `opt` is engaged.<b=
r><br>Why should `variant` be any different? Why should `variant` provide g=
uarantees that its types do not?=20
Alternatively, why should `variant` <i>interfere</i> with the guarantees of=
its
types?<br><br>This also makes sense conceptually.<br><br>The basic concept=
of a `variant` is that it is an intersection of the behavior of its types.=
If you take a `variant` as a parameter, then your function is saying that =
it will adapt to fit any of those object types, that the functionality it e=
xposes is valid for any of them.<br><br>This is enshrined in the behavior o=
f `variant`'s special member functions. The `noexcept` specification fo=
r move construction (from another `variant`) is noexcept only if <i>all</i>=
of its component types are noexcept move constructible. It provides the in=
tersection of the behavior of all of its types. If one of its types is not =
even move constructible, then a variant containing that type will not be mo=
ve constructible, no matter what other types in that variant say.<br><br>Ev=
eryone seems to agree that this should be the case. Pretty much every moder=
n variant implementation, whether never-empty or not, follows this behavior=
.... until it comes time to talk about exception safety. Suddenly, people st=
art wanting to break this concept.<br><br>The <i>only reason</i> given for =
breaking this concept is implementation burden/overhead. It's not conce=
ptual, it's purely the pain of properly intersecting the various except=
ion safety guarantees.<br><br>And yet, `variant` still does for one case: n=
oexcept. If your types all offer the nothrow guarantee for an operation, th=
en `variant` will offer that guarantee too.<br><br>The others, basic and st=
rong, are different for one important reason: the compiler can't tell t=
he difference. There's no way to ask if all of the types, for all opera=
tions, offer the basic guarantee. Now, `optional` works because it only has=
one state; it doesn't have to worry about converting from state to sta=
te in-place. `variant` does.<br><br>Which means that, to implement perfect =
exception guarantee forwarding, `variant` implementations have to provide t=
he strong guarantee during all operations that convert the type.<br><br>`va=
riant` does not have an exception guarantee. Just as `variant` does not hav=
e a copy or move constructor. Only `variant<T, U>` has these properti=
es. And by design and by concept, `variant<T, U> should be copy/movea=
ble if T and U both are. And `variant` should provide the exception guarant=
ees that both T and U provide.<br><br>Nothing less. `variant` should no mor=
e manufacture exception guarantees out of whole cloth than it should manufa=
cture a move assignment operator from move constructible-only types. That&#=
39;s the problem with <i>enforcing</i> the basic guarantee on `variant`. Yo=
u're not properly exposing the user to the behavior of the component ty=
pes.<br><br>I believe in the intersection-of-behavior view of `variant`. Th=
at's another reason why I like Williams.Variant; it offers exception gu=
arantee forwarding. If all your types are strong, you get strong. If you ad=
d one basic guarantee type in there, you can only rely on getting the basic=
guarantee (even though <i>technically</i>, most of the time it'll be s=
trong).<br><br>If I put only nothrow exception guarantee types in a `varian=
t`, I expect that variant to also provide that guarantee. And virtually eve=
ry modern implementation will.<br><br>Why should I <i>not</i> get the same =
behavior with the strong guarantee?<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_902_1206694240.1443640455567--
------=_Part_901_2035428658.1443640455566--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 30 Sep 2015 15:37:11 -0400
Raw View
--089e0141a7188f862f0520fc0e6a
Content-Type: text/plain; charset=UTF-8
On Wed, Sep 30, 2015 at 3:14 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Wednesday, September 30, 2015 at 1:30:55 PM UTC-4, Tony V E wrote:
>>
>> On Wed, Sep 30, 2015 at 11:18 AM, Nevin Liber <ne...@eviloverlord.com>
>> wrote:
>>
>> On 30 September 2015 at 10:02, Tony V E <tvan...@gmail.com> wrote:
>>
>> That should be the same as (if I got the syntax right in an email)
>>
>> get<X&>(variant<X,Y>(x1)) = x2
>>
>> ie any time you are not switching types, variant should get out of the
>> way and let X do whatever it does.
>> Variant's job is managing the type switch (and access to the current
>> type+value). When there is no type-switch, variant shouldn't be involved.
>>
>> (That's why, for me, from variant's perspective Wiliams variant does
>> offer the strong guarantee - the variant portion (the discriminator) is
>> unchanged)
>>
>>
>> It's great that you have your own personal definitions for things, but if
>> you take the definitions given at <
>> http://www.boost.org/community/exception_safety.html>:
>>
>>
>> - The *basic* guarantee: that the invariants of the component are
>> preserved, and no resources are leaked.
>> - The *strong* guarantee: that the operation has either completed
>> successfully or thrown an exception, leaving the program state exactly as
>> it was before the operation started.
>>
>>
>> When variant<X,Y>(x1) = x2 throws, variant's operation completed
>> successfully, while X's operation did not. I see them as 2 separate
>> operations.
>> But yes, I understand that might be a bit unconventional.
>>
>
> It's not unconventional at all. Since people love to compare variant to
> optional, let's look at that type's behavior.
>
It is not unconventional to want this "strong-ish" or "as strong as its
parts" behaviour for variant. And your explanation of it is a good one.
What I see as unconventional is my view of whether it should be _labelled_
"strong" when X is only offering basic. In my mind the variant (part) is
still offering the strong guarantee even when X is only offering basic.
Because the variant part is strong. The overall assignment operation is
still basic (weakest link in the chain), but to me variant's part is still
strong. And that comes down to whether you can/should/etc see it as two
operations or one. And that might be unconventional.
Basically, I'm probably better off using your reasons for wanting it than
my own reasons. Otherwise I'll confuse people and/or get into pedantic
discussions.
Tony
> std::optional<T> provides only the exception guarantee that T does. If T
> provides no guarantee, then `opt = T()` provides no guarantees if `opt` is
> engaged.
>
> Why should `variant` be any different? Why should `variant` provide
> guarantees that its types do not? Alternatively, why should `variant`
> *interfere* with the guarantees of its types?
>
> This also makes sense conceptually.
>
> The basic concept of a `variant` is that it is an intersection of the
> behavior of its types. If you take a `variant` as a parameter, then your
> function is saying that it will adapt to fit any of those object types,
> that the functionality it exposes is valid for any of them.
>
> This is enshrined in the behavior of `variant`'s special member functions.
> The `noexcept` specification for move construction (from another `variant`)
> is noexcept only if *all* of its component types are noexcept move
> constructible. It provides the intersection of the behavior of all of its
> types. If one of its types is not even move constructible, then a variant
> containing that type will not be move constructible, no matter what other
> types in that variant say.
>
> Everyone seems to agree that this should be the case. Pretty much every
> modern variant implementation, whether never-empty or not, follows this
> behavior... until it comes time to talk about exception safety. Suddenly,
> people start wanting to break this concept.
>
> The *only reason* given for breaking this concept is implementation
> burden/overhead. It's not conceptual, it's purely the pain of properly
> intersecting the various exception safety guarantees.
>
> And yet, `variant` still does for one case: noexcept. If your types all
> offer the nothrow guarantee for an operation, then `variant` will offer
> that guarantee too.
>
> The others, basic and strong, are different for one important reason: the
> compiler can't tell the difference. There's no way to ask if all of the
> types, for all operations, offer the basic guarantee. Now, `optional` works
> because it only has one state; it doesn't have to worry about converting
> from state to state in-place. `variant` does.
>
> Which means that, to implement perfect exception guarantee forwarding,
> `variant` implementations have to provide the strong guarantee during all
> operations that convert the type.
>
> `variant` does not have an exception guarantee. Just as `variant` does not
> have a copy or move constructor. Only `variant<T, U>` has these properties.
> And by design and by concept, `variant<T, U> should be copy/moveable if T
> and U both are. And `variant` should provide the exception guarantees that
> both T and U provide.
>
> Nothing less. `variant` should no more manufacture exception guarantees
> out of whole cloth than it should manufacture a move assignment operator
> from move constructible-only types. That's the problem with *enforcing*
> the basic guarantee on `variant`. You're not properly exposing the user to
> the behavior of the component types.
>
> I believe in the intersection-of-behavior view of `variant`. That's
> another reason why I like Williams.Variant; it offers exception guarantee
> forwarding. If all your types are strong, you get strong. If you add one
> basic guarantee type in there, you can only rely on getting the basic
> guarantee (even though *technically*, most of the time it'll be strong).
>
> If I put only nothrow exception guarantee types in a `variant`, I expect
> that variant to also provide that guarantee. And virtually every modern
> implementation will.
>
> Why should I *not* get the same behavior with the strong guarantee?
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0141a7188f862f0520fc0e6a
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Sep 30, 2015 at 3:14 PM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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">On Wednesday, Septemb=
er 30, 2015 at 1:30:55 PM UTC-4, Tony V E wrote:<blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"><div><div>On Wed, Sep 30, 2015 at 11:18 AM, N=
evin Liber <span dir=3D"ltr"><<a rel=3D"nofollow">ne...@eviloverlord.com=
</a>></span> wrote:<span class=3D""><br><blockquote style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span>=
On 30 September 2015 at 10:02, Tony V E <span dir=3D"ltr"><<a rel=3D"nof=
ollow">tvan...@gmail.com</a>></span> wrote:<br></span><div><div><span><b=
lockquote style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div di=
r=3D"ltr">That should be the same as (if I got the syntax right in an email=
)<br><div><div><div><br></div><div>=C2=A0 =C2=A0 get<X&>(variant&=
lt;X,Y>(x1)) =3D x2 <br></div><div><br></div><div>ie any time you are no=
t switching types, variant should get out of the way and let X do whatever =
it does.<br></div><div>Variant's job is managing the type switch (and a=
ccess to the current type+value).=C2=A0 When there is no type-switch, varia=
nt shouldn't be involved.<br><br></div><div>(That's why, for me, fr=
om variant's perspective Wiliams variant does offer the strong guarante=
e - the variant portion (the discriminator) is unchanged)</div></div></div>=
</div></blockquote><div><br></div></span><div>It's great that you have =
your own personal definitions for things, but if you take the definitions g=
iven at <<a href=3D"http://www.boost.org/community/exception_safety.html=
" rel=3D"nofollow" target=3D"_blank">http://www.boost.org/community/excepti=
on_safety.html</a>>:</div><div><br></div><div><ul style=3D"margin:0em 0e=
m 1.5em;padding:0em;font-size:13px;list-style:circle;color:rgb(0,0,0);font-=
family:sans-serif"><li style=3D"margin:0em 0em 0em 1.25em;padding:0em;text-=
indent:0em">The=C2=A0<i style=3D"margin:0px;padding:0px">basic</i>=C2=A0gua=
rantee: that the invariants of the component are preserved, and no resource=
s are leaked.</li><li style=3D"margin:0em 0em 0em 1.25em;padding:0em;text-i=
ndent:0em">The=C2=A0<i style=3D"margin:0px;padding:0px">strong</i>=C2=A0gua=
rantee: that the operation has either completed successfully or thrown an e=
xception, leaving the program state exactly as it was before the operation =
started.</li></ul></div></div></div></div></blockquote><div><br></div><div>=
When variant<X,Y>(x1) =3D x2 throws, variant's operation complete=
d successfully, while X's operation did not.=C2=A0 I see them as 2 sepa=
rate operations.<br></div><div>But yes, I understand that might be a bit un=
conventional.<br></div></span></div></div></div></blockquote><div><br>It=
9;s not unconventional at all. Since people love to compare variant to opti=
onal, let's look at that type's behavior.<br></div></blockquote><di=
v><br></div><div>It is not unconventional to want this "strong-ish&quo=
t; or "as strong as its parts" behaviour for variant.=C2=A0 And y=
our explanation of it is a good one.<br><br></div><div>What I see as unconv=
entional is my view of whether it should be _labelled_ "strong" w=
hen X is only offering basic.=C2=A0 In my mind the variant (part) is still =
offering the strong guarantee even when X is only offering basic.=C2=A0 Bec=
ause the variant part is strong.=C2=A0 The overall assignment operation is =
still basic (weakest link in the chain), but to me variant's part is st=
ill strong.=C2=A0 And that comes down to whether you can/should/etc see it =
as two operations or one.=C2=A0 And that might be unconventional.<br><br></=
div><div>Basically, I'm probably better off using your reasons for want=
ing it than my own reasons.=C2=A0 Otherwise I'll confuse people and/or =
get into pedantic discussions.<br></div><div>Tony<br></div><div><br></div><=
blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div><br>std::optional<T> provides only=
the exception guarantee that T does. If T provides no guarantee, then `opt=
=3D T()` provides no guarantees if `opt` is engaged.<br><br>Why should `va=
riant` be any different? Why should `variant` provide guarantees that its t=
ypes do not?=20
Alternatively, why should `variant` <i>interfere</i> with the guarantees of=
its
types?<br><br>This also makes sense conceptually.<br><br>The basic concept=
of a `variant` is that it is an intersection of the behavior of its types.=
If you take a `variant` as a parameter, then your function is saying that =
it will adapt to fit any of those object types, that the functionality it e=
xposes is valid for any of them.<br><br>This is enshrined in the behavior o=
f `variant`'s special member functions. The `noexcept` specification fo=
r move construction (from another `variant`) is noexcept only if <i>all</i>=
of its component types are noexcept move constructible. It provides the in=
tersection of the behavior of all of its types. If one of its types is not =
even move constructible, then a variant containing that type will not be mo=
ve constructible, no matter what other types in that variant say.<br><br>Ev=
eryone seems to agree that this should be the case. Pretty much every moder=
n variant implementation, whether never-empty or not, follows this behavior=
.... until it comes time to talk about exception safety. Suddenly, people st=
art wanting to break this concept.<br><br>The <i>only reason</i> given for =
breaking this concept is implementation burden/overhead. It's not conce=
ptual, it's purely the pain of properly intersecting the various except=
ion safety guarantees.<br><br>And yet, `variant` still does for one case: n=
oexcept. If your types all offer the nothrow guarantee for an operation, th=
en `variant` will offer that guarantee too.<br><br>The others, basic and st=
rong, are different for one important reason: the compiler can't tell t=
he difference. There's no way to ask if all of the types, for all opera=
tions, offer the basic guarantee. Now, `optional` works because it only has=
one state; it doesn't have to worry about converting from state to sta=
te in-place. `variant` does.<br><br>Which means that, to implement perfect =
exception guarantee forwarding, `variant` implementations have to provide t=
he strong guarantee during all operations that convert the type.<br><br>`va=
riant` does not have an exception guarantee. Just as `variant` does not hav=
e a copy or move constructor. Only `variant<T, U>` has these properti=
es. And by design and by concept, `variant<T, U> should be copy/movea=
ble if T and U both are. And `variant` should provide the exception guarant=
ees that both T and U provide.<br><br>Nothing less. `variant` should no mor=
e manufacture exception guarantees out of whole cloth than it should manufa=
cture a move assignment operator from move constructible-only types. That&#=
39;s the problem with <i>enforcing</i> the basic guarantee on `variant`. Yo=
u're not properly exposing the user to the behavior of the component ty=
pes.<br><br>I believe in the intersection-of-behavior view of `variant`. Th=
at's another reason why I like Williams.Variant; it offers exception gu=
arantee forwarding. If all your types are strong, you get strong. If you ad=
d one basic guarantee type in there, you can only rely on getting the basic=
guarantee (even though <i>technically</i>, most of the time it'll be s=
trong).<br><br>If I put only nothrow exception guarantee types in a `varian=
t`, I expect that variant to also provide that guarantee. And virtually eve=
ry modern implementation will.<br><br>Why should I <i>not</i> get the same =
behavior with the strong guarantee?<br></div><div class=3D"HOEnZb"><div cla=
ss=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0141a7188f862f0520fc0e6a--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 Sep 2015 15:18:59 -0700 (PDT)
Raw View
------=_Part_7762_1176613441.1443651539288
Content-Type: multipart/alternative;
boundary="----=_Part_7763_1103743991.1443651539289"
------=_Part_7763_1103743991.1443651539289
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 30, 2015 at 3:13:07 PM UTC-4, Matt Calabrese wrote:
>
> On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> That's one way to see it. Another way to see it is that it satisfies *at
>> least* the guarantee that the objects themselves provide. If your
>> throwing-move types provide a basic guarantee, then variant will not fix
>> that for you. If your throwing-move types provide the strong guarantee,
>> then variant will ensure that a variant containing them will *also*
>> provide that guarantee.
>>
>
> Okay, I accept that assessment and I sold it a little short, but that
> leaves you with the case that when one of your operations does *not* obey
> the strong guarantee, you are still paying for double buffering anyway,
> even though your overall guarantee is basic regardless.
>
That's true.
Nothing with `variant` in C++ can be perfect; that's the nature of the
game. Every possible implementation disadvantages *someone* in some way.
But a type with overhead that a person can theoretically use is better than
a no-overhead type that they can't.
It should also be noted that exception guarantees are not based on types,
but on operations that throw. Though generally speaking, it's a good idea
for all operations to have the same guarantee on a type, it is possible for
certain operations to be strong and others to be basic. So move assignment
might be strong, while copy assignment is basic.
So its better to be safe than to over-promise and under-deliver.
All it's really doing in that case is bloating your type and making access
> less efficient.
>
How much bloat? How much less efficient? Not just for a specific type; I
want to know how it will actually affect things in the wild.
There have to be codebases out there that uses some templated `variant`
type. It'd be interesting to look at all the variant instantiations they
use and see just how many would gain space due to the issue. It'd also be
interesting to see how many would be broken by your suggestion.
This is how the conversation regarding traits/noexcept describing
> strong/basic guarantee arose.
>
> On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> I have moral objections with a variant interfering with the behavior of
>> its typelist.
>>
>
> You have to understand that with a sum-like type, the correspondence
> between what is efficiently implementable does not necessarily directly
> correspond to the same operations between field types and overall type in
> the way that it usually does for a type like std::vector. Specifically,
> things like the assignment operator in a sum-like type depend more on the
> move-*constructor* of field types than the move-assignment operator of
> the field types. This is why the move-constructor being not noexcept is
> what's actually impacting our assignment operation here. It's unintuitive
> perhaps, yes, but it's ultimately true and not really something that can be
> denied. I think you acknowledge that.
>
Yes, I understand that.
I also *do not care*. A `variant` has the responsibility of exporting the
intersection of behavior of its constituent types. I don't care if its easy
or hard to do; as long as it can be done (and is not unreasonably
inefficient), then `variant` should do it.
This is why I personally suggest constraining the assignment operation
> based on the move-constructor being noexcept, since if we don't, we're
> effectively requiring changing the implementation of the overall type in
> such a circumstance to the point that's it's not even really the same
> datastructure internally.
>
Implementation details are important for standardizing functionality; don't
get me wrong. But the mere fact that internal workings change based on
types is not the issue. Optimized `variant` implementations, of any kind,
will have various changes like this. They may have a different copy/move
implementation if all of the types are trivially copyable. They may put the
byte in front or the back, depending on the alignment and padding of the
types involved. And so forth.
The issue is not that the internal representation is different depending on
the typelist. The issue is the overhead caused by forwarding exception
guarantees, in space and time.
If users really want that, I'd argue they should just use a different type,
> or meet the constraints (which can be done non-intrusively to existing
> field types), or manually do double-buffering at a higher level.
>
My belief is that, religious objections aside, whatever variant gets
standardized should be *usable* by everyone. Even if the required overhead
is too much for some, they should have at least been able to theoretically
have used it if they like. And thus, new variant types would be created as
an *optimization*, not in order to actually write functional code.
The way I interpret things is this. My personal stance:
> * constrain operations based on what the fundamental the datastructure and
> its intrinsic functions require
>
So, what is your fundamental concept of a `variant` data-structure? How
does that fundamental concept justify making it non-copyable if all of the
types are throwing copies?
I didn't ask how the *implementation* justifies that. I asked how your
*concept*, "what the fundamental the datastructure and its intrinsic
functions require" justifies that.
If all of the typelists are moveable, so too should be the variant of them.
If all of the types in the typelist are noexcept moveable, so too should be
the variant of them.
To me, those are "what the fundamental the datastructure and its intrinsic
functions require". So from my perspective, your suggestion violates your
own principle.
Alternative:
> * constrain operations based on what people might more intuitively expect,
> regardless of how it affects the implementation
>
>
I view the alternative as a mistake. If the constraints seem unintuitive,
> then that's unfortunate, but I don't think we should act like they don't
> exist.
>
Those constraints only "exist" when you prioritize memory and runtime
performance over providing actual functionality. So you shouldn't act like
something is objectively true when it's based on priorities.
You're not arguing on the basis of some conceptual purity; you're arguing
on the basis that C++ is limited, we have to take some option, and yours is
the one that provides never-empty with neither an invalid state nor any
additional overhead, while still offering a basic exception guarantee.
Some people would find it easier to live with an invalid state. Others with
added overhead. Others would rather be emptyable to begin with.
Your perspective is not more correct than theirs simply because it's yours.
Doing so leads us to a solution where we either weaken the invariants of
> the type (adding invalid states) or a solution where the internal workings
> of the type are fundamentally changed for certain template arguments
> (double buffering). There are functional equivalents that don't require us
> making either of these sacrifices.
>
Yes. You instead sacrifice *something else*. It's still a sacrifice. The
question is which is worth more.
Your sacrifice makes the type non-functional for some people, so calling it
a "functional equivalent" is... dubious. I don't have access to Nevin's
codebase, so I can't say for certain. But it's entirely possible (from his
description) that the types he uses would make his `variant`s broken under
your system, all because someone used `std::list`s somewhere in the
aggregation hierarchy.
Or worse, it would work on one implementation, where they made
`std::list::list()` noexcept, while failing on another. That's a
non-trivial risk when declaring behavior non-functional due to the presence
of `noexcept`.
Williams.Variant punishes users of throw-move types by making them pay
extra memory costs. Your variant type punishes users of throw-move types by
making them use some other variant type.
That's too much of a sacrifice to me.
> On Tue, Sep 29, 2015 at 7:00 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> Without an actual invalid state, there is no way to offer any kind of
>>>> exception guarantee. Not for any typelist. So long as those types do not
>>>> have a noexcept default constructor, there is no way to put the variant in
>>>> a valid-but-unspecified state.
>>>>
>>>
>>> That's because you're defining your requirements separate from what the
>>> datastructure would imply. Instead we should l*ift* the requirements
>>> from the implementation of the datastructure and its intrinsic
>>> functions. I've always been stating "with a fallback" or via the "optional"
>>> solution. The suggestion is that if neither of these cases are satisfied,
>>> you've not met the concept requirements of the assignment operation.
>>> Instead of weakening the type's invariants and also complicating the
>>> contracts of all functions involved, a user could simply use one of the
>>> suggested solutions.
>>>
>>
>> Solutions that *do not exist*. Remember: no version of `optional` works
>> the way you need it to in order to be a valid solution (ie: switch to
>> nullopt on exception failure and synthesize operations that T does not
>> allow). And if the typelist doesn't contain a "fallback" state, then you
>> have a gimped type *with no recourse* to fix it.
>>
>
> It's not a "gimped" type, you're just not meeting the requirements of that
> operation. You choose to not like those requirements because they are
> unintuitive to you.
>
Stop putting words into people's mouths. The fact that it's shockingly
surprising behavior is only *one* of the flaws of your particular
sacrifice. I've mentioned the main one already (the fact that it's broken
for some people) and why that's not acceptable from a standard library type.
What you propose is a gimped interface because the requirements of that
operation do not match the actual *requirements* of that operation. They
only "match" those requirements if those requirements "lowest-possible
overhead and the basic exception guarantee with no invalidity".
If having your intuitive requirements implies completely changing the inner
> workings of the type and affects things as trivial as how the internal
> field types are accessed, all in the event that a template argument has a
> move constructor that can throw, simply to account for the assignment
> operation (which notably may or may not be used and may or may not require
> the strong guarantee), and doing so makes the type less efficient regarding
> space and regarding access, then I think that's irrational.
>
As previously stated, there is no perfect variant type. Someone else gave
their hierarchy of preferences. Here's mine:
Williams.Variant (sans-empty) > N4542 >> Eggs.Variant >>>> Matt.Variant
I think Williams.Variant is pretty much as close to being (design-wise)
correct as C++ can get. If even that overhead is considered to be too much,
I'm willing to accept an invalid-via-error state; not because I think it's
right or good, but purely as a concession to memory/performance needs.
And yes, the last entries show how much I dislike your idea. As much as
I've railed against it, I'd rather *lose never-empty* entirely than to use
a never-empty type that is broken in the way you suggest. Where merely
removing a default constructor's `noexcept` specification makes all your
code using `variant`s of that type stop working.
Better to be bloated and able to run than slim and non-functional.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7763_1103743991.1443651539289
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, September 30, 2015 at 3:13:07 PM UTC-4, Matt Calabrese wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div cla=
ss=3D"gmail_quote"><div></div><div>On Wed, Sep 30, 2015 at 8:03 AM, Nicol B=
olas=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" g=
df-obfuscated-mailto=3D"vf5BoR1cCgAJ" rel=3D"nofollow" onmousedown=3D"this.=
href=3D'javascript:';return true;" onclick=3D"this.href=3D'java=
script:';return true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote=
:</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"><div>That's one way to see it. Another way to s=
ee it is that it satisfies <i>at least</i> the guarantee that the objects t=
hemselves provide. If your throwing-move types provide a basic guarantee, t=
hen variant will not fix that for you. If your throwing-move types provide =
the strong guarantee, then variant will ensure that a variant containing th=
em will <i>also</i> provide that guarantee.<br></div></blockquote><div><br>=
</div><div>Okay, I accept that assessment and I sold it a little short, but=
that leaves you with the case that when one of your operations does <i>not=
</i>=C2=A0obey the strong guarantee, you are still paying for double buffer=
ing anyway, even though your overall guarantee is basic regardless.</div></=
div></div></div></blockquote><div><br>That's true.<br><br>Nothing with =
`variant` in C++ can be perfect; that's the nature of the game. Every p=
ossible implementation disadvantages <i>someone</i> in some way. But a type=
with overhead that a person can theoretically use is better than a no-over=
head type that they can't.<br><br>It should also be noted that exceptio=
n guarantees are not based on types, but on operations that throw. Though g=
enerally speaking, it's a good idea for all operations to have the same=
guarantee on a type, it is possible for certain operations to be strong an=
d others to be basic. So move assignment might be strong, while copy assign=
ment is basic.<br><br>So its better to be safe than to over-promise and und=
er-deliver.<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><div class=3D"gmail_quote"><div>All it's really doing =
in that case is bloating your type and making access less efficient.</div><=
/div></div></div></blockquote><div><br>How much bloat? How much less effici=
ent? Not just for a specific type; I want to know how it will actually affe=
ct things in the wild.<br><br>There have to be codebases out there that use=
s some templated `variant` type. It'd be interesting to look at all the=
variant instantiations they use and see just how many would gain space due=
to the issue. It'd also be interesting to see how many would be broken=
by your suggestion.<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><div class=3D"gmail_quote"><div>This is how the=
conversation regarding traits/noexcept describing strong/basic guarantee a=
rose.</div><div><br></div><div>On Wed, Sep 30, 2015 at 8:03 AM, Nicol Bolas=
=C2=A0<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-o=
bfuscated-mailto=3D"vf5BoR1cCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">jmck...@gmail.com</a>></span>=C2=A0<wbr>wrote:</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>I have moral objections with a variant interfering=
with the behavior of its typelist.<br></div></blockquote><div><br></div><d=
iv>You have to understand that with a sum-like type, the correspondence bet=
ween what is efficiently implementable does not necessarily directly corres=
pond to the same operations between field types and overall type in the way=
that it usually does for a type like std::vector. Specifically, things lik=
e the assignment operator in a sum-like type depend more on the move-<i>con=
structor</i> of field types than the move-assignment operator of the field =
types. This is why the move-constructor being not noexcept is what's ac=
tually=20
impacting our assignment operation here. It's unintuitive perhaps, yes,=
=20
but it's ultimately true and not really something that can be denied. I=
=20
think you acknowledge that.</div></div></div></div></blockquote><div><br>Ye=
s, I understand that.<br><br>I also <i>do not care</i>. A `variant` has the=
responsibility of exporting the intersection of behavior of its constituen=
t types. I don't care if its easy or hard to do; as long as it can be d=
one (and is not unreasonably inefficient), then `variant` should do it.<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"><di=
v><div class=3D"gmail_quote"><div>This is why I personally suggest constrai=
ning the assignment operation based on the move-constructor being noexcept,=
since if we don't, we're effectively requiring changing the implem=
entation of the overall type in such a circumstance to the point that's=
it's not even really the same datastructure internally.</div></div></d=
iv></div></blockquote><div><br>Implementation details are important for sta=
ndardizing functionality;=20
don't get me wrong. But the mere fact that internal workings change=20
based on types is not the issue. Optimized `variant` implementations, of
any kind, will have various changes like this. They may have a=20
different copy/move implementation if all of the types are trivially=20
copyable. They may put the byte in front or the back,=20
depending on the alignment and padding of the types involved. And so=20
forth.<br><br>The issue is not that the internal representation is differen=
t depending on the typelist. The issue is the overhead caused by forwarding=
exception guarantees, in space and time.<br><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><=
div>If users really want that, I'd argue they should just use a differe=
nt type, or meet the constraints (which can be done non-intrusively to exis=
ting field types), or manually do double-buffering at a higher level.</div>=
</div></div></div></blockquote><div><br>My belief is that, religious object=
ions aside, whatever variant gets standardized should be <i>usable</i> by e=
veryone. Even if the required overhead is too much for some, they should ha=
ve at least been able to theoretically have used it if they like. And thus,=
new variant types would be created as an <i>optimization</i>, not in order=
to actually write functional code.<br><br></div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></=
div><div>The way I interpret things is this. My personal stance:</div><div>=
* constrain operations based on what the fundamental the datastructure and =
its intrinsic functions require</div></div></div></div></blockquote><div><b=
r>So, what is your fundamental concept of a `variant` data-structure? How d=
oes that fundamental concept justify making it non-copyable if all of the t=
ypes are throwing copies?<br><br>I didn't ask how the <i>implementation=
</i> justifies that. I asked how your <i>concept</i>, "what the fundam=
ental the datastructure and its intrinsic functions require" justifies=
that.<br><br>If all of the typelists are moveable, so too should be the va=
riant of=20
them. If all of the types in the typelist are noexcept moveable, so too=20
should be the variant of them.<br><br>To me, those are "what the funda=
mental the datastructure and its intrinsic functions require". So from=
my perspective, your suggestion violates your own principle.<br><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div cla=
ss=3D"gmail_quote"><div></div><div>Alternative:</div><div>* constrain opera=
tions based on what people might more intuitively expect, regardless of how=
it affects the implementation<br></div></div></div></div></blockquote><blo=
ckquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204,=
204, 204); padding-left: 1ex;" class=3D"gmail_quote"><div>=C2=A0</div></bl=
ockquote><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=
><div class=3D"gmail_quote"><div></div><div>I view the alternative as a mis=
take. If the constraints seem unintuitive, then that's unfortunate, but=
I don't think we should act like they don't exist.</div></div></di=
v></div></blockquote><div><br>Those constraints only "exist" when=
you prioritize memory and runtime performance over providing actual functi=
onality. So you shouldn't act like something is objectively true when i=
t's based on priorities.<br><br>You're not arguing on the basis of =
some conceptual purity; you're arguing on the basis that C++ is limited=
, we have to take some option, and yours is the one that provides never-emp=
ty with neither an invalid state nor any additional overhead, while still o=
ffering a basic exception guarantee.<br><br>Some people would find it easie=
r to live with an invalid state. Others with added overhead. Others would r=
ather be emptyable to begin with.<br><br>Your perspective is not more corre=
ct than theirs simply because it's yours.<br><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quot=
e"><div> Doing so leads us to a solution where we either weaken the invaria=
nts of the type (adding invalid states) or a solution where the internal wo=
rkings of the type are fundamentally changed for certain template arguments=
(double buffering). There are functional equivalents that don't requir=
e us making either of these sacrifices.</div></div></div></div></blockquote=
><div><br>Yes. You instead sacrifice <i>something else</i>. It's still =
a sacrifice. The question is which is worth more.<br><br>Your sacrifice mak=
es the type non-functional for some people, so calling it a "functiona=
l equivalent" is... dubious. I don't have access to Nevin's co=
debase, so I can't say for certain. But it's entirely possible (fro=
m his description) that the types he uses would make his `variant`s broken =
under your system, all because someone used `std::list`s somewhere in the a=
ggregation hierarchy.<br><br>Or worse, it would work on one implementation,=
where they made `std::list::list()` noexcept, while failing on another. Th=
at's a non-trivial risk when declaring behavior non-functional due to t=
he presence of `noexcept`.<br><br>Williams.Variant punishes users of throw-=
move types by making them pay extra memory costs. Your variant type punishe=
s users of throw-move types by making them use some other variant type.<br>=
<br>That's too much of a sacrifice to me.<br>=C2=A0</div><blockquote cl=
ass=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 class=3D"gmail_qu=
ote"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-le=
ft-style:solid;padding-left:1ex"><span><blockquote class=3D"gmail_quote" st=
yle=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"><d=
iv><div class=3D"gmail_quote"><div>On Tue, Sep 29, 2015 at 7:00 PM, Nicol B=
olas=C2=A0<span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>&g=
t;</span>=C2=A0<wbr>wrote:</div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex"><div>Without
an actual invalid state, there is no way to offer any kind of exception
guarantee. Not for any typelist. So long as those types do not have a noex=
cept default constructor, there is no way to put the variant in a valid-but=
-unspecified state.</div></blockquote><div><br></div><div>That's becaus=
e you're defining your requirements separate from what the datastructur=
e would imply. Instead we should l<i>ift</i>=C2=A0the requirements from the=
implementation of the datastructure and its intrinsic functions.=C2=A0I=
9;ve always been stating "with a fallback" or via the "optio=
nal" solution. The suggestion is that if neither of these cases are sa=
tisfied, you've not met the concept requirements of the assignment oper=
ation. Instead of weakening the type's invariants and also complicating=
the contracts of all functions involved, a user could simply use one of th=
e suggested solutions.</div></div></div></div></blockquote></span><div><br>=
Solutions that <i>do not exist</i>. Remember: no version of `optional` work=
s the way you need it to in order to be a valid solution (ie: switch to nul=
lopt on exception failure and synthesize operations that T does not allow).=
And if the typelist doesn't contain a "fallback" state, then=
you have a gimped type <i>with no recourse</i> to fix it.</div></blockquot=
e><div>=C2=A0</div><div>It's not a "gimped" type, you're =
just not meeting the requirements of that operation. You choose to not like=
those requirements because they are unintuitive to you.</div></div></div><=
/div></blockquote><div><br>Stop putting words into people's mouths. The=
fact that it's shockingly surprising behavior is only <i>one</i> of th=
e flaws of your particular sacrifice. I've mentioned the main one alrea=
dy (the fact that it's broken for some people) and why that's not a=
cceptable from a standard library type.<br><br>What you propose is a gimped=
interface because the requirements of that operation do not match the actu=
al <i><b>requirements</b></i> of that operation. They only "match"=
; those requirements if those requirements "lowest-possible overhead a=
nd the basic exception guarantee with no invalidity".<br><br></div><bl=
ockquote 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><div class=
=3D"gmail_quote"><div>If having your intuitive requirements implies complet=
ely changing the inner workings of the type and affects things as trivial a=
s how the internal field types are accessed, all in the event that a templa=
te argument has a move constructor that can throw, simply to account for th=
e assignment operation (which notably may or may not be used and may or may=
not require the strong guarantee), and doing so makes the type less effici=
ent regarding space and regarding access, then I think that's irrationa=
l.</div></div></div></div></blockquote><div><br>As previously stated, there=
is no perfect variant type. Someone else gave their hierarchy of preferenc=
es. Here's mine:<br><br>Williams.Variant (sans-empty) > N4542 >&g=
t; Eggs.Variant >>>> Matt.Variant<br><br>I think Williams.Varia=
nt is pretty much as close to being (design-wise) correct as C++ can get. I=
f even that overhead is considered to be too much, I'm willing to accep=
t an invalid-via-error state; not because I think it's right or good, b=
ut purely as a concession to memory/performance needs.<br><br>And yes, the =
last entries show how much I dislike your idea. As much as I've railed =
against it, I'd rather <i>lose never-empty</i> entirely than to use a n=
ever-empty type that is broken in the way you suggest. Where merely removin=
g a default constructor's `noexcept` specification makes all your code =
using `variant`s of that type stop working.<br><br>Better to be bloated and=
able to run than slim and non-functional.<br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;">
</blockquote>
<p></p>
-- <br />
<br />
--- <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 />
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_7763_1103743991.1443651539289--
------=_Part_7762_1176613441.1443651539288--
.
Author: David Krauss <potswa@gmail.com>
Date: Thu, 1 Oct 2015 19:56:46 +0800
Raw View
--Apple-Mail=_38E2F398-D260-427D-86AA-C551EC392B47
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9330, at 11:47 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I liked the idea so much that I implemented it (on a branch: https://gith=
ub.com/eggs-cpp/variant/tree/N4462 <https://github.com/eggs-cpp/variant/tre=
e/N4462>). I found the duplicated constructor implementation cost manageabl=
e, but then I could not complete it as I was lacking an `is_more_perfect_co=
nstructible` trait for SFINAE, an `is_nothrow_more_perfect_constructible` t=
rait for `noexcept`, and new power words to describe these on the documenta=
tion.
Hmm=E2=80=A6 N4462 left the exact standard interface open-ended, but the in=
tent is that it shouldn=E2=80=99t be reimplemented per container. It should=
be reliably available as std::allocator<T>::construct if no other std:: na=
me is allocated.
I hope we don=E2=80=99t ever need std::is_nothrow_more_perfect_constructibl=
e, but rather just expression SFINAE on noexcept(std::allocator::construct(=
args)) or noexcept(std::allocator_traits::construct(a, args)).
As for your immediate problem, perhaps this expression SFINAE would do the =
trick:
> + , typename std::enable_if< =20
> + !std::is_constructible<decltype(T{ Args ... }), Args...>::value, bool =
=20
> + >::type =3D false =20
When this overload is chosen, you can assume that brace initialization is u=
sed, and then write the noexcept spec that way.
(I submitted the DR which became N4462=E2=80=A6)
--=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/.
--Apple-Mail=_38E2F398-D260-427D-86AA-C551EC392B47
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9330, at 11:47 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"ma=
ilto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:=
</div><br class=3D"Apple-interchange-newline"><div class=3D""><span style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px; float: none; display: inline !important;" class=3D"">I liked t=
he idea so much that I implemented it (on a branch:<span class=3D"Apple-con=
verted-space"> </span></span><a href=3D"https://github.com/eggs-cpp/va=
riant/tree/N4462" style=3D"font-family: Helvetica; font-size: 12px; font-st=
yle: normal; font-variant: normal; font-weight: normal; letter-spacing: nor=
mal; line-height: normal; orphans: auto; text-align: start; text-indent: 0p=
x; text-transform: none; white-space: normal; widows: auto; word-spacing: 0=
px; -webkit-text-stroke-width: 0px;" class=3D"">https://github.com/eggs-cpp=
/variant/tree/N4462</a><span style=3D"font-family: Helvetica; font-size: 12=
px; font-style: normal; font-variant: normal; font-weight: normal; letter-s=
pacing: normal; line-height: normal; orphans: auto; text-align: start; text=
-indent: 0px; text-transform: none; white-space: normal; widows: auto; word=
-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline=
!important;" class=3D"">). I found the duplicated constructor implementati=
on cost manageable, but then I could not complete it as I was lacking an `i=
s_more_perfect_constructible` trait for SFINAE, an `is_nothrow_more_perfect=
_constructible` trait for `noexcept`, and new power words to describe these=
on the documentation.</span><br style=3D"font-family: Helvetica; font-size=
: 12px; font-style: normal; font-variant: normal; font-weight: normal; lett=
er-spacing: normal; line-height: normal; orphans: auto; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; widows: auto; =
word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""></div></bloc=
kquote></div><div class=3D""><br class=3D""></div><div class=3D"">Hmm=E2=80=
=A6 N4462 left the exact standard interface open-ended, but the intent is t=
hat it shouldn=E2=80=99t be reimplemented per container. It should be relia=
bly available as <font face=3D"Courier" class=3D"">std::allocator<T>:=
:construct</font> if no other <font face=3D"Courier" class=3D"">std::<=
/font> name is allocated.</div><div class=3D""><br class=3D""></div><div cl=
ass=3D"">I hope we don=E2=80=99t ever need <font face=3D"Courier" class=3D"=
">std::is_nothrow_more_perfect_constructible</font>, but rather just expres=
sion SFINAE on <span style=3D"font-family: Courier;" class=3D"">noexce=
pt(std::allocator::construct(args))</span> or <font face=3D"Couri=
er" class=3D"">noexcept(std::allocator_traits::construct(a, args))</font>.<=
/div><div class=3D""><br class=3D""></div><div class=3D"">As for your immed=
iate problem, perhaps this expression SFINAE would do the trick:</div><div =
class=3D""><br class=3D""></div><div class=3D""><blockquote type=3D"cite" c=
lass=3D""><table class=3D" diff-table tab-size" data-tab-size=3D"8"><tbody =
class=3D""><tr class=3D""><td class=3D"blob-code-addition blob-code">
<font face=3D"Courier" style=3D"font-size: 12px;" class=3D""><span clas=
s=3D"blob-code-inner">+ , <span class=3D"pl-k">typename</span> std=
::enable_if<</span>
</font></td>
</tr>
=20
<tr class=3D"">
</tr></tbody></table><table class=3D" diff-table tab-size" data-tab-siz=
e=3D"8"><tbody class=3D""><tr class=3D"">
</tr></tbody></table><table class=3D" diff-table tab-size" data-tab-siz=
e=3D"8"><tbody class=3D""><tr class=3D""></tr><tr class=3D"">
<td class=3D"blob-code-addition blob-code">
<font face=3D"Courier" style=3D"font-size: 12px;" class=3D""><span clas=
s=3D"blob-code-inner">+ !std::is_constructible<decltype(T=
{ Args ... }), Args...>::value, <span class=3D"pl-k">bool</span></span>
</font></td>
</tr>
=20
<tr class=3D"">
</tr></tbody></table><table class=3D" diff-table tab-size" data-tab-siz=
e=3D"8"><tbody class=3D""><tr class=3D"">
</tr></tbody></table><table class=3D" diff-table tab-size" data-tab-siz=
e=3D"8"><tbody class=3D""><tr class=3D"">
<td class=3D"blob-code-addition blob-code">
<font face=3D"Courier" style=3D"font-size: 12px;" class=3D""><span clas=
s=3D"blob-code-inner">+ >::type =3D <span class=3D"pl-c1">fal=
se</span></span>
</font></td></tr></tbody></table></blockquote><div class=3D""><br class=
=3D""></div></div><div class=3D"">When this overload is chosen, you can ass=
ume that brace initialization is used, and then write the <font face=3D"Cou=
rier" class=3D"">noexcept</font> spec that way.</div><div class=3D""><br cl=
ass=3D""></div><div class=3D"">(I submitted the DR which became N4462=E2=80=
=A6)</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_38E2F398-D260-427D-86AA-C551EC392B47--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Thu, 1 Oct 2015 10:42:05 -0300
Raw View
On 10/1/2015 8:56 AM, David Krauss wrote:
>
>> On 2015=E2=80=9309=E2=80=9330, at 11:47 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> I liked the idea so much that I implemented it (on a
>> branch:https://github.com/eggs-cpp/variant/tree/N4462). I found the
>> duplicated constructor implementation cost manageable, but then I
>> could not complete it as I was lacking an
>> `is_more_perfect_constructible` trait for SFINAE, an
>> `is_nothrow_more_perfect_constructible` trait for `noexcept`, and new
>> power words to describe these on the documentation.
>
> Hmm=E2=80=A6 N4462 left the exact standard interface open-ended, but the =
intent
> is that it shouldn=E2=80=99t be reimplemented per container. It should be
> reliably available as std::allocator<T>::construct if no other std::
> name is allocated.
Facilities with embedded storage (`pair`, `tuple`, `optional`,=20
`variant`, ...) tend to use member-initializer-lists to construct their=20
subobjects (sometimes they must, e.g. `constexpr`). An=20
`allocator<T>::construct` is not a viable option for them, nor is some=20
`construct<T>` function since that would incur artificial move=20
construction. Only a core language change would guarantee this=20
functionality does not have to be reimplemented over and over.
> I hope we don=E2=80=99t ever need std::is_nothrow_more_perfect_constructi=
ble,
> but rather just expression SFINAE on
> noexcept(std::allocator::construct(args)) or
> noexcept(std::allocator_traits::construct(a, args)).
Those aren't SFINAE friendly nor noexcept transparent.
> As for your immediate problem, perhaps this expression SFINAE would do
> the trick:
>
>> + , typename std::enable_if<
>>
>> + !std::is_constructible<decltype(T{ Args ... }), Args...>::value, bool
>>
>> + >::type =3D false
>>
>
> When this overload is chosen, you can assume that brace initialization
> is used, and then write the noexcept spec that way.
If I were to complete the N4462 implementation, I could implement the=20
missing traits as implementation details. I stopped because I can see=20
the people willing to go the extra mile to implement it wanting the=20
satellite traits and definitions. If you are willing to do some fancy=20
SFINAE and duplicate your constructors to support a new form of=20
construction, it's highly probably that you will be doing SFINAE and/or=20
noexcept for it too. And for it to be used, you'll likely have to=20
document the interface as doing this new form of construction with no name.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Thu, 1 Oct 2015 23:58:16 +0800
Raw View
--Apple-Mail=_B9F51C7E-4D1F-46C6-87D0-F14322537A84
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9301, at 9:42 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> Facilities with embedded storage (`pair`, `tuple`, `optional`, `variant`,=
...) tend to use member-initializer-lists to construct their subobjects (s=
ometimes they must, e.g. `constexpr`). An `allocator<T>::construct` is not =
a viable option for them, nor is some `construct<T>` function since that wo=
uld incur artificial move construction. Only a core language change would g=
uarantee this functionality does not have to be reimplemented over and over=
..
Yes, I=E2=80=99m contemplating some sort of core language extension to help=
alleviate the need for Allocator::construct. There=E2=80=99s using-allocat=
or construction, destructive-move construction, more-uniform initialization=
, and no reason the user should need to pretend to introduce an allocation =
policy when defining some new initialization policy.
>> I hope we don=E2=80=99t ever need std::is_nothrow_more_perfect_construct=
ible,
>> but rather just expression SFINAE on
>> noexcept(std::allocator::construct(args)) or
>> noexcept(std::allocator_traits::construct(a, args)).
>=20
> Those aren't SFINAE friendly nor noexcept transparent.
Right, but they should be. The lack of those properties has a ripple-down e=
ffect cursing anything that touches an allocator.
> If I were to complete the N4462 implementation, I could implement the mis=
sing traits as implementation details. I stopped because I can see the peop=
le willing to go the extra mile to implement it wanting the satellite trait=
s and definitions. If you are willing to do some fancy SFINAE and duplicate=
your constructors to support a new form of construction, it's highly proba=
bly that you will be doing SFINAE and/or noexcept for it too. And for it to=
be used, you'll likely have to document the interface as doing this new fo=
rm of construction with no name.
My point is that I think traits templates are getting out of hand and I=E2=
=80=99d like a more uniform approach to initialization SFINAE.
--=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/.
--Apple-Mail=_B9F51C7E-4D1F-46C6-87D0-F14322537A84
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9301, at 9:42 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"mai=
lto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:<=
/div><br class=3D"Apple-interchange-newline"><div class=3D"">Facilities wit=
h embedded storage (`pair`, `tuple`, `optional`, `variant`, ...) tend to us=
e member-initializer-lists to construct their subobjects (sometimes they mu=
st, e.g. `constexpr`). An `allocator<T>::construct` is not a viable o=
ption for them, nor is some `construct<T>` function since that would =
incur artificial move construction. Only a core language change would guara=
ntee this functionality does not have to be reimplemented over and over.<br=
class=3D""></div></blockquote><div><br class=3D""></div><div>Yes, I=E2=80=
=99m contemplating some sort of core language extension to help alleviate t=
he need for <font face=3D"Courier" class=3D"">Allocator::construct</font>. =
There=E2=80=99s using-allocator construction, destructive-move construction=
, more-uniform initialization, and no reason the user should need to preten=
d to introduce an allocation policy when defining some new initialization p=
olicy.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=
=3D""><blockquote type=3D"cite" class=3D"">I hope we don=E2=80=99t ever nee=
d std::is_nothrow_more_perfect_constructible,<br class=3D"">but rather just=
expression SFINAE on<br class=3D"">noexcept(std::allocator::construct(args=
)) or<br class=3D"">noexcept(std::allocator_traits::construct(a, args)).<br=
class=3D""></blockquote><br class=3D"">Those aren't SFINAE friendly nor no=
except transparent.<br class=3D""></div></blockquote><div><br class=3D""></=
div><div>Right, but they should be. The lack of those properties has a ripp=
le-down effect cursing anything that touches an allocator.</div><br class=
=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">If I were to com=
plete the N4462 implementation, I could implement the missing traits as imp=
lementation details. I stopped because I can see the people willing to go t=
he extra mile to implement it wanting the satellite traits and definitions.=
If you are willing to do some fancy SFINAE and duplicate your constructors=
to support a new form of construction, it's highly probably that you will =
be doing SFINAE and/or noexcept for it too. And for it to be used, you'll l=
ikely have to document the interface as doing this new form of construction=
with no name.<br class=3D""></div></blockquote></div><br class=3D""><div c=
lass=3D"">My point is that I think traits templates are getting out of hand=
and I=E2=80=99d like a more uniform approach to initialization SFINAE.</di=
v><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_B9F51C7E-4D1F-46C6-87D0-F14322537A84--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Thu, 1 Oct 2015 13:36:14 -0300
Raw View
On 10/1/2015 12:58 PM, David Krauss wrote:
>> On 2015=E2=80=9310=E2=80=9301, at 9:42 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>>> I hope we don=E2=80=99t ever need std::is_nothrow_more_perfect_construc=
tible,
>>> but rather just expression SFINAE on
>>> noexcept(std::allocator::construct(args)) or
>>> noexcept(std::allocator_traits::construct(a, args)).
>>
>> Those aren't SFINAE friendly nor noexcept transparent.
>
> Right, but they should be. The lack of those properties has a
> ripple-down effect cursing anything that touches an allocator.
I'm not sure I see why it should be SFINAE friendly. What other=20
`allocator[_traits]::construct` overload could you possibly intend to=20
call that would be a viable match were it not for the substitution error=20
outside an immediate context?
>> If I were to complete the N4462 implementation, I could implement the
>> missing traits as implementation details. I stopped because I can see
>> the people willing to go the extra mile to implement it wanting the
>> satellite traits and definitions. If you are willing to do some fancy
>> SFINAE and duplicate your constructors to support a new form of
>> construction, it's highly probably that you will be doing SFINAE
>> and/or noexcept for it too. And for it to be used, you'll likely have
>> to document the interface as doing this new form of construction with
>> no name.
>
> My point is that I think traits templates are getting out of hand and
> I=E2=80=99d like a more uniform approach to initialization SFINAE.
My point is that this new semantic construct ought to have a name.=20
Something by which people refer to the notion, instead of enumerating=20
the rules by which it is defined. Someone said this is `INVOKE` for=20
constructors, I hope we don't repeat that mistake.
I want to write in the documentation that my constructor requires T to=20
be fancy-constructible, or that it shall not participate in overload=20
resolution unless T is fancy-constructible. And I want to continue that=20
in code, either by `static_assert`, `requires` or `enable_if` as=20
appropriate. So I would expect any proposal to at least define a name=20
for the new concept it introduces, so that people don't have to invent=20
(different) names for it. Then we can wait and see how many people=20
implement an `is_fancy_constructible` trait before deciding to provide one.
My overall point is that the goal is worthy, but the proposal does not=20
come in an easy to consume form. Just as with `INVOKE`, originally=20
designed to motivate a core language change, had users reimplementing=20
that functionality over and over again in slightly broken ways before=20
finally providing it in the standard library. We should try to provide a=20
feature complete library solution from the go, or perhaps we should just=20
bite the core language change.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Sam Kellett <samkellett@gmail.com>
Date: Thu, 1 Oct 2015 22:13:28 +0100
Raw View
--001a11410972b8540705211184cd
Content-Type: text/plain; charset=UTF-8
> I think Williams.Variant is pretty much as close to being (design-wise)
> correct as C++ can get. If even that overhead is considered to be too much,
> I'm willing to accept an invalid-via-error state; not because I think it's
> right or good, but purely as a concession to memory/performance needs.
>
> And yes, the last entries show how much I dislike your idea. As much as
> I've railed against it, I'd rather *lose never-empty* entirely than to
> use a never-empty type that is broken in the way you suggest. Where merely
> removing a default constructor's `noexcept` specification makes all your
> code using `variant`s of that type stop working.
>
sorry if this has been mentioned before -- there has been a huge amount of
variant talk (just look at how many variant papers are going to kona!) and
i think i've only seen relatively little...
but could it be acceptable to allow the user to select which type of
variant behaviour they want via a variant_traits template parameter? ie.
one that forces noexcept move of all types or one that has an empty state
or one that double buffers or one that uses the heap, etc...
and on maybe another note entirely, would it be possible to use some
compiler magic to get a perfect variant (ie single-buffer, any type,
never-empty)? i've only seen talk of library implementations, but why not
(if helpful) let the compiler do some work too?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11410972b8540705211184cd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>I think Williams.V=
ariant is pretty much as close to being (design-wise) correct as C++ can ge=
t. If even that overhead is considered to be too much, I'm willing to a=
ccept an invalid-via-error state; not because I think it's right or goo=
d, but purely as a concession to memory/performance needs.<br><br>And yes, =
the last entries show how much I dislike your idea. As much as I've rai=
led against it, I'd rather <i>lose never-empty</i> entirely than to use=
a never-empty type that is broken in the way you suggest. Where merely rem=
oving a default constructor's `noexcept` specification makes all your c=
ode using `variant`s of that type stop working.</div></blockquote><div><br>=
</div><div>sorry if this has been mentioned before -- there has been a huge=
amount of variant talk (just look at how many variant papers are going to =
kona!) and i think i've only seen relatively little... <br><br></div><d=
iv>but could it be acceptable to allow the user to select which type of var=
iant behaviour they want via a variant_traits template parameter? ie. one t=
hat forces noexcept move of all types or one that has an empty state or one=
that double buffers or one that uses the heap, etc...<br><br><br></div><di=
v>and on maybe another note entirely, would it be possible to use some comp=
iler magic to get a perfect variant (ie single-buffer, any type, never-empt=
y)? i've only seen talk of library implementations, but why not (if hel=
pful) let the compiler do some work too?<br> </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11410972b8540705211184cd--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Thu, 1 Oct 2015 17:43:21 -0400
Raw View
--001a113fb8c09f74bd052111ef61
Content-Type: text/plain; charset=UTF-8
On Thu, Oct 1, 2015 at 5:13 PM, Sam Kellett <samkellett@gmail.com> wrote:
>
> I think Williams.Variant is pretty much as close to being (design-wise)
>> correct as C++ can get. If even that overhead is considered to be too much,
>> I'm willing to accept an invalid-via-error state; not because I think it's
>> right or good, but purely as a concession to memory/performance needs.
>>
>> And yes, the last entries show how much I dislike your idea. As much as
>> I've railed against it, I'd rather *lose never-empty* entirely than to
>> use a never-empty type that is broken in the way you suggest. Where merely
>> removing a default constructor's `noexcept` specification makes all your
>> code using `variant`s of that type stop working.
>>
>
> sorry if this has been mentioned before -- there has been a huge amount of
> variant talk (just look at how many variant papers are going to kona!) and
> i think i've only seen relatively little...
>
> but could it be acceptable to allow the user to select which type of
> variant behaviour they want via a variant_traits template parameter? ie.
> one that forces noexcept move of all types or one that has an empty state
> or one that double buffers or one that uses the heap, etc...
>
>
If it wasn't ugly. Even just buffering vs invalid would be nice.
However, in general the committee shies away from policy-based classes.
Part of the problem is that you want APIs that take one type, not a whole
class of types.
ie a function that takes a shared_ptr<Foo> :
void doSomething(shared_ptr<Foo> foo) {
.... lots of code here...
}
If shared_ptr had policies (for destruction, etc), then my function
_probably_ needs to become a template:
template<typename Policy>
void doSomething(shared_ptr<Foo, Policy> foo) {
....lots of code here, now in the header ...
}
Not sure if the same applies to a policy-based variant, but that's the
general criticism of policies.
You _might_ be able to argue variant is different because _maybe_:
A) many variants get used via typedefs, so you need not see the policy
B) many variant functions are already templates
?
> and on maybe another note entirely, would it be possible to use some
> compiler magic to get a perfect variant (ie single-buffer, any type,
> never-empty)? i've only seen talk of library implementations, but why not
> (if helpful) let the compiler do some work too?
>
The compiler probably can't help you. For variant<X,Y> the goal is to
destroy the old X, and _in the same place_ construct a Y. If constructing
the Y fails, what do you do?
*IF* the compiler knew that it could just memcpy X from a temporary and
back into place, it could restore X. But some classes have pointers to
themselves and other oddities such that an X here is not the same as an X
there:
class X {
char blob[32];
char * ptr;
X(const char * str) {
if (int len = strlen(str) < 32) {
ptr = blob;
} else {
ptr = malloc(len + 1);
}
strcpy(ptr, str);
}
~X()
{
if (ptr != blob) {
free(ptr);
}
}
};
// ignore the bugs. I don't have an email compiler
You can't memcpy the above (and expect the class not to crash in the
destructor at least).
The only way the compiler can know, is by checking things like
is_trivially_copyable or is_nothrow_move_whatever, etc. But these are the
same things a library can do.
I see no compiler magic available here. Most compiler magic (in terms of
checking classes) is now available to libraries.
HOWEVER, the *system* could maybe do magic.
For example, Transactional Memory would give us the ideal variant (I think).
Or, in theory, messing with virtual memory addressing in some magical way -
because the "C++ pointer" memory location of X really isn't the same as the
physical memory location of X. But I suspect this would only be possible
with page-sized objects (if at all).
Or some magic I haven't thought of.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113fb8c09f74bd052111ef61
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Thu, Oct 1, 2015 at 5:13 PM, Sam Kellett <span dir=3D"ltr"><<a hr=
ef=3D"mailto:samkellett@gmail.com" target=3D"_blank">samkellett@gmail.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"><sp=
an class=3D""><br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div>I think Williams.Vari=
ant is pretty much as close to being (design-wise) correct as C++ can get. =
If even that overhead is considered to be too much, I'm willing to acce=
pt an invalid-via-error state; not because I think it's right or good, =
but purely as a concession to memory/performance needs.<br><br>And yes, the=
last entries show how much I dislike your idea. As much as I've railed=
against it, I'd rather <i>lose never-empty</i> entirely than to use a =
never-empty type that is broken in the way you suggest. Where merely removi=
ng a default constructor's `noexcept` specification makes all your code=
using `variant`s of that type stop working.</div></blockquote><div><br></d=
iv></span><div>sorry if this has been mentioned before -- there has been a =
huge amount of variant talk (just look at how many variant papers are going=
to kona!) and i think i've only seen relatively little... <br><br></di=
v><div>but could it be acceptable to allow the user to select which type of=
variant behaviour they want via a variant_traits template parameter? ie. o=
ne that forces noexcept move of all types or one that has an empty state or=
one that double buffers or one that uses the heap, etc...<br><br></div></d=
iv></blockquote><div><br></div><div>If it wasn't ugly.=C2=A0 Even just =
buffering vs invalid would be nice.<br><br></div><div>However, in general t=
he committee shies away from policy-based classes.<br></div>Part of the pro=
blem is that you want APIs that take one type, not a whole class of types.<=
br></div><div class=3D"gmail_quote">ie a function that takes a shared_ptr&l=
t;Foo> :<br><br>void doSomething(shared_ptr<Foo> foo) {<br></div><=
div class=3D"gmail_quote">... lots of code here...<br></div><div class=3D"g=
mail_quote">}<br><br>If shared_ptr had policies (for destruction, etc), the=
n my function _probably_ needs to become a template:<br><br></div><div clas=
s=3D"gmail_quote">template<typename Policy><br></div><div class=3D"gm=
ail_quote">void doSomething(shared_ptr<Foo, Policy> foo) {<br></div><=
div class=3D"gmail_quote">...lots of code here, now in the header ...<br></=
div><div class=3D"gmail_quote">}<br><br></div><div class=3D"gmail_quote">No=
t sure if the same applies to a policy-based variant, but that's the ge=
neral criticism of policies.<br><br></div><div class=3D"gmail_quote">You _m=
ight_ be able to argue variant is different because _maybe_:<br></div><div =
class=3D"gmail_quote">A) many variants get used via typedefs, so you need n=
ot see the policy<br></div><div class=3D"gmail_quote">B) many variant funct=
ions are already templates<br>?<br><br></div><div class=3D"gmail_quote"><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div>and on may=
be another note entirely, would it be possible to use some compiler magic t=
o get a perfect variant (ie single-buffer, any type, never-empty)? i've=
only seen talk of library implementations, but why not (if helpful) let th=
e compiler do some work too?<br></div></div></blockquote><div><br></div><di=
v>The compiler probably can't help you.=C2=A0 For variant<X,Y> th=
e goal is to destroy the old X, and _in the same place_ construct a Y.=C2=
=A0 If constructing the Y fails, what do you do?<br></div><div>*IF* the com=
piler knew that it could just memcpy X from a temporary and back into place=
, it could restore X.=C2=A0 But some classes have pointers to themselves an=
d other oddities such that an X here is not the same as an X there:<br><br>=
</div><div>class X {<br></div><div>=C2=A0=C2=A0=C2=A0 char blob[32];<br></d=
iv><div>=C2=A0=C2=A0=C2=A0 char * ptr;<br></div><div>=C2=A0=C2=A0=C2=A0 X(c=
onst char * str) { <br></div><div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 if (int len =3D strlen(str) < 32) {<br></div><div>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ptr =3D blob;<br></div><di=
v>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } else {<br></div><div>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ptr =3D malloc=
(len + 1);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br></div><div>=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 strcpy(ptr, str);<br></div><div>=
=C2=A0=C2=A0=C2=A0 }<br></div><div>=C2=A0=C2=A0=C2=A0 ~X()<br>=C2=A0=C2=A0=
=C2=A0 {<br></div><div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 if (ptr !=3D blob) {<br></div><div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 free(ptr);<br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br>=C2=A0=C2=A0=C2=A0 }<br></div><div>};<b=
r></div><div>// ignore the bugs. I don't have an email compiler<br></di=
v><div><br></div><div>You can't memcpy the above (and expect the class =
not to crash in the destructor at least).<br><br></div><div>The only way th=
e compiler can know, is by checking things like is_trivially_copyable or is=
_nothrow_move_whatever, etc.=C2=A0 But these are the same things a library =
can do.<br></div><div>I see no compiler magic available here.=C2=A0 Most co=
mpiler magic (in terms of checking classes) is now available to libraries.<=
br><br></div><div>HOWEVER, the *system* could maybe do magic.<br></div><div=
>For example, Transactional Memory would give us the ideal variant (I think=
).<br><br></div><div>Or, in theory, messing with virtual memory addressing =
in some magical way - because the "C++ pointer" memory location o=
f X really isn't the same as the physical memory location of X.=C2=A0 B=
ut I suspect this would only be possible with page-sized objects (if at all=
).<br><br></div><div>Or some magic I haven't thought of.<br></div><div>=
<br></div><div>Tony<br></div></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113fb8c09f74bd052111ef61--
.
Author: Sam Kellett <samkellett@gmail.com>
Date: Thu, 1 Oct 2015 22:53:24 +0100
Raw View
--001a11c342ee8579e30521121343
Content-Type: text/plain; charset=UTF-8
On Thu, Oct 1, 2015 at 5:13 PM, Sam Kellett <samkellett@gmail.com> wrote:
>
>>
>> I think Williams.Variant is pretty much as close to being (design-wise)
>>> correct as C++ can get. If even that overhead is considered to be too much,
>>> I'm willing to accept an invalid-via-error state; not because I think it's
>>> right or good, but purely as a concession to memory/performance needs.
>>>
>>> And yes, the last entries show how much I dislike your idea. As much as
>>> I've railed against it, I'd rather *lose never-empty* entirely than to
>>> use a never-empty type that is broken in the way you suggest. Where merely
>>> removing a default constructor's `noexcept` specification makes all your
>>> code using `variant`s of that type stop working.
>>>
>>
>> sorry if this has been mentioned before -- there has been a huge amount
>> of variant talk (just look at how many variant papers are going to kona!)
>> and i think i've only seen relatively little...
>>
>> but could it be acceptable to allow the user to select which type of
>> variant behaviour they want via a variant_traits template parameter? ie.
>> one that forces noexcept move of all types or one that has an empty state
>> or one that double buffers or one that uses the heap, etc...
>>
>>
> If it wasn't ugly. Even just buffering vs invalid would be nice.
>
> However, in general the committee shies away from policy-based classes.
> Part of the problem is that you want APIs that take one type, not a whole
> class of types.
> ie a function that takes a shared_ptr<Foo> :
>
> void doSomething(shared_ptr<Foo> foo) {
> ... lots of code here...
> }
>
> If shared_ptr had policies (for destruction, etc), then my function
> _probably_ needs to become a template:
>
> template<typename Policy>
> void doSomething(shared_ptr<Foo, Policy> foo) {
> ...lots of code here, now in the header ...
> }
>
> Not sure if the same applies to a policy-based variant, but that's the
> general criticism of policies.
>
> You _might_ be able to argue variant is different because _maybe_:
> A) many variants get used via typedefs, so you need not see the policy
> B) many variant functions are already templates
> ?
>
thanks for the feedback.
ugly is true, but i think it could be avoidable at the user level. say
something more akin to std::string than std::shared_ptr. so you would have
a std::basic_variant and from there you have your variant types defined
(ala wstring, u16string, etc...) -- i have no idea what you'd call them
though...
std::sbvariant, std::mvvariant, std::nevariant... these names all suck bad,
points if you can even guess which one is which from my previous email..
but yeah, you'd never really deal with the policy on a per-function basis,
just like you rarely if ever do with strings.
>
>
>> and on maybe another note entirely, would it be possible to use some
>> compiler magic to get a perfect variant (ie single-buffer, any type,
>> never-empty)? i've only seen talk of library implementations, but why not
>> (if helpful) let the compiler do some work too?
>>
>
> The compiler probably can't help you. For variant<X,Y> the goal is to
> destroy the old X, and _in the same place_ construct a Y. If constructing
> the Y fails, what do you do?
> *IF* the compiler knew that it could just memcpy X from a temporary and
> back into place, it could restore X. But some classes have pointers to
> themselves and other oddities such that an X here is not the same as an X
> there:
>
> class X {
> char blob[32];
> char * ptr;
> X(const char * str) {
> if (int len = strlen(str) < 32) {
> ptr = blob;
> } else {
> ptr = malloc(len + 1);
> }
> strcpy(ptr, str);
> }
> ~X()
> {
> if (ptr != blob) {
> free(ptr);
> }
> }
> };
> // ignore the bugs. I don't have an email compiler
>
> You can't memcpy the above (and expect the class not to crash in the
> destructor at least).
>
> The only way the compiler can know, is by checking things like
> is_trivially_copyable or is_nothrow_move_whatever, etc. But these are the
> same things a library can do.
> I see no compiler magic available here. Most compiler magic (in terms of
> checking classes) is now available to libraries.
>
> HOWEVER, the *system* could maybe do magic.
> For example, Transactional Memory would give us the ideal variant (I
> think).
>
> Or, in theory, messing with virtual memory addressing in some magical way
> - because the "C++ pointer" memory location of X really isn't the same as
> the physical memory location of X. But I suspect this would only be
> possible with page-sized objects (if at all).
>
> Or some magic I haven't thought of.
>
again, thanks for the feedback that was really interesting. i have no
experience with work a compiler does so that was a total shot in the dark
-- i just wanted to throw it out there for my own curiosity if nothing
else. i'm sure that if it could help somebody would have already mentioned
it.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c342ee8579e30521121343
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_ext=
ra"><div class=3D"gmail_quote"><span class=3D"">On Thu, Oct 1, 2015 at 5:13=
PM, Sam Kellett <span dir=3D"ltr"><<a href=3D"mailto:samkellett@gmail.c=
om" target=3D"_blank">samkellett@gmail.com</a>></span> wrote:<br><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><span><br><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div>I think Williams.Variant is pretty much as close to being (desi=
gn-wise) correct as C++ can get. If even that overhead is considered to be =
too much, I'm willing to accept an invalid-via-error state; not because=
I think it's right or good, but purely as a concession to memory/perfo=
rmance needs.<br><br>And yes, the last entries show how much I dislike your=
idea. As much as I've railed against it, I'd rather <i>lose never-=
empty</i> entirely than to use a never-empty type that is broken in the way=
you suggest. Where merely removing a default constructor's `noexcept` =
specification makes all your code using `variant`s of that type stop workin=
g.</div></blockquote><div><br></div></span><div>sorry if this has been ment=
ioned before -- there has been a huge amount of variant talk (just look at =
how many variant papers are going to kona!) and i think i've only seen =
relatively little... <br><br></div><div>but could it be acceptable to allow=
the user to select which type of variant behaviour they want via a variant=
_traits template parameter? ie. one that forces noexcept move of all types =
or one that has an empty state or one that double buffers or one that uses =
the heap, etc...<br><br></div></div></blockquote><div><br></div></span><div=
>If it wasn't ugly.=C2=A0 Even just buffering vs invalid would be nice.=
<br><br></div><div>However, in general the committee shies away from policy=
-based classes.<br></div>Part of the problem is that you want APIs that tak=
e one type, not a whole class of types.<br></div><div class=3D"gmail_quote"=
>ie a function that takes a shared_ptr<Foo> :<br><br>void doSomething=
(shared_ptr<Foo> foo) {<br></div><div class=3D"gmail_quote">... lots =
of code here...<br></div><div class=3D"gmail_quote">}<br><br>If shared_ptr =
had policies (for destruction, etc), then my function _probably_ needs to b=
ecome a template:<br><br></div><div class=3D"gmail_quote">template<typen=
ame Policy><br></div><div class=3D"gmail_quote">void doSomething(shared_=
ptr<Foo, Policy> foo) {<br></div><div class=3D"gmail_quote">...lots o=
f code here, now in the header ...<br></div><div class=3D"gmail_quote">}<br=
><br></div><div class=3D"gmail_quote">Not sure if the same applies to a pol=
icy-based variant, but that's the general criticism of policies.<br><br=
></div><div class=3D"gmail_quote">You _might_ be able to argue variant is d=
ifferent because _maybe_:<br></div><div class=3D"gmail_quote">A) many varia=
nts get used via typedefs, so you need not see the policy<br></div><div cla=
ss=3D"gmail_quote">B) many variant functions are already templates<br>?<br>=
</div></div></div></blockquote><div><br></div><div>thanks for the feedback.=
<br><br>ugly is true, but i think it could be avoidable at the user level. =
say something more akin to std::string than std::shared_ptr. so you would h=
ave a std::basic_variant and from there you have your variant types defined=
(ala wstring, u16string, etc...) -- i have no idea what you'd call the=
m though...<br><br></div><div>std::sbvariant, std::mvvariant, std::nevarian=
t... these names all suck bad, points if you can even guess which one is wh=
ich from my previous email..<br></div><div><br></div><div>but yeah, you'=
;d never really deal with the policy on a per-function basis, just like you=
rarely if ever do with strings.<br></div><div><br>=C2=A0</div><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 class=3D"gmail_extra"><div class=
=3D"gmail_quote"></div><br><div class=3D"gmail_quote"><span class=3D""><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div>and on mayb=
e another note entirely, would it be possible to use some compiler magic to=
get a perfect variant (ie single-buffer, any type, never-empty)? i've =
only seen talk of library implementations, but why not (if helpful) let the=
compiler do some work too?<br></div></div></blockquote><div><br></div></sp=
an><div>The compiler probably can't help you.=C2=A0 For variant<X,Y&=
gt; the goal is to destroy the old X, and _in the same place_ construct a Y=
..=C2=A0 If constructing the Y fails, what do you do?<br></div><div>*IF* the=
compiler knew that it could just memcpy X from a temporary and back into p=
lace, it could restore X.=C2=A0 But some classes have pointers to themselve=
s and other oddities such that an X here is not the same as an X there:<br>=
<br></div><div>class X {<br></div><div>=C2=A0=C2=A0=C2=A0 char blob[32];<br=
></div><div>=C2=A0=C2=A0=C2=A0 char * ptr;<br></div><div>=C2=A0=C2=A0=C2=A0=
X(const char * str) { <br></div><div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 if (int len =3D strlen(str) < 32) {<br></div><div>=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ptr =3D blob;<br></div>=
<div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } else {<br></div><div>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ptr =3D mal=
loc(len + 1);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br></div><div=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 strcpy(ptr, str);<br></div><div=
>=C2=A0=C2=A0=C2=A0 }<br></div><div>=C2=A0=C2=A0=C2=A0 ~X()<br>=C2=A0=C2=A0=
=C2=A0 {<br></div><div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 if (ptr !=3D blob) {<br></div><div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 free(ptr);<br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br>=C2=A0=C2=A0=C2=A0 }<br></div><div>};<b=
r></div><div>// ignore the bugs. I don't have an email compiler<br></di=
v><div><br></div><div>You can't memcpy the above (and expect the class =
not to crash in the destructor at least).<br><br></div><div>The only way th=
e compiler can know, is by checking things like is_trivially_copyable or is=
_nothrow_move_whatever, etc.=C2=A0 But these are the same things a library =
can do.<br></div><div>I see no compiler magic available here.=C2=A0 Most co=
mpiler magic (in terms of checking classes) is now available to libraries.<=
br><br></div><div>HOWEVER, the *system* could maybe do magic.<br></div><div=
>For example, Transactional Memory would give us the ideal variant (I think=
).<br><br></div><div>Or, in theory, messing with virtual memory addressing =
in some magical way - because the "C++ pointer" memory location o=
f X really isn't the same as the physical memory location of X.=C2=A0 B=
ut I suspect this would only be possible with page-sized objects (if at all=
).<br><br></div><div>Or some magic I haven't thought of.<span class=3D"=
HOEnZb"><font color=3D"#888888"><br></font></span></div></div></div></div><=
/blockquote><div><br></div><div>again, thanks for the feedback that was rea=
lly interesting. i have no experience with work a compiler does so that was=
a total shot in the dark -- i just wanted to throw it out there for my own=
curiosity if nothing else. i'm sure that if it could help somebody wou=
ld have already mentioned it.<br>=C2=A0<br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c342ee8579e30521121343--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 1 Oct 2015 16:52:33 -0500
Raw View
--001a1141dba0e0d1e505211212db
Content-Type: text/plain; charset=UTF-8
On 1 October 2015 at 16:13, Sam Kellett <samkellett@gmail.com> wrote:
> but could it be acceptable to allow the user to select which type of
> variant behaviour they want via a variant_traits template parameter?
>
No.
If you want different behavior, use a different name for your class
template.
Also, what happens when one part of your program wants variant<vector<T>,
deque<T>> to use double buffering and another part wants variant<vector,
deque> to have an invalid state?
And I'm not even sure if variant<vector<int>, deque<int>> is a user defined
type, as it isn't dependent on any user defined types.
Plus there are logistics problems; where do you put the traits
specialization so that everybody see it?
and on maybe another note entirely, would it be possible to use some
> compiler magic to get a perfect variant (ie single-buffer, any type,
> never-empty)? i've only seen talk of library implementations, but why not
> (if helpful) let the compiler do some work too?
>
Not as far as anyone has ever said.
The fundamental problem doesn't change: if operations may throw, what
state do you leave the variant in?
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1141dba0e0d1e505211212db
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 1 October 2015 at 16:13, Sam Kellett <span dir=3D"ltr">=
<<a href=3D"mailto:samkellett@gmail.com" target=3D"_blank">samkellett@gm=
ail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"g=
mail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>but could =
it be acceptable to allow the user to select which type of variant behaviou=
r they want via a variant_traits template parameter?</div></div></blockquot=
e><div><br></div><div>No.</div><div><br></div><div>If you want different be=
havior, use a different name for your class template.</div><div><br></div><=
div>Also, what happens when one part of your program wants variant<vecto=
r<T>, deque<T>> to use double buffering and another part wan=
ts variant<vector, deque> to have an invalid state?</div><div><br></d=
iv><div>And I'm not even sure if variant<vector<int>, deque<=
;int>> is a user defined type, as it isn't dependent on any user =
defined types.</div><div><br></div><div>Plus there are logistics problems; =
where do you put the traits specialization so that everybody see it?</div><=
div><br></div><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>and on m=
aybe another note entirely, would it be possible to use some compiler magic=
to get a perfect variant (ie single-buffer, any type, never-empty)? i'=
ve only seen talk of library implementations, but why not (if helpful) let =
the compiler do some work too?<br></div></div></blockquote><div><br></div><=
div>Not as far as anyone has ever said.</div><div><br></div><div>The fundam=
ental problem doesn't change: =C2=A0if operations may throw, what state=
do you leave the variant in?</div><div>=C2=A0--=C2=A0</div></div><div clas=
s=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a=
href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlor=
d.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1141dba0e0d1e505211212db--
.
Author: David Krauss <potswa@gmail.com>
Date: Fri, 2 Oct 2015 06:59:04 +0800
Raw View
> On 2015=E2=80=9310=E2=80=9302, at 12:36 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I'm not sure I see why it should be SFINAE friendly. What other `allocato=
r[_traits]::construct` overload could you possibly intend to call that woul=
d be a viable match were it not for the substitution error outside an immed=
iate context?
Usually when a constructor doesn=E2=80=99t work you want to remove it from =
the overload set. That=E2=80=99s what your implementation is trying to to d=
o, right?
> My point is that this new semantic construct ought to have a name. Someth=
ing by which people refer to the notion, instead of enumerating the rules b=
y which it is defined. Someone said this is `INVOKE` for constructors, I ho=
pe we don't repeat that mistake.
I conceived the technique; I didn=E2=80=99t prototype it or write the propo=
sal. You=E2=80=99re just as free as Ville to propose an interface.
Without wading back into this, I=E2=80=99ll just say that my records show t=
his path to be already well-trodden. I raised similar concerns when reviewi=
ng N4462. It=E2=80=99s up to your own initiative to rectify any perceived p=
roblem.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Thu, 1 Oct 2015 22:28:18 -0300
Raw View
On 10/1/2015 7:59 PM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9302, at 12:36 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>>
>> I'm not sure I see why it should be SFINAE friendly. What other `allocat=
or[_traits]::construct` overload could you possibly intend to call that wou=
ld be a viable match were it not for the substitution error outside an imme=
diate context?
>
> Usually when a constructor doesn=E2=80=99t work you want to remove it fro=
m the overload set. That=E2=80=99s what your implementation is trying to to=
do, right?
I would want the constructor not to introduce a hard error when there=20
isn't any, and I would want `allocator[_traits]::construct` not to=20
swallow a hard error when there is one. I would not be willing to=20
document my interface in terms of implementation details anyways.
Regardless, `allocator[_traits]::construct` does not apply to `variant`.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Fri, 2 Oct 2015 10:25:33 +0800
Raw View
--Apple-Mail=_F1B0A84F-942F-4ABD-953C-5FA7E1C0914B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9302, at 9:28 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I would want the constructor not to introduce a hard error when there isn=
't any, and I would want `allocator[_traits]::construct` not to swallow a h=
ard error when there is one.
What do you mean =E2=80=9Cswallow=E2=80=9D? You wouldn=E2=80=99t want alloc=
ator[_traits]::construct ever to have SFINAE? Why not?
I think that allocator_traits should supply a member is_constructible trait=
regardless, but errors on ODR-use are seldom helpful. To me, providing a s=
ignature without a backing definition is more like =E2=80=9Cswallowing an e=
rror.=E2=80=9D
Surely a dedicated std::construct function should provide SFINAE.
> I would not be willing to document my interface in terms of implementatio=
n details anyways.
>=20
> Regardless, `allocator[_traits]::construct` does not apply to `variant`.
In reviewing N4462, when pressed for a =E2=80=9Chard=E2=80=9D justification=
for std::construct, I gave std::allocator::construct being a customization=
point.
I=E2=80=99m not trying to wade into this now. Please do not interpret my su=
ggestions as disagreement with your opinions. I just want to mention a simp=
ler alternative to your suggested suite of traits templates. Your opinions =
on SFINAE are helpful, as long as they relate to semantics. But details lik=
e whether =E2=80=9Callocator=E2=80=9D appears in the name of the function a=
re less related.
--=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/.
--Apple-Mail=_F1B0A84F-942F-4ABD-953C-5FA7E1C0914B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9302, at 9:28 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"mai=
lto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:<=
/div><br class=3D"Apple-interchange-newline"><div class=3D"">I would want t=
he constructor not to introduce a hard error when there isn't any, and I wo=
uld want `allocator[_traits]::construct` not to swallow a hard error when t=
here is one. </div></blockquote><div><br class=3D""></div><div>What do you =
mean =E2=80=9Cswallow=E2=80=9D? You wouldn=E2=80=99t want <font face=3D"Cou=
rier" class=3D"">allocator[_traits]::construct</font> ever to have SFINAE? =
Why not?</div><div><br class=3D""></div><div>I think that <font face=3D"Cou=
rier" class=3D"">allocator_traits</font> should supply a member <font =
face=3D"Courier" class=3D"">is_constructible</font> trait regardless, =
but errors on ODR-use are seldom helpful. To me, providing a signature with=
out a backing definition is more like =E2=80=9Cswallowing an error.=E2=80=
=9D</div><div><br class=3D""></div><div>Surely a dedicated <font face=
=3D"Courier" class=3D"">std::construct</font> function should provide SFINA=
E.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""=
>I would not be willing to document my interface in terms of implementation=
details anyways.<br class=3D""><br class=3D"">Regardless, `allocator[_trai=
ts]::construct` does not apply to `variant`.<br class=3D""></div></blockquo=
te></div><br class=3D""><div class=3D"">In reviewing N4462, when pressed fo=
r a =E2=80=9Chard=E2=80=9D justification for <font face=3D"Courier" class=
=3D"">std::construct</font>, I gave <font face=3D"Courier" class=3D"">std::=
allocator::construct</font> being a customization point.</div><div class=3D=
""><br class=3D""></div><div class=3D"">I=E2=80=99m not trying to wade into=
this now. Please do not interpret my suggestions as disagreement with your=
opinions. I just want to mention a simpler alternative to your suggested s=
uite of traits templates. Your opinions on SFINAE are helpful, as long as t=
hey relate to semantics. But details like whether =E2=80=9C<font face=3D"Co=
urier" class=3D"">allocator</font>=E2=80=9D appears in the name of the func=
tion are less related.</div><div class=3D""><br class=3D""></div></body></h=
tml>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_F1B0A84F-942F-4ABD-953C-5FA7E1C0914B--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Fri, 2 Oct 2015 11:02:10 -0300
Raw View
On 10/1/2015 11:25 PM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9302, at 9:28 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> I would want the constructor not to introduce a hard error when there
>> isn't any, and I would want `allocator[_traits]::construct` not to
>> swallow a hard error when there is one.
>
> What do you mean =E2=80=9Cswallow=E2=80=9D? You wouldn=E2=80=99t want
> allocator[_traits]::construct ever to have SFINAE? Why not?
I just don't see the point, there's no other potential candidate one=20
might want to be calling instead. If I fail to meet the requirements=20
when I call it I expect a hard error, hopefully a clear one (like "the=20
selected constructor X is private"). If I do not want a hard error I=20
will make sure not to violate the requirements.
I suspect the point of making `construct` SFINAE-friendly is to be able=20
to define its requirements as whatever is well-formed. That sounds=20
backwards to me.
> I think that allocator_traits should supply a member
> is_constructible trait regardless, but errors on ODR-use are seldom
> helpful. To me, providing a signature without a backing definition is
> more like =E2=80=9Cswallowing an error.=E2=80=9D
I could see the point of such a trait.
> Surely a dedicated std::construct function should provide SFINAE.
A free `std::construct` function would participate in an open-ended=20
overload set, for me it would depend entirely on what its declaration=20
is. For instance, `experimental::apply` is not SFINAE-friendly and puts=20
the entire body in the definition, resulting in a risk to unqualified=20
`apply` calls. I'm assuming `std::construct` would simply return a `T`,=20
so it would not interfere with other candidates. I'd welcome a hard=20
error if and only if it's triggered when overload resolution resolved=20
that's the one you want to call, since you would have violated its=20
preconditions.
>> I would not be willing to document my interface in terms of
>> implementation details anyways.
>>
>> Regardless, `allocator[_traits]::construct` does not apply to `variant`.
>
> In reviewing N4462, when pressed for a =E2=80=9Chard=E2=80=9D justificati=
on for
> std::construct, I gave std::allocator::construct being a customization
> point.
>
> I=E2=80=99m not trying to wade into this now. Please do not interpret my
> suggestions as disagreement with your opinions. I just want to mention a
> simpler alternative to your suggested suite of traits templates.
Don't focus on the traits so much, they are not the basic issue here;=20
give me a name to use when documenting my semantics instead. The traits=20
will follow because I would strive for my implementation to be=20
idiomatic, reading either of
- static_assert(is_fancy_constructible<T, Args...>{});
- enable_if_t<is_fancy_constructible<T, Args...>{}>
- requires is_fancy_constructible<T, Args...>
as appropriate.
> Your
> opinions on SFINAE are helpful, as long as they relate to semantics. But
> details like whether =E2=80=9Callocator=E2=80=9D appears in the name of t=
he function are
> less related.
The name is indeed irrelevant. An `std::construct` with the same=20
interface of `allocator[_traits]::construct` would be just as useless=20
for types with embedded storage like `variant` and `tuple`. An=20
`std::construct` that simply returns `T` would not be an option for=20
types with embedded storage either, as it would inject a move.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 2 Oct 2015 07:51:38 -0700 (PDT)
Raw View
------=_Part_204_800329508.1443797498673
Content-Type: multipart/alternative;
boundary="----=_Part_205_1901523367.1443797498673"
------=_Part_205_1901523367.1443797498673
Content-Type: text/plain; charset=UTF-8
On Thursday, October 1, 2015 at 5:13:31 PM UTC-4, Sam Kellett wrote:
>
>
> I think Williams.Variant is pretty much as close to being (design-wise)
>> correct as C++ can get. If even that overhead is considered to be too much,
>> I'm willing to accept an invalid-via-error state; not because I think it's
>> right or good, but purely as a concession to memory/performance needs.
>>
>> And yes, the last entries show how much I dislike your idea. As much as
>> I've railed against it, I'd rather *lose never-empty* entirely than to
>> use a never-empty type that is broken in the way you suggest. Where merely
>> removing a default constructor's `noexcept` specification makes all your
>> code using `variant`s of that type stop working.
>>
>
> sorry if this has been mentioned before -- there has been a huge amount of
> variant talk (just look at how many variant papers are going to kona!) and
> i think i've only seen relatively little...
>
> but could it be acceptable to allow the user to select which type of
> variant behaviour they want via a variant_traits template parameter? ie.
> one that forces noexcept move of all types or one that has an empty state
> or one that double buffers or one that uses the heap, etc...
>
The issue (beyond what others have said) with a policy-based variant is
that the policies actually mutate the *interface*. A perfect never-empty
variant would not have or need `valid()` or `operator bool()` method. Yet
even if you SFINAE such functions away based on policies, they would still
be part of the documentation. Also, the behavior of the default constructor
would be very different based on policies.
Overall, I don't think it's a bad idea to spell two functionally different
types the same way. Remember `vector<bool>`.
A two-class solution could be feasible, but then you have another fight:
*which* two classes? One perfect never-empty (with exception guarantee
forwarding, ala Williams.Variant) and one that's a typical emptyable
variant? What about someone who would wants never-empty, yet needs N4542
solution due to memory/runtime performance?
If your two classes are perfect never-empty and N4542, then all the people
who want empty-able variants will be upset that you have made two separate
classes without taking them into account.
> and on maybe another note entirely, would it be possible to use some
> compiler magic to get a perfect variant (ie single-buffer, any type,
> never-empty)? i've only seen talk of library implementations, but why not
> (if helpful) let the compiler do some work too?
>
I don't think it's possible even for the compiler.
The fundamental problem is this: the variant stores a type X. You're
performing a copy/move/emplace operation with a new type Y. If that
operation fails, how can you get the variant back into some reasonable
state (let alone the original state), for any typelist?
If one of the types in the typelist has a non-throwing default constructor,
then you don't even need compiler magic to solve it. But if none of them
do, then how could the compiler resolve it? What magic can it impose?
The compiler cannot *make* a throwing move type into a nothrow move type.
Nor can it make a non-trivially copyable type trivially copyable. Nor can
it undo the result of a destructor call. And it's not legal to simply
memcpy the object elsewhere before destruction, since the destructor will
have a different `this` pointer than it should.
Maybe there is some solution a compiler could create. But I'm not sure how
it would be possible without breaking some currently valid C++ code.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_205_1901523367.1443797498673
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, October 1, 2015 at 5:13:31 PM UTC-4, Sam Kellett wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div>I think Williams.Variant is pretty much as close to bei=
ng (design-wise) correct as C++ can get. If even that overhead is considere=
d to be too much, I'm willing to accept an invalid-via-error state; not=
because I think it's right or good, but purely as a concession to memo=
ry/performance needs.<br><br>And yes, the last entries show how much I disl=
ike your idea. As much as I've railed against it, I'd rather <i>los=
e never-empty</i> entirely than to use a never-empty type that is broken in=
the way you suggest. Where merely removing a default constructor's `no=
except` specification makes all your code using `variant`s of that type sto=
p working.</div></blockquote><div><br></div><div>sorry if this has been men=
tioned before -- there has been a huge amount of variant talk (just look at=
how many variant papers are going to kona!) and i think i've only seen=
relatively little... <br><br></div><div>but could it be acceptable to allo=
w the user to select which type of variant behaviour they want via a varian=
t_traits template parameter? ie. one that forces noexcept move of all types=
or one that has an empty state or one that double buffers or one that uses=
the heap, etc...<br></div></div></blockquote><div><br>The issue (beyond wh=
at others have said) with a policy-based variant is that the policies actua=
lly mutate the <i>interface</i>. A perfect never-empty variant would not ha=
ve or need `valid()` or `operator bool()` method. Yet even if you SFINAE su=
ch functions away based on policies, they would still be part of the docume=
ntation. Also, the behavior of the default constructor would be very differ=
ent based on policies.<br><br>Overall, I don't think it's a bad ide=
a to spell two functionally different types the same way. Remember `vector&=
lt;bool>`.<br><br>A two-class solution could be feasible, but then you h=
ave another fight: <i>which</i> two classes? One perfect never-empty (with =
exception guarantee forwarding, ala Williams.Variant) and one that's a =
typical emptyable variant? What about someone who would wants never-empty, =
yet needs N4542 solution due to memory/runtime performance?<br><br>If your =
two classes are perfect never-empty and N4542, then all the people who want=
empty-able variants will be upset that you have made two separate classes =
without taking them into account.<br>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><div></div><div>and on maybe another no=
te entirely, would it be possible to use some compiler magic to get a perfe=
ct variant (ie single-buffer, any type, never-empty)? i've only seen ta=
lk of library implementations, but why not (if helpful) let the compiler do=
some work too?<br></div></div></blockquote><div><br>I don't think it&#=
39;s possible even for the compiler.<br><br>The fundamental problem is this=
: the variant stores a type X. You're performing a copy/move/emplace op=
eration with a new type Y. If that operation fails, how can you get the var=
iant back into some reasonable state (let alone the original state), for an=
y typelist?<br><br>If one of the types in the typelist has a non-throwing d=
efault constructor, then you don't even need compiler magic to solve it=
.. But if none of them do, then how could the compiler resolve it? What magi=
c can it impose?<br><br>The compiler cannot <i>make</i> a throwing move typ=
e into a nothrow move type. Nor can it make a non-trivially copyable type t=
rivially copyable. Nor can it undo the result of a destructor call. And it&=
#39;s not legal to simply memcpy the object elsewhere before destruction, s=
ince the destructor will have a different `this` pointer than it should.<br=
><br>Maybe there is some solution a compiler could create. But I'm not =
sure how it would be possible without breaking some currently valid C++ cod=
e.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_205_1901523367.1443797498673--
------=_Part_204_800329508.1443797498673--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 2 Oct 2015 07:58:41 -0700 (PDT)
Raw View
------=_Part_882_1110217892.1443797921844
Content-Type: multipart/alternative;
boundary="----=_Part_883_1941602527.1443797921844"
------=_Part_883_1941602527.1443797921844
Content-Type: text/plain; charset=UTF-8
On Friday, October 2, 2015 at 10:51:39 AM UTC-4, Nicol Bolas wrote:
>
> Overall, I don't think it's a bad idea to spell two functionally different
> types the same way. Remember `vector<bool>`.
>
I meant "I don't think it's a *good* idea ..."
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_883_1941602527.1443797921844
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, October 2, 2015 at 10:51:39 AM UTC-4, N=
icol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>Overall,=
I don't think it's a bad idea to spell two functionally different =
types the same way. Remember `vector<bool>`.<br></div></blockquote><d=
iv><br>I meant "I don't think it's a <b>good</b> idea ..."=
;</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_883_1941602527.1443797921844--
------=_Part_882_1110217892.1443797921844--
.
Author: David Krauss <potswa@gmail.com>
Date: Fri, 2 Oct 2015 23:47:25 +0800
Raw View
--Apple-Mail=_F77941AC-62CD-4D02-8A1D-4E90394C2CDA
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9302, at 10:02 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I just don't see the point, there's no other potential candidate one migh=
t want to be calling instead. If I fail to meet the requirements when I cal=
l it I expect a hard error, hopefully a clear one (like "the selected const=
ructor X is private"). If I do not want a hard error I will make sure not t=
o violate the requirements.
Allocator::constructor wraps a class=E2=80=99 own constructors, so you may =
want SFINAE on it whenever the constructors are collectively providing SFIN=
AE. The outcome might be ignoring a wrapper constructor and the conversion =
it enables, rather than selecting a different constructor in the same wrapp=
er.
> I suspect the point of making `construct` SFINAE-friendly is to be able t=
o define its requirements as whatever is well-formed. That sounds backwards=
to me.
No, the point is to add capabilities to wrappers. The wrapper W pretends to=
be a T but actually it allocates a T using an A. Now A can affect whether =
W implicitly converts from U. Maybe T(U) doesn=E2=80=99t exist but T(U,A) d=
oes. Only A knows the correct way to call T::T, and without that, the best =
W can do is convert from everything.
>> Surely a dedicated std::construct function should provide SFINAE.
>=20
> A free `std::construct` function would participate in an open-ended overl=
oad set, for me it would depend entirely on what its declaration is. For in=
stance, `experimental::apply` is not SFINAE-friendly and puts the entire bo=
dy in the definition, resulting in a risk to unqualified `apply` calls. I'm=
assuming `std::construct` would simply return a `T`, so it would not inter=
fere with other candidates.
I think it would take an uninitialized T*, but guaranteed copy elision coul=
d change that. I=E2=80=99m not sure how you=E2=80=99re figuring risk or wha=
t you mean by =E2=80=9Copen-ended,=E2=80=9D but of course ADL and unqualifi=
ed calls can happen even without such a parameter. I don=E2=80=99t think st=
d::construct should be a customization point; constructors are already cust=
omizable.
> I'd welcome a hard error if and only if it's triggered when overload reso=
lution resolved that's the one you want to call, since you would have viola=
ted its preconditions.
If the job of std::construct is to choose between direct-initialization and=
direct-list-initialization, should it SFINAE when both of those initializa=
tions are ill-formed in the context of its own declaration?
I don=E2=80=99t think it has many preconditions. Accessibility is SFINAE=E2=
=80=99d, so there=E2=80=99s no way to make a hard error on inaccessible con=
structors.
> Don't focus on the traits so much, they are not the basic issue here; giv=
e me a name to use when documenting my semantics instead. The traits will f=
ollow because I would strive for my implementation to be idiomatic, reading=
either of
>=20
> - static_assert(is_fancy_constructible<T, Args...>{});
> - enable_if_t<is_fancy_constructible<T, Args...>{}>
> - requires is_fancy_constructible<T, Args...>
>=20
> as appropriate.
Hmm, idioms are nice, and I suppose someone will want such a static_assert.
> The name is indeed irrelevant. An `std::construct` with the same interfac=
e of `allocator[_traits]::construct` would be just as useless for types wit=
h embedded storage like `variant` and `tuple`. An `std::construct` that sim=
ply returns `T` would not be an option for types with embedded storage eith=
er, as it would inject a move.
There=E2=80=99s a little misunderstanding. I was talking about SFINAE, not =
actually calling the function.
As for calling it, guaranteed copy elision should help.
--=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/.
--Apple-Mail=_F77941AC-62CD-4D02-8A1D-4E90394C2CDA
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9302, at 10:02 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"ma=
ilto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:=
</div><br class=3D"Apple-interchange-newline"><div class=3D"">I just don't =
see the point, there's no other potential candidate one might want to be ca=
lling instead. If I fail to meet the requirements when I call it I expect a=
hard error, hopefully a clear one (like "the selected constructor X is pri=
vate"). If I do not want a hard error I will make sure not to violate the r=
equirements.<br class=3D""></div></blockquote><div><br class=3D""></div><di=
v><font face=3D"Courier" class=3D"">Allocator::constructor</font> wraps a c=
lass=E2=80=99 own constructors, so you may want SFINAE on it whenever the c=
onstructors are collectively providing SFINAE. The outcome might be ignorin=
g a wrapper constructor and the conversion it enables, rather than selectin=
g a different constructor in the same wrapper.</div><br class=3D""><blockqu=
ote type=3D"cite" class=3D""><div class=3D"">I suspect the point of making =
`construct` SFINAE-friendly is to be able to define its requirements as wha=
tever is well-formed. That sounds backwards to me.<br class=3D""></div></bl=
ockquote><div><br class=3D""></div><div>No, the point is to add capabilitie=
s to wrappers. The wrapper <font face=3D"Courier" class=3D"">W</font> prete=
nds to be a <font face=3D"Courier" class=3D"">T</font> but actually it allo=
cates a <span style=3D"font-family: Courier;" class=3D"">T</span> =
;using an <font face=3D"Courier" class=3D"">A</font>. Now <span style=
=3D"font-family: Courier;" class=3D"">A</span> can affect whether =
;<span style=3D"font-family: Courier;" class=3D"">W</span> implicitly =
converts from <font face=3D"Courier" class=3D"">U</font>. Maybe <span =
style=3D"font-family: Courier;" class=3D"">T(U)</span> doesn=E2=80=99t=
exist but <span style=3D"font-family: Courier;" class=3D"">T(U,A)</sp=
an> does. Only <span style=3D"font-family: Courier;" class=3D"">A=
</span> knows the correct way to call <font face=3D"Courier" class=3D"=
">T::T</font>, and without that, the best <span style=3D"font-family: =
Courier;" class=3D"">W</span> can do is convert from everything.</div>=
<br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><blockq=
uote type=3D"cite" class=3D"">Surely a dedicated std::construct function sh=
ould provide SFINAE.</blockquote><br class=3D"">A free `std::construct` fun=
ction would participate in an open-ended overload set, for me it would depe=
nd entirely on what its declaration is. For instance, `experimental::apply`=
is not SFINAE-friendly and puts the entire body in the definition, resulti=
ng in a risk to unqualified `apply` calls. I'm assuming `std::construct` wo=
uld simply return a `T`, so it would not interfere with other candidates.</=
div></blockquote><div><br class=3D""></div><div>I think it would take an un=
initialized <font face=3D"Courier" class=3D"">T*</font>, but guaranteed cop=
y elision could change that. I=E2=80=99m not sure how you=E2=80=99re figuri=
ng risk or what you mean by =E2=80=9Copen-ended,=E2=80=9D but of course ADL=
and unqualified calls can happen even without such a parameter. I don=E2=
=80=99t think <font face=3D"Courier" class=3D"">std::construct</font> shoul=
d be a customization point; constructors are already customizable.</div><br=
class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""> I'd welco=
me a hard error if and only if it's triggered when overload resolution reso=
lved that's the one you want to call, since you would have violated its pre=
conditions.<br class=3D""></div></blockquote><div><br class=3D""></div><div=
>If the job of <font face=3D"Courier" class=3D"">std::construct</font> is t=
o choose between direct-initialization and direct-list-initialization, shou=
ld it SFINAE when both of those initializations are ill-formed in the conte=
xt of its own declaration?</div><div><br class=3D""></div><div>I don=E2=80=
=99t think it has many preconditions. Accessibility is SFINAE=E2=80=99d, so=
there=E2=80=99s no way to make a hard error on inaccessible constructors.<=
/div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">Do=
n't focus on the traits so much, they are not the basic issue here; give me=
a name to use when documenting my semantics instead. The traits will follo=
w because I would strive for my implementation to be idiomatic, reading eit=
her of<br class=3D""><br class=3D"">- static_assert(is_fancy_constructible&=
lt;T, Args...>{});<br class=3D"">- enable_if_t<is_fancy_constructible=
<T, Args...>{}><br class=3D"">- requires is_fancy_constructible<=
;T, Args...><br class=3D""><br class=3D"">as appropriate.<br class=3D"">=
</div></blockquote><div><br class=3D""></div><div>Hmm, idioms are nice, and=
I suppose someone will want such a <font face=3D"Courier" class=3D"">stati=
c_assert</font>.</div><br class=3D""><blockquote type=3D"cite" class=3D""><=
div class=3D"">The name is indeed irrelevant. An `std::construct` with the =
same interface of `allocator[_traits]::construct` would be just as useless =
for types with embedded storage like `variant` and `tuple`. An `std::constr=
uct` that simply returns `T` would not be an option for types with embedded=
storage either, as it would inject a move.<br class=3D""></div></blockquot=
e></div><br class=3D""><div class=3D"">There=E2=80=99s a little misundersta=
nding. I was talking about SFINAE, not actually calling the function.</div>=
<div class=3D""><br class=3D""></div><div class=3D"">As for calling it, gua=
ranteed copy elision should help.</div><div class=3D""><br class=3D""></div=
></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_F77941AC-62CD-4D02-8A1D-4E90394C2CDA--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Fri, 2 Oct 2015 13:44:17 -0300
Raw View
On 10/2/2015 12:47 PM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9302, at 10:02 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> I just don't see the point, there's no other potential candidate one
>> might want to be calling instead. If I fail to meet the requirements
>> when I call it I expect a hard error, hopefully a clear one (like "the
>> selected constructor X is private"). If I do not want a hard error I
>> will make sure not to violate the requirements.
>
> Allocator::constructor wraps a class=E2=80=99 own constructors, so you ma=
y want
> SFINAE on it whenever the constructors are collectively providing
> SFINAE. The outcome might be ignoring a wrapper constructor and the
> conversion it enables, rather than selecting a different constructor in
> the same wrapper.
I am not convinced this is the Allocator's job, but the wrapper's. When=20
you call `Allocator::construct` you want to construct something, if it=20
cannot be constructed then it's a bug. When you call the wrapper's=20
constructor, it's trying to be transparent, if it cannot be constructed=20
then it does not exist.
>> I suspect the point of making `construct` SFINAE-friendly is to be
>> able to define its requirements as whatever is well-formed. That
>> sounds backwards to me.
>
> No, the point is to add capabilities to wrappers. The wrapper W pretends
> to be a T but actually it allocates a T using an A. Now A can affect
> whether W implicitly converts from U. Maybe T(U) doesn=E2=80=99t exist bu=
t
> T(U,A) does. Only A knows the correct way to call T::T, and without
> that, the best W can do is convert from everything.
Could you just show me how would W document its semantics?
>>> Surely a dedicated std::construct function should provide SFINAE.
>>
>> A free `std::construct` function would participate in an open-ended
>> overload set, for me it would depend entirely on what its declaration
>> is. For instance, `experimental::apply` is not SFINAE-friendly and
>> puts the entire body in the definition, resulting in a risk to
>> unqualified `apply` calls. I'm assuming `std::construct` would simply
>> return a `T`, so it would not interfere with other candidates.
>
> I think it would take an uninitialized T*, but guaranteed copy elision
> could change that. I=E2=80=99m not sure how you=E2=80=99re figuring risk =
or what you
> mean by =E2=80=9Copen-ended,=E2=80=9D but of course ADL and unqualified c=
alls can happen
> even without such a parameter. I don=E2=80=99t think std::construct shoul=
d be a
> customization point; constructors are already customizable.
I chose to assume `std::construct` would offer a different interface to=20
cover more ground.
The overload candidate set for `Allocator::construct` is entirely=20
defined by `Allocator`; the overload candidate set for `std::construct`=20
is open, anyone can add overloads to that set, and `std::construct`=20
should play nicely with them. How much template instantiation is=20
necessary during overload resolution is implementation defined, so one=20
has to assume that every declaration in the candidate set will be=20
instantiated. If any of those instantiations causes a hard error, it=20
will get in the way of the user attempt to call a completely unrelated=20
function that happens to share a name. That's the risk I'm referring to,=20
which would not exist for `std::construct` as any declaration=20
instantiation would be well-formed.
I do not think `std::construct` should be a customization point either.
>> I'd welcome a hard error if and only if it's triggered when overload
>> resolution resolved that's the one you want to call, since you would
>> have violated its preconditions.
>
> If the job of std::construct is to choose between direct-initialization
> and direct-list-initialization, should it SFINAE when both of those
> initializations are ill-formed in the context of its own declaration?
That would depend on how you choose to define such a `std::construct`. I=20
would consider a request to construct something that cannot be=20
constructed a bug, so I would define it so that it is a hard error.
>> The name is indeed irrelevant. An `std::construct` with the same
>> interface of `allocator[_traits]::construct` would be just as useless
>> for types with embedded storage like `variant` and `tuple`. An
>> `std::construct` that simply returns `T` would not be an option for
>> types with embedded storage either, as it would inject a move.
>
> There=E2=80=99s a little misunderstanding. I was talking about SFINAE, no=
t
> actually calling the function.
>
> As for calling it, guaranteed copy elision should help.
I'm not sure this clears the misunderstanding. I was trying to say that=20
these solutions cannot be consumed by `variant` and other types with=20
embedded storage. Guaranteed copy elision would definitively help.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Sat, 3 Oct 2015 12:08:55 +0800
Raw View
--Apple-Mail=_7C45123A-92F1-4803-99DD-83D525BC70DB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9303, at 12:44 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I am not convinced this is the Allocator's job, but the wrapper's. When y=
ou call `Allocator::construct` you want to construct something, if it canno=
t be constructed then it's a bug. When you call the wrapper's constructor, =
it's trying to be transparent, if it cannot be constructed then it does not=
exist.
The wrapped type may be written specifically against the allocator. Because=
of rebind, an allocator should be able to handle any unexpected node type.=
But a contained type may be finicky about what sort of allocator it needs,=
or arbitrary about what allocation/construction policies it supports. The =
wrapper doesn=E2=80=99t have much say in the matter.
> Could you just show me how would W document its semantics?
W<T,A>::W(Args...) would require that A can construct T, specifically that =
allocator_traits<A>::construct<T>(Args ...) is a well-formed expression, ot=
herwise SFINAE. (Or, take it in terms of an invented allocator_traits::is_c=
onstructible.) It=E2=80=99s just a natural extension of SFINAE on is_constr=
uctible to allocators=E2=80=A6 is_constructible is inaccurate; it provides =
false positives and false negatives when the allocator changes the construc=
tor argument list.
> I chose to assume `std::construct` would offer a different interface to c=
over more ground.
>=20
> The overload candidate set for `Allocator::construct` is entirely defined=
by `Allocator`; the overload candidate set for `std::construct` is open, a=
nyone can add overloads to that set, and `std::construct` should play nicel=
y with them.
I don=E2=80=99t follow. You say std::construct shouldn=E2=80=99t be a custo=
mization point; to me that means not to bless ADL. How else can a user add =
an overload?
> How much template instantiation is necessary during overload resolution i=
s implementation defined, so one has to assume that every declaration in th=
e candidate set will be instantiated. If any of those instantiations causes=
a hard error, it will get in the way of the user attempt to call a complet=
ely unrelated function that happens to share a name. That's the risk I'm re=
ferring to, which would not exist for `std::construct` as any declaration i=
nstantiation would be well-formed.
ADL propagates brittleness. But if we don=E2=80=99t open that can of worms,=
std::construct is just the same as std::allocator::construct, i.e. closed =
except for explicit specialization.
The standard library should be (or should have been) smarter about preventi=
ng ADL and requiring qualification, e.g. by defining functions in an unspec=
ified namespace and importing them into std:: by using-declaration. That=E2=
=80=99s just a global issue and not particularly connected to construct. I =
feel like I=E2=80=99m fundamentally misunderstanding you.
> I do not think `std::construct` should be a customization point either.
>=20
>> If the job of std::construct is to choose between direct-initialization
>> and direct-list-initialization, should it SFINAE when both of those
>> initializations are ill-formed in the context of its own declaration?
>=20
> That would depend on how you choose to define such a `std::construct`. I =
would consider a request to construct something that cannot be constructed =
a bug, so I would define it so that it is a hard error.
There exists a Platonic ideal that all requirements are specified by enable=
_if or requires clauses, and no other SFINAE happens. But SFINAE was invent=
ed to allow requirements to be implicit, because that is the common case. I=
don=E2=80=99t see how calling std::construct with invalid parameter types =
is any more a =E2=80=9Crequest=E2=80=9D than any other overloaded function =
call.
>> There=E2=80=99s a little misunderstanding. I was talking about SFINAE, n=
ot
>> actually calling the function.
>>=20
>> As for calling it, guaranteed copy elision should help.
>=20
> I'm not sure this clears the misunderstanding. I was trying to say that t=
hese solutions cannot be consumed by `variant` and other types with embedde=
d storage. Guaranteed copy elision would definitively help.
You can use std::construct for SFINAE but not call it.
template< typename value_type >
template< typename args ...
, std::enable_if_t< ! std::is_constructible< value_type, args ... >::va=
lue > * // No direct-initialization.
, decltype( std::construct< T >( args ... ) ) * // But flexible-initial=
ization works. (Does not ODR-use std::construct.)
>
wrapper< value_type >::wrapper( args ... a )
: value{ a ... } // Deduce that brace-initialization is right.
{}
--=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/.
--Apple-Mail=_7C45123A-92F1-4803-99DD-83D525BC70DB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9303, at 12:44 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"ma=
ilto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:=
</div><br class=3D"Apple-interchange-newline"><div class=3D"">I am not conv=
inced this is the Allocator's job, but the wrapper's. When you call `Alloca=
tor::construct` you want to construct something, if it cannot be constructe=
d then it's a bug. When you call the wrapper's constructor, it's trying to =
be transparent, if it cannot be constructed then it does not exist.<br clas=
s=3D""></div></blockquote><div><br class=3D""></div><div>The wrapped type m=
ay be written specifically against the allocator. Because of <font face=3D"=
Courier" class=3D"">rebind</font>, an allocator should be able to handle an=
y unexpected node type. But a contained type may be finicky about what sort=
of allocator it needs, or arbitrary about what allocation/construction pol=
icies it supports. The wrapper doesn=E2=80=99t have much say in the matter.=
</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">C=
ould you just show me how would W document its semantics?<br class=3D""></d=
iv></blockquote><div><br class=3D""></div><div><font face=3D"Courier" class=
=3D"">W<T,A>::W(Args...)</font> would require that <font face=3D"Cour=
ier" class=3D"">A</font> can construct <font face=3D"Courier" class=3D"">T<=
/font>, specifically that <font face=3D"Courier" class=3D"">allocator_trait=
s<A>::construct<T>(Args ...)</font> is a well-formed expression=
, otherwise SFINAE. (Or, take it in terms of an invented <font face=3D"Cour=
ier" class=3D"">allocator_traits::is_constructible</font>.) It=E2=80=99s ju=
st a natural extension of SFINAE on <font face=3D"Courier" class=3D"">is_co=
nstructible</font> to allocators=E2=80=A6 <span style=3D"font-family: =
Courier;" class=3D"">is_constructible</span> is inaccurate; it provide=
s false positives and false negatives when the allocator changes the constr=
uctor argument list.</div><br class=3D""><blockquote type=3D"cite" class=3D=
""><div class=3D"">I chose to assume `std::construct` would offer a differe=
nt interface to cover more ground.<br class=3D""><br class=3D"">The overloa=
d candidate set for `Allocator::construct` is entirely defined by `Allocato=
r`; the overload candidate set for `std::construct` is open, anyone can add=
overloads to that set, and `std::construct` should play nicely with them. =
</div></blockquote><div><br class=3D""></div><div>I don=E2=80=99t follow. Y=
ou say <font face=3D"Courier" class=3D"">std::construct</font> shouldn=
=E2=80=99t be a customization point; to me that means not to bless ADL. How=
else can a user add an overload?</div><br class=3D""><blockquote type=3D"c=
ite" class=3D""><div class=3D"">How much template instantiation is necessar=
y during overload resolution is implementation defined, so one has to assum=
e that every declaration in the candidate set will be instantiated. If any =
of those instantiations causes a hard error, it will get in the way of the =
user attempt to call a completely unrelated function that happens to share =
a name. That's the risk I'm referring to, which would not exist for `std::c=
onstruct` as any declaration instantiation would be well-formed.<br class=
=3D""></div></blockquote><div><br class=3D""></div><div>ADL propagates brit=
tleness. But if we don=E2=80=99t open that can of worms, <font face=3D"Cour=
ier" class=3D"">std::construct</font> is just the same as <font face=
=3D"Courier" class=3D"">std::allocator::construct</font>, i.e. closed excep=
t for explicit specialization.</div><div><br class=3D""></div><div>The stan=
dard library should be (or should have been) smarter about preventing ADL a=
nd requiring qualification, e.g. by defining functions in an unspecified na=
mespace and importing them into <font face=3D"Courier" class=3D"">std::</fo=
nt> by using-declaration. That=E2=80=99s just a global issue and not partic=
ularly connected to <font face=3D"Courier" class=3D"">construct</font>. I f=
eel like I=E2=80=99m fundamentally misunderstanding you.</div><br class=3D"=
"><blockquote type=3D"cite" class=3D""><div class=3D"">I do not think `std:=
:construct` should be a customization point either.<br class=3D""><br class=
=3D""><blockquote type=3D"cite" class=3D"">If the job of std::construct is =
to choose between direct-initialization<br class=3D"">and direct-list-initi=
alization, should it SFINAE when both of those<br class=3D"">initialization=
s are ill-formed in the context of its own declaration?<br class=3D""></blo=
ckquote><br class=3D"">That would depend on how you choose to define such a=
`std::construct`. I would consider a request to construct something that c=
annot be constructed a bug, so I would define it so that it is a hard error=
..<br class=3D""></div></blockquote><div><br class=3D""></div><div>There exi=
sts a Platonic ideal that all requirements are specified by <font face=3D"C=
ourier" class=3D"">enable_if</font> or <font face=3D"Courier" class=3D"">re=
quires</font> clauses, and no other SFINAE happens. But SFINAE was invented=
to allow requirements to be implicit, because that is the common case. I d=
on=E2=80=99t see how calling <font face=3D"Courier" class=3D"">std::constru=
ct</font> with invalid parameter types is any more a =E2=80=9Crequest=E2=80=
=9D than any other overloaded function call.</div><br class=3D""><blockquot=
e type=3D"cite" class=3D""><div class=3D""><blockquote type=3D"cite" class=
=3D"">There=E2=80=99s a little misunderstanding. I was talking about SFINAE=
, not<br class=3D"">actually calling the function.<br class=3D""><br class=
=3D"">As for calling it, guaranteed copy elision should help.<br class=3D""=
></blockquote><br class=3D"">I'm not sure this clears the misunderstanding.=
I was trying to say that these solutions cannot be consumed by `variant` a=
nd other types with embedded storage. Guaranteed copy elision would definit=
ively help.<br class=3D""></div></blockquote></div><br class=3D""><div clas=
s=3D"">You can use <font face=3D"Courier" class=3D"">std::construct</font> =
for SFINAE but not call it.</div><div class=3D""><br class=3D""></div><div =
class=3D""><font face=3D"Courier" class=3D"">template< typename value_ty=
pe ></font></div><div class=3D""><font face=3D"Courier" class=3D"">templ=
ate< typename args ...</font></div><div class=3D""><font face=3D"Courier=
" class=3D""> , std::enable_if_t< </font><span style=
=3D"font-family: Courier;" class=3D"">! std::is_constructible< value_typ=
e, args ... >::value > * // No direct-initialization.</span></div><di=
v class=3D""><span style=3D"font-family: Courier;" class=3D""> =
, </span><span style=3D"font-family: Courier;" class=3D"">decltype( s=
td::construct< T >( args ... ) )</span><span style=3D"font-family: Co=
urier;" class=3D""> * // But flexible-initialization works. (Does not =
ODR-use std::construct.)</span></div><div class=3D""><font face=3D"Courier"=
class=3D"">></font></div><div class=3D""><font face=3D"Courier" class=
=3D"">wrapper< value_type >::wrapper( args ... a )</font></div><=
div class=3D""><font face=3D"Courier" class=3D""> : value{ a .=
... } // Deduce that brace-initialization is right.</font></div><div class=
=3D""><font face=3D"Courier" class=3D""> {}</font></div><div c=
lass=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_7C45123A-92F1-4803-99DD-83D525BC70DB--
.
Author: David Krauss <potswa@gmail.com>
Date: Sat, 3 Oct 2015 15:54:22 +0800
Raw View
--Apple-Mail=_2E6B3721-F707-4FF0-8B28-B1547347CE31
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9303, at 12:44 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I am not convinced this is the Allocator's job, but the wrapper's. When y=
ou call `Allocator::construct` you want to construct something, if it canno=
t be constructed then it's a bug. When you call the wrapper's constructor, =
it's trying to be transparent, if it cannot be constructed then it does not=
exist.
By the way, allocator support isn=E2=80=99t limited to heap-based container=
s. std::pair and std::tuple also have allocator_arg constructors with uses-=
allocator construction. The same should apply to variant as well. Currently=
, scoped_allocator_adaptor::construct encapsulates this process for heap-ba=
sed classes, but stack-based wrappers need to reimplement it without any st=
andard facility. Return-by-value Allocator::construct and matching SFINAE w=
ould solve it uniformly and let overloading work like the non-allocator cas=
e.
That said, I also suspect that uses-allocator construction belongs not in a=
n allocator interface, but as a particular case a general =E2=80=9Ccontext-=
sensitive construction,=E2=80=9D which would also include destructive-move.=
Such things should work with aggregate-initialization; they shouldn=E2=80=
=99t be specially hooked to constructors at all.
--=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/.
--Apple-Mail=_2E6B3721-F707-4FF0-8B28-B1547347CE31
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9303, at 12:44 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"ma=
ilto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:=
</div></blockquote><blockquote type=3D"cite"><br class=3D"Apple-interchange=
-newline"><div class=3D""><span class=3D"" style=3D"float: none; display: i=
nline !important;">I am not convinced this is the Allocator's job, but the =
wrapper's. When you call `Allocator::construct` you want to construct somet=
hing, if it cannot be constructed then it's a bug. When you call the wrappe=
r's constructor, it's trying to be transparent, if it cannot be constructed=
then it does not exist.</span></div></blockquote></div><br class=3D""><div=
class=3D"">By the way, allocator support isn=E2=80=99t limited to heap-bas=
ed containers. <font face=3D"Courier" class=3D"">std::pair</font> and <font=
face=3D"Courier" class=3D"">std::tuple</font> also have <font face=3D=
"Courier" class=3D"">allocator_arg</font> constructors with uses-allocator =
construction. The same should apply to <font face=3D"Courier" class=3D"">va=
riant</font> as well. Currently, <font face=3D"Courier" class=3D"">sco=
ped_allocator_adaptor::construct</font> encapsulates this process for heap-=
based classes, but stack-based wrappers need to reimplement it without any =
standard facility. Return-by-value <font face=3D"Courier" class=3D"">A=
llocator::construct</font> and matching SFINAE would solve it uniforml=
y and let overloading work like the non-allocator case.</div><div class=3D"=
"><br class=3D""></div><div class=3D"">That said, I also suspect that uses-=
allocator construction belongs not in an allocator interface, but as a part=
icular case a general =E2=80=9Ccontext-sensitive construction,=E2=80=9D whi=
ch would also include destructive-move. Such things should work with aggreg=
ate-initialization; they shouldn=E2=80=99t be specially hooked to construct=
ors at all.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_2E6B3721-F707-4FF0-8B28-B1547347CE31--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sat, 3 Oct 2015 12:33:02 -0300
Raw View
On 10/3/2015 1:08 AM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9303, at 12:44 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>> Could you just show me how would W document its semantics?
>
> W<T,A>::W(Args...) would require that A can construct T, specifically
> that allocator_traits<A>::construct<T>(Args ...) is a well-formed
> expression, otherwise SFINAE. (Or, take it in terms of an invented
> allocator_traits::is_constructible.) It=E2=80=99s just a natural extensio=
n of
> SFINAE on is_constructible to allocators=E2=80=A6 is_constructible is
> inaccurate; it provides false positives and false negatives when the
> allocator changes the constructor argument list.
In terms of an invented `allocator_traits::is_constructible` seems=20
reasonable to me. EmplaceConstructible would probably work too (if=20
repurposed to not be exclusive to containers).
But what about the wrappers with embedded storage we are discussing in=20
this thread? Should `variant` document something in terms of=20
`std::allocator<?>::is_constructible`? It would technically be correct,=20
but after Boost.Variant I would cringe at the mention of allocators in=20
the documentation.
I'm gonna stop here. My objections are not technical, I don't challenge=20
the feasibility of any of it. I believe it to be in poor taste, that's=20
subjective and you obviously disagree with me.
>> I chose to assume `std::construct` would offer a different interface
>> to cover more ground.
>>
>> The overload candidate set for `Allocator::construct` is entirely
>> defined by `Allocator`; the overload candidate set for
>> `std::construct` is open, anyone can add overloads to that set, and
>> `std::construct` should play nicely with them.
>
> I don=E2=80=99t follow. You say std::construct shouldn=E2=80=99t be a cus=
tomization
> point; to me that means not to bless ADL. How else can a user add an
> overload?
I don't see how you bring customization points to the picture. There's a=20
motivation for SFINAEing out an otherwise ill-formed declaration (like=20
`invoke` does), or else you leave pretty much every other (unrelated)=20
use of the unqualified name in either ill-formed or=20
implementation-defined land (like `apply` does). I don't know of a=20
motivation for SFINAEing out an otherwise ill-formed definition, and I=20
can't think of places where the standard library does this to free=20
functions (but I did not go spelunking, it's just a general "we don't do=20
this" feeling).
>> I do not think `std::construct` should be a customization point either.
>>
>>> If the job of std::construct is to choose between direct-initialization
>>> and direct-list-initialization, should it SFINAE when both of those
>>> initializations are ill-formed in the context of its own declaration?
>>
>> That would depend on how you choose to define such a `std::construct`.
>> I would consider a request to construct something that cannot be
>> constructed a bug, so I would define it so that it is a hard error.
>
> There exists a Platonic ideal that all requirements are specified by
> enable_if or requires clauses, and no other SFINAE happens.
Ideally, maybe. In reality, it comes with a number of associated=20
overheads ranging from technical to cognitive, it's a tradeoff as usual.
>>> There=E2=80=99s a little misunderstanding. I was talking about SFINAE, =
not
>>> actually calling the function.
>>>
>>> As for calling it, guaranteed copy elision should help.
>>
>> I'm not sure this clears the misunderstanding. I was trying to say
>> that these solutions cannot be consumed by `variant` and other types
>> with embedded storage. Guaranteed copy elision would definitively help.
>
> You can use std::construct for SFINAE but not call it.
>
> template< typename value_type >
> template< typename args ...
> , std::enable_if_t< ! std::is_constructible< value_type, args ...
> >::value > * // No direct-initialization.
> , decltype( std::construct< T >( args ... ) ) * // But
> flexible-initialization works. (Does not ODR-use std::construct.)
> >
> wrapper< value_type >::wrapper( args ... a )
> : value{ a ... } // Deduce that brace-initialization is right.
> {}
This example shows how the proposed solution cannot easily be consumed=20
by types with embedded storage. Looking at it, the first thing I'd want=20
to do is define a trait to test for the well-formedness of the=20
`construct` expression. At least now I have a name to go by.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sat, 3 Oct 2015 12:42:57 -0300
Raw View
On 10/3/2015 4:54 AM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9303, at 12:44 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> I am not convinced this is the Allocator's job, but the wrapper's.
>> When you call `Allocator::construct` you want to construct something,
>> if it cannot be constructed then it's a bug. When you call the
>> wrapper's constructor, it's trying to be transparent, if it cannot be
>> constructed then it does not exist.
>
> By the way, allocator support isn=E2=80=99t limited to heap-based contain=
ers.
> std::pair and std::tuple also have allocator_arg constructors with
> uses-allocator construction. The same should apply to variant as well.
> Currently, scoped_allocator_adaptor::construct encapsulates this process
> for heap-based classes, but stack-based wrappers need to reimplement it
> without any standard facility. Return-by-value Allocator::construct and
> matching SFINAE would solve it uniformly and let overloading work like
> the non-allocator case.
>
> That said, I also suspect that uses-allocator construction belongs not
> in an allocator interface, but as a particular case a general
> =E2=80=9Ccontext-sensitive construction,=E2=80=9D which would also includ=
e
> destructive-move. Such things should work with aggregate-initialization;
> they shouldn=E2=80=99t be specially hooked to constructors at all.
I'm glad you brought uses-allocator construction into the picture, it=20
shares many of the same concerns for types with embedded storage. You'll=20
notice however that unlike the flexible-construction proposal, it comes=20
with both a name for the concept and a trait to constrain constructors.
Unfortunately there's a hole in the concept, due to part of the=20
semantics being defined in `scoped_allocator_adaptor`. Using a `pair`=20
within a type with embedded storage breaks the scoped-allocator model.
We discussed with Pablo how types with embedded storage have to keep=20
reimplementing the solution over and over, and the best we could come up=20
with was an adaptor wrapper that would do the job of dispatching to the=20
right constructor. Guaranteed copy elision would open new and IMHO=20
better possibilities.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 4 Oct 2015 07:53:23 +0800
Raw View
--Apple-Mail=_56E01BEB-58F2-4D0E-ACB6-F3DA93541E66
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9303, at 11:33 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I'm gonna stop here. My objections are not technical, I don't challenge t=
he feasibility of any of it. I believe it to be in poor taste, that's subje=
ctive and you obviously disagree with me.
I don=E2=80=99t disagree. I=E2=80=99m not against having allocator_traits::=
is_constructible or an additional interface outside std::allocator. But tho=
se are additional things to have, which would make a proposal bigger, so I=
=E2=80=99m trying to tease out any arguments in favor.
> I don't see how you bring customization points to the picture.
I didn=E2=80=99t. You were talking about an =E2=80=9Copen overload set=E2=
=80=9D and I asked whether that meant ADL.
> There's a motivation for SFINAEing out an otherwise ill-formed declaratio=
n (like `invoke` does), or else you leave pretty much every other (unrelate=
d) use of the unqualified name in either ill-formed or implementation-defin=
ed land (like `apply` does). I don't know of a motivation for SFINAEing out=
an otherwise ill-formed definition, and I can't think of places where the =
standard library does this to free functions (but I did not go spelunking, =
it's just a general "we don't do this" feeling).
Constructors for wrappers (pair, function, etc.) are defined to SFINAE them=
selves on is_constructible. It seems reasonable to let std::construct behav=
e the same way even though it=E2=80=99s not inside a wrapper.
--=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/.
--Apple-Mail=_56E01BEB-58F2-4D0E-ACB6-F3DA93541E66
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9303, at 11:33 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"ma=
ilto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:=
</div><br class=3D"Apple-interchange-newline"><div class=3D""><span style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px; float: none; display: inline !important;" class=3D"">I'm gonna=
stop here. My objections are not technical, I don't challenge the feasibil=
ity of any of it. I believe it to be in poor taste, that's subjective and y=
ou obviously disagree with me.</span><br style=3D"font-family: Helvetica; f=
ont-size: 12px; font-style: normal; font-variant: normal; font-weight: norm=
al; letter-spacing: normal; line-height: normal; orphans: auto; text-align:=
start; text-indent: 0px; text-transform: none; white-space: normal; widows=
: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""></di=
v></blockquote></div><br class=3D""><div class=3D"">I don=E2=80=99t disagre=
e. I=E2=80=99m not against having <font face=3D"Courier" class=3D"">allocat=
or_traits::is_constructible</font> or an additional interface outside <font=
face=3D"Courier" class=3D"">std::allocator</font>. But those are additiona=
l things to have, which would make a proposal bigger, so I=E2=80=99m trying=
to tease out any arguments in favor.</div><div class=3D""><br class=3D""><=
/div><div class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">I=
don't see how you bring customization points to the picture. </div></block=
quote><div class=3D""><br class=3D""></div><div class=3D"">I didn=E2=80=99t=
.. You were talking about an =E2=80=9Copen overload set=E2=80=9D and I asked=
whether that meant ADL.</div><br class=3D""><blockquote type=3D"cite" clas=
s=3D""><div class=3D"">There's a motivation for SFINAEing out an otherwise =
ill-formed declaration (like `invoke` does), or else you leave pretty much =
every other (unrelated) use of the unqualified name in either ill-formed or=
implementation-defined land (like `apply` does). I don't know of a motivat=
ion for SFINAEing out an otherwise ill-formed definition, and I can't think=
of places where the standard library does this to free functions (but I di=
d not go spelunking, it's just a general "we don't do this" feeling).</div>=
</blockquote></div><div class=3D""><div class=3D""><span class=3D"" style=
=3D"float: none; display: inline !important;"><br class=3D""></span></div><=
/div><div class=3D""><span class=3D"" style=3D"float: none; display: inline=
!important;">Constructors for wrappers (<font face=3D"Courier" class=3D"">=
pair</font>, <font face=3D"Courier" class=3D"">function</font>, etc.) are d=
efined to SFINAE themselves on <font face=3D"Courier" class=3D"">is_constru=
ctible</font>. It seems reasonable to let <font face=3D"Courier" class=3D""=
>std::construct</font> behave the same way even though it=E2=80=99s not ins=
ide a wrapper.</span></div><div class=3D""><br class=3D""></div></body></ht=
ml>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_56E01BEB-58F2-4D0E-ACB6-F3DA93541E66--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sat, 3 Oct 2015 22:37:31 -0300
Raw View
On 10/3/2015 8:53 PM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9303, at 11:33 PM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>> I don't see how you bring customization points to the picture.
>
> I didn=E2=80=99t. You were talking about an =E2=80=9Copen overload set=E2=
=80=9D and I asked
> whether that meant ADL.
It does mean ADL (by being a free function of a namespace associated=20
with other standard library facilities), it does not mean customization=20
points. ADL and customization points are different beasts.
>> There's a motivation for SFINAEing out an otherwise ill-formed
>> declaration (like `invoke` does), or else you leave pretty much every
>> other (unrelated) use of the unqualified name in either ill-formed or
>> implementation-defined land (like `apply` does). I don't know of a
>> motivation for SFINAEing out an otherwise ill-formed definition, and I
>> can't think of places where the standard library does this to free
>> functions (but I did not go spelunking, it's just a general "we don't
>> do this" feeling).
>
> Constructors for wrappers (pair, function, etc.) are defined to SFINAE
> themselves on is_constructible. It seems reasonable to let
> std::construct behave the same way even though it=E2=80=99s not inside a =
wrapper.
I know of two motivations driving that: (1) The declaration of most such=20
constructors would otherwise interfere with overload resolution. (2) The=20
well-formedness of the declaration of such constructors determine=20
`std::is_constructible`, which is a trait of the type.
(1) is not a concern for a free function like `std::construct`. As for=20
(2), my understanding according to what you have told me is that=20
deriving a trait from it is not the goal either, which would IMHO be=20
backwards as flexible-constructibility is a trait of the type not a=20
satellite function (regardless of whether such function is SFINAE=20
friendly, or whether an actual type-trait exist in code).
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 4 Oct 2015 10:16:10 +0800
Raw View
--Apple-Mail=_C00EE2F6-63AE-4E65-A493-83E81EA2EBEC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9304, at 9:37 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> As for (2), my understanding according to what you have told me is that d=
eriving a trait from it is not the goal either, which would IMHO be backwar=
ds as flexible-constructibility is a trait of the type not a satellite func=
tion (regardless of whether such function is SFINAE friendly, or whether an=
actual type-trait exist in code).
It=E2=80=99s premature to talk about the inherent traits of std::construct.=
The simple implementation as two overloads, SFINAE=E2=80=99d on is_constru=
ctible, gives ugly internal errors, =E2=80=9Cbrace-initialization didn=E2=
=80=99t work.=E2=80=9D To raise the QOI you need an additional overload or =
otherwise to inspect direct-brace-initialization. Given that, why not SFINA=
E on the well-formedness of brace-initialization too?
Likewise, if we need a trait for std::construct validity, metaprocessing is=
minimized by simply instantiating its signature and reporting whether that=
worked. Then if the user wants to call it, the signature is already cached=
..
It=E2=80=99s a trait of the function if you want it to be. Of course everyt=
hing comes equally from the type in the end.
--=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/.
--Apple-Mail=_C00EE2F6-63AE-4E65-A493-83E81EA2EBEC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9304, at 9:37 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"mai=
lto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:<=
/div><br class=3D"Apple-interchange-newline"><div class=3D""><span style=3D=
"font-family: Helvetica; font-size: 12px; font-style: normal; font-variant:=
normal; font-weight: normal; letter-spacing: normal; line-height: normal; =
orphans: auto; text-align: start; text-indent: 0px; text-transform: none; w=
hite-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-wi=
dth: 0px; float: none; display: inline !important;" class=3D"">As for (2), =
my understanding according to what you have told me is that deriving a trai=
t from it is not the goal either, which would IMHO be backwards as flexible=
-constructibility is a trait of the type not a satellite function (regardle=
ss of whether such function is SFINAE friendly, or whether an actual type-t=
rait exist in code).</span><br style=3D"font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant: normal; font-weight: normal; letter=
-spacing: normal; line-height: normal; orphans: auto; text-align: start; te=
xt-indent: 0px; text-transform: none; white-space: normal; widows: auto; wo=
rd-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""></div></blockq=
uote></div><br class=3D""><div class=3D"">It=E2=80=99s premature to talk ab=
out the inherent traits of <font face=3D"Courier" class=3D"">std::construct=
</font>. The simple implementation as two overloads, SFINAE=E2=80=99d on <f=
ont face=3D"Courier" class=3D"">is_constructible</font>, gives ugly interna=
l errors, =E2=80=9Cbrace-initialization didn=E2=80=99t work.=E2=80=9D To ra=
ise the QOI you need an additional overload or otherwise to inspect direct-=
brace-initialization. Given that, why not SFINAE on the well-formedness of =
brace-initialization too?</div><div class=3D""><br class=3D""></div><div cl=
ass=3D"">Likewise, if we need a trait for <font face=3D"Courier" class=
=3D"">std::construct</font> validity, metaprocessing is minimized by simply=
instantiating its signature and reporting whether that worked. Then if the=
user wants to call it, the signature is already cached.</div><div class=3D=
""><br class=3D""></div><div class=3D"">It=E2=80=99s a trait of the functio=
n if you want it to be. Of course everything comes equally from the type in=
the end.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_C00EE2F6-63AE-4E65-A493-83E81EA2EBEC--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sun, 4 Oct 2015 13:31:56 -0300
Raw View
On 10/3/2015 11:16 PM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9304, at 9:37 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> As for (2), my understanding according to what you have told me is
>> that deriving a trait from it is not the goal either, which would IMHO
>> be backwards as flexible-constructibility is a trait of the type not a
>> satellite function (regardless of whether such function is SFINAE
>> friendly, or whether an actual type-trait exist in code).
>
> It=E2=80=99s premature to talk about the inherent traits of std::construc=
t. The
> simple implementation as two overloads, SFINAE=E2=80=99d on is_constructi=
ble,
> gives ugly internal errors, =E2=80=9Cbrace-initialization didn=E2=80=99t =
work.=E2=80=9D To raise
> the QOI you need an additional overload or otherwise to inspect
> direct-brace-initialization. Given that, why not SFINAE on the
> well-formedness of brace-initialization too?
I'm failing to make my point across, as you keep bringing technical=20
arguments into the discussion. I couldn't care less about how you choose=20
to implement these. I care that you give me a definition for me to=20
decide on an implementation, instead of trying to give me pieces to=20
build yours.
> Likewise, if we need a trait for std::construct validity, metaprocessing
> is minimized by simply instantiating its signature and reporting whether
> that worked. Then if the user wants to call it, the signature is already
> cached.
If you'd like to use efficiency arguments, I'd expect you to provide=20
measurements over a concrete implementation to back them up (and if you=20
do, please start a new thread). You seem to be suggesting that checking=20
the well-formedness of an overloaded function call that checks for the=20
well-formedness of an expression is cheaper than just checking for the=20
well-formedness of an expression. I'm not saying it's not, I've been=20
surprised enough to say anything without measuring first.
> It=E2=80=99s a trait of the function if you want it to be. Of course ever=
ything
> comes equally from the type in the end.
It's not, you might happen to choose to define your function to match=20
the trait. For instance, does `std::construct` require destructibility?=20
Your implementation does not seem to need it, and flexible-constructible=20
the concept does not require it, while `is_flexible_constructible` the=20
type-trait would.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 5 Oct 2015 01:55:40 +0800
Raw View
--Apple-Mail=_79F3B3F9-6F8E-4935-A0B9-E80E7B2C5E47
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9310=E2=80=9305, at 12:31 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9 <kaballo86@hotmail.com> wrote:
>=20
> I'm failing to make my point across, as you keep bringing technical argum=
ents into the discussion. I couldn't care less about how you choose to impl=
ement these. I care that you give me a definition for me to decide on an im=
plementation, instead of trying to give me pieces to build yours.
You made a weak technical argument that deriving the trait from the functio=
n =E2=80=9Cwould IMHO be backwards,=E2=80=9D so I made a weak technical arg=
ument that it would work fine and could have advantages. I have an aestheti=
c preference for writing expression SFINAE and not memorizing names of trai=
ts (there are too many); your preference seems to be the opposite. That=E2=
=80=99s all.
By default, violating a library precondition is UB, which allows either a h=
ard error or SFINAE. A proposal could well just leave it at that.
> It's not, you might happen to choose to define your function to match the=
trait. For instance, does `std::construct` require destructibility? Your i=
mplementation does not seem to need it, and flexible-constructible the conc=
ept does not require it, while `is_flexible_constructible` the type-trait w=
ould.
Expression SFINAE using decltype(construct<x>(y,z)) does not require destru=
ctibility, even if construct returned by value (=C2=A75.2.2/11). Defining t=
he trait using the function should work=E2=80=A6 But you still have to chec=
k brace-initialization somewhere, and doing so without adding an intrinsic =
or requiring destructibility is a bit tricky. I think a new-expression woul=
d suffice. Yet the scent of a new intrinsic is in the air (and more traits:=
is_list_constructible, is_copy_list_constructible, =E2=80=A6 where will th=
ey end).
--=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/.
--Apple-Mail=_79F3B3F9-6F8E-4935-A0B9-E80E7B2C5E47
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9305, at 12:31 AM, Agust=C3=ADn K-ballo Berg=C3=A9 <<a href=3D"ma=
ilto:kaballo86@hotmail.com" class=3D"">kaballo86@hotmail.com</a>> wrote:=
</div><br class=3D"Apple-interchange-newline"><div class=3D"">I'm failing t=
o make my point across, as you keep bringing technical arguments into the d=
iscussion. I couldn't care less about how you choose to implement these. I =
care that you give me a definition for me to decide on an implementation, i=
nstead of trying to give me pieces to build yours.<br class=3D""></div></bl=
ockquote><div><br class=3D""></div><div>You made a weak technical argument =
that deriving the trait from the function =E2=80=9Cwould IMHO be backwards,=
=E2=80=9D so I made a weak technical argument that it would work fine and c=
ould have advantages. I have an aesthetic preference for writing expression=
SFINAE and not memorizing names of traits (there are too many); your prefe=
rence seems to be the opposite. That=E2=80=99s all.</div><div><br class=3D"=
"></div><div>By default, violating a library precondition is UB, which allo=
ws either a hard error or SFINAE. A proposal could well just leave it at th=
at.</div><div><br class=3D""></div><blockquote type=3D"cite" class=3D""><di=
v class=3D"">It's not, you might happen to choose to define your function t=
o match the trait. For instance, does `std::construct` require destructibil=
ity? Your implementation does not seem to need it, and flexible-constructib=
le the concept does not require it, while `is_flexible_constructible` the t=
ype-trait would.<br class=3D""></div></blockquote></div><br class=3D""><div=
class=3D"">Expression SFINAE using <font face=3D"Courier" class=3D"">declt=
ype(construct<x>(y,z))</font> does not require destructibility, even&=
nbsp;if <font face=3D"Courier" class=3D"">construct</font> returned by valu=
e (=C2=A75.2.2/11). Defining the trait using the function should work=E2=80=
=A6 But you still have to check brace-initialization somewhere, and doing s=
o without adding an intrinsic or requiring destructibility is a bit tricky.=
I think a new-expression would suffice. Yet the scent of a new intrinsic i=
s in the air (and more traits: <font face=3D"Courier" class=3D"">is_list_co=
nstructible</font>, <font face=3D"Courier" class=3D"">is_copy_list_construc=
tible</font>, =E2=80=A6 where will they end).</div><div class=3D""><br clas=
s=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--Apple-Mail=_79F3B3F9-6F8E-4935-A0B9-E80E7B2C5E47--
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Sun, 4 Oct 2015 15:43:41 -0300
Raw View
On 10/4/2015 2:55 PM, David Krauss wrote:
>
>> On 2015=E2=80=9310=E2=80=9305, at 12:31 AM, Agust=C3=ADn K-ballo Berg=C3=
=A9
>> <kaballo86@hotmail.com <mailto:kaballo86@hotmail.com>> wrote:
>>
>> I'm failing to make my point across, as you keep bringing technical
>> arguments into the discussion. I couldn't care less about how you
>> choose to implement these. I care that you give me a definition for me
>> to decide on an implementation, instead of trying to give me pieces to
>> build yours.
>
> You made a weak technical argument that deriving the trait from the
> function =E2=80=9Cwould IMHO be backwards,=E2=80=9D so I made a weak tech=
nical argument
> that it would work fine and could have advantages. I have an aesthetic
> preference for writing expression SFINAE and not memorizing names of
> traits (there are too many); your preference seems to be the opposite.
> That=E2=80=99s all.
My argument was not technical at all. If you wish to implement the trait=20
in that way I don't care, I personally wouldn't do it.
> By default, violating a library precondition is UB, which allows either
> a hard error or SFINAE. A proposal could well just leave it at that.
That would be consistent with the rest of the library.
>> It's not, you might happen to choose to define your function to match
>> the trait. For instance, does `std::construct` require
>> destructibility? Your implementation does not seem to need it, and
>> flexible-constructible the concept does not require it, while
>> `is_flexible_constructible` the type-trait would.
>
> Expression SFINAE using decltype(construct<x>(y,z)) does not require
> destructibility, even if construct returned by value (=C2=A75.2.2/11).
> Defining the trait using the function should work=E2=80=A6 But you still =
have to
> check brace-initialization somewhere, and doing so without adding an
> intrinsic or requiring destructibility is a bit tricky. I think a
> new-expression would suffice. Yet the scent of a new intrinsic is in the
> air (and more traits: is_list_constructible, is_copy_list_constructible,
> =E2=80=A6 where will they end).
Making `std::construct` not require destructibility for the=20
brace-initialization case is not necessarily a good idea, it will be=20
surprising when it picks the "wrong" constructor because a destructor is=20
not accessible. However restricting is functionality only so that it can=20
then be used to derive a trait from it is what IMHO would be backwards.=20
It all falls back on how you decide to define these things, and I don't=20
think defining them as "whatever `construct` does" is reasonable,=20
regardless of how you choose to implement them.
With regard to traits, keep in mind that you will be needing an=20
`is_list_constructible` trait to implement a SFINAE friendly=20
`std::construct` (while it's technically possible to exploit SFINAE's=20
short-circuiting behavior to avoid a dedicated trait, the associated=20
cost is so high it's hardly ever worth the trouble). This is the exact=20
same check you would need for an `is_flexible_constructible` type-trait.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Mon, 05 Oct 2015 13:03:45 -0400
Raw View
On 2015-10-01 17:43, Tony V E wrote:
> On Thu, Oct 1, 2015 at 5:13 PM, Sam Kellett wrote:
>> and on maybe another note entirely, would it be possible to use some
>> compiler magic to get a perfect variant (ie single-buffer, any type,
>> never-empty)? i've only seen talk of library implementations, but why not
>> (if helpful) let the compiler do some work too?
>
> The compiler probably can't help you. For variant<X,Y> the goal is to
> destroy the old X, and _in the same place_ construct a Y. If constructing
> the Y fails, what do you do?
> *IF* the compiler knew that it could just memcpy X from a temporary and
> back into place, it could restore X. But some classes have pointers to
> themselves and other oddities such that an X here is not the same as an X
> there:
I'm not sure this necessarily involves the compiler vs. a pure library
implementation, and I also suspect it *doesn't work*, but just to verify
that it's been considered... what's wrong with this approach?
1. If an exception might occur, make a bitwise copy to temporary (i.e.
stack) storage.
2. Allocate the new object in the variant's storage area.
2e. (If an exception occurs at #2) destroy the new object and copy the
bits of the old object back. Rethrow.
3. Make a bitwise copy of the new object to temporary (i.e. stack) storage.
4. Copy the bits of the old object back, then destroy the old object.
5. Copy the bits of the new object back.
Basically, the idea is to have the variant's buffer "simultaneously"
containing both the old and new objects, so that the old object can be
destroyed *in place* and *after* the new object has been successfully
constructed.
The down side is that this needs up to 3x as much memory and loses quite
a bit of performance due to addition of four bitwise copies.
(To answer my own question... I suppose you could run into pathological
cases like the RHS of the assignment has a reference to the old-LHS that
persists until old-LHS is destroyed, and tries to do something with it
during the new-LHS construction. Whee!)
Of course, this feels a lot like why we need relocatability... if we
have that, we just construct the new object in scratch storage (i.e.
stack) and move it into place. Or move out the old object and don't muck
about with any other moves (unless constructing the new object fails).
I really don't see how *some* form double buffering is avoidable if
we're going to have the strong guarantee, as that implies that the old
object (or at least a copy) must still be available until the new object
is constructed, i.e. they must both be "alive" at the same time. That
means storage *somewhere* for both of them simultaneously.
It also means esoteric ctors/dtors are going to have the fun of dealing
with different call order depending on noexcept specification of the
participating types. Joy...
--
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 5 Oct 2015 13:15:19 -0400
Raw View
--089e011605f466443705215ea879
Content-Type: text/plain; charset=UTF-8
On Mon, Sep 28, 2015 at 4:01 PM, Anthony Williams <anthony.ajw@gmail.com>
wrote:
> On 28/09/15 20:18, 'Matt Calabrese' via ISO C++ Standard - Future
> Proposals wrote:
> > On Mon, Sep 28, 2015 at 12:14 PM, Matt Calabrese <calabrese@google.com
> > <mailto:calabrese@google.com>> wrote:
> >
> > Similarly, what is expected of emplacement? No matter what your
> > field types are (including all fundamental types), it's possible for
> > a user to invoke an emplace operation that can throw. Because of
> > this, it seems to me that when doing emplacement that can throw,
> > you'd need double storage or to allow copy-construct then
> > move-assign (this latter point is probably not controversial for
> > types that are trivially copy-constructible/destructible)
> >
> >
> > Err, I mean *emplace somewhere then move-assign here, not copy then
> > move-assign.
>
> Yes. My current implementation just provides basic guarantee for emplace
> because the requirements are different to assignment and it's a
> proof-of-concept implementation.
>
> To provide the strong guarantee for emplace, you need to double-buffer
> if *any* type is missing the nothrow move constructor (rather than only
> if 2 types can throw), since you still need the backup even if the types
> are the same, whereas with assignment you can use the type's native
> assignment.
>
> Of course, if you never use the type's native assignment (to really
> provide the strong guarantee), then you need buffering for assignment
> too if one type has a throwing move.
>
> Also, you may end up using the buffer more often, unless you're willing
> to emplace-construct a temporary and then nothrow-move from there. If
> you were willing to do that, you'd probably not need emplace anyway as
> you could just say v=T(args);
>
> So, strong guarantee for emplacement increases the chance you'd need to
> double-buffer.
>
Never-ending-thread :-(
I need to be clear about this. We have (in your proposal) what is probably
the minimum conditions for when extra buffering is required to enable
strong(ish) *assignment*.
However, for strongish emplace the set of conditions becomes "larger" or
more unlikely (or however you want to describe it).
The point of strongish assignment (IIUC) was to avoid the "invalid" state.
But we can't completely remove invalid unless we also do similar on
emplace. IMO, it isn't worth doing strongish assignment unless we can
completely banish the invalid state. If we still have invalid for emplace,
we might as well use it on failed assignment as well.
So to get rid of invalid, ie to get strongish emplace, we need extra
buffering if any type has a throwing constructor?
We could narrow the requirements by emplacing to a temporary, then moving,
however:
1. the type would need nothrow move
2. we would be defeating the point of calling emplace*
[*] the point of emplace is either
- the type is immovable
- efficiency
- convenience? ie a I had the args, why make me type the constructor?
Do I understand correctly?
(basically the Lenexa variant is looking better and better. Kudos to the
"Lenexa Ten")
Tony
> Anthony
> --
> Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
> just::thread C++11 thread library http://www.stdthread.co.uk
> Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e011605f466443705215ea879
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Sep 28, 2015 at 4:01 PM, Anthony Williams <span dir=3D"ltr"><=
;<a href=3D"mailto:anthony.ajw@gmail.com" target=3D"_blank">anthony.ajw@gma=
il.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">On 28/09/15 =
20:18, 'Matt Calabrese' via ISO C++ Standard - Future<br>
<span class=3D"">Proposals wrote:<br>
> On Mon, Sep 28, 2015 at 12:14 PM, Matt Calabrese <<a href=3D"mailto=
:calabrese@google.com">calabrese@google.com</a><br>
</span><span class=3D"">> <mailto:<a href=3D"mailto:calabrese@google.=
com">calabrese@google.com</a>>> wrote:<br>
><br>
>=C2=A0 =C2=A0 =C2=A0Similarly, what is expected of emplacement? No matt=
er what your<br>
>=C2=A0 =C2=A0 =C2=A0field types are (including all fundamental types), =
it's possible for<br>
>=C2=A0 =C2=A0 =C2=A0a user to invoke an emplace operation that can thro=
w. Because of<br>
>=C2=A0 =C2=A0 =C2=A0this, it seems to me that when doing emplacement th=
at can throw,<br>
>=C2=A0 =C2=A0 =C2=A0you'd need double storage or to allow copy-cons=
truct then<br>
>=C2=A0 =C2=A0 =C2=A0move-assign (this latter point is probably not cont=
roversial for<br>
>=C2=A0 =C2=A0 =C2=A0types that are trivially copy-constructible/destruc=
tible)<br>
><br>
><br>
> Err, I mean *emplace somewhere then move-assign here, not copy then<br=
>
> move-assign.<br>
<br>
</span>Yes. My current implementation just provides basic guarantee for emp=
lace<br>
because the requirements are different to assignment and it's a<br>
proof-of-concept implementation.<br>
<br>
To provide the strong guarantee for emplace, you need to double-buffer<br>
if *any* type is missing the nothrow move constructor (rather than only<br>
if 2 types can throw), since you still need the backup even if the types<br=
>
are the same, whereas with assignment you can use the type's native<br>
assignment.<br>
<br>
Of course, if you never use the type's native assignment (to really<br>
provide the strong guarantee), then you need buffering for assignment<br>
too if one type has a throwing move.<br>
<br>
Also, you may end up using the buffer more often, unless you're willing=
<br>
to emplace-construct a temporary and then nothrow-move from there. If<br>
you were willing to do that, you'd probably not need emplace anyway as<=
br>
you could just say v=3DT(args);<br>
<br>
So, strong guarantee for emplacement increases the chance you'd need to=
<br>
double-buffer.<br></blockquote><div><br></div><div>Never-ending-thread :-(<=
br><br></div><div>I need to be clear about this.=C2=A0 We have (in your pro=
posal) what is probably the minimum conditions for when extra buffering is =
required to enable strong(ish) *assignment*.<br><br></div><div>However, for=
strongish emplace the set of conditions becomes "larger" or more=
unlikely (or however you want to describe it).<br><br></div><div>The point=
of strongish assignment (IIUC) was to avoid the "invalid" state.=
=C2=A0 But we can't completely remove invalid unless we also do similar=
on emplace.=C2=A0 IMO, it isn't worth doing strongish assignment unles=
s we can completely banish the invalid state.=C2=A0 If we still have invali=
d for emplace, we might as well use it on failed assignment as well.<br><br=
></div><div>So to get rid of invalid, ie to get strongish emplace, we need =
extra buffering if any type has a throwing constructor?<br><br></div><div>W=
e could narrow the requirements by emplacing to a temporary, then moving, h=
owever:<br>1. the type would need nothrow move<br></div><div>2. we would be=
defeating the point of calling emplace*<br><br></div><div>[*] the point of=
emplace is either<br></div><div>- the type is immovable<br></div><div>- ef=
ficiency<br></div><div>- convenience? ie a I had the args, why make me type=
the constructor?<br><br></div><div>Do I understand correctly?<br></div><di=
v>(basically the Lenexa variant is looking better and better.=C2=A0 Kudos t=
o the "Lenexa Ten")<br><br></div><div>Tony<br><br></div><div><br>=
</div><div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=3D"im HOEnZb"><br>
Anthony<br>
--<br>
Author of C++ Concurrency in Action=C2=A0 =C2=A0 =C2=A0<a href=3D"http://ww=
w.stdthread.co.uk/book/" rel=3D"noreferrer" target=3D"_blank">http://www.st=
dthread.co.uk/book/</a><br>
just::thread C++11 thread library=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0<a href=3D"http://www.stdthread.co.uk" rel=3D"noreferrer" target=3D"_=
blank">http://www.stdthread.co.uk</a><br>
Just Software Solutions Ltd=C2=A0 =C2=A0 =C2=A0 =C2=A0<a href=3D"http://www=
..justsoftwaresolutions.co.uk" rel=3D"noreferrer" target=3D"_blank">http://w=
ww.justsoftwaresolutions.co.uk</a><br>
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976<br=
>
<br>
</span><div class=3D"HOEnZb"><div class=3D"h5">--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e011605f466443705215ea879--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Mon, 5 Oct 2015 12:16:36 -0500
Raw View
--001a114363ac5cf74c05215eaf3f
Content-Type: text/plain; charset=UTF-8
On 5 October 2015 at 12:03, Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 2015-10-01 17:43, Tony V E wrote:
> I'm not sure this necessarily involves the compiler vs. a pure library
> implementation, and I also suspect it *doesn't work*, but just to verify
> that it's been considered... what's wrong with this approach?
>
> 1. If an exception might occur, make a bitwise copy to temporary (i.e.
> stack) storage.
> 2. Allocate the new object in the variant's storage area.
> 2e. (If an exception occurs at #2) destroy the new object and copy the
> bits of the old object back. Rethrow.
> 3. Make a bitwise copy of the new object to temporary (i.e. stack) storage.
> 4. Copy the bits of the old object back, then destroy the old object.
> 5. Copy the bits of the new object back.
>
How does this differ from the "False Hopes" section of <
http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty.memcpy-solution
>?
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a114363ac5cf74c05215eaf3f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 5 October 2015 at 12:03, Matthew Woehlke <span dir=3D"l=
tr"><<a href=3D"mailto:mwoehlke.floss@gmail.com" target=3D"_blank">mwoeh=
lke.floss@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><di=
v class=3D"gmail_quote"><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">On 2015-10-01 17:43, Tony V E wrot=
e:<br>I'm not sure this necessarily involves the compiler vs. a pure li=
brary<br>
implementation, and I also suspect it *doesn't work*, but just to verif=
y<br>
that it's been considered... what's wrong with this approach?<br>
<br>
1. If an exception might occur, make a bitwise copy to temporary (i.e.<br>
stack) storage.<br>
2. Allocate the new object in the variant's storage area.<br>
2e. (If an exception occurs at #2) destroy the new object and copy the<br>
bits of the old object back. Rethrow.<br>
3. Make a bitwise copy of the new object to temporary (i.e. stack) storage.=
<br>
4. Copy the bits of the old object back, then destroy the old object.<br>
5. Copy the bits of the new object back.<br></blockquote><div><br></div><di=
v>How does this differ from the "False Hopes" section of <<a h=
ref=3D"http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#va=
riant.design.never-empty.memcpy-solution">http://www.boost.org/doc/libs/1_5=
9_0/doc/html/variant/design.html#variant.design.never-empty.memcpy-solution=
</a>>?</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin &quo=
t;:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com=
" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</di=
v>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a114363ac5cf74c05215eaf3f--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 5 Oct 2015 13:25:15 -0400
Raw View
--001a1140346cf2f70005215ecb71
Content-Type: text/plain; charset=UTF-8
On Mon, Oct 5, 2015 at 1:16 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 5 October 2015 at 12:03, Matthew Woehlke <mwoehlke.floss@gmail.com>
> wrote:
>
>> On 2015-10-01 17:43, Tony V E wrote:
>> I'm not sure this necessarily involves the compiler vs. a pure library
>> implementation, and I also suspect it *doesn't work*, but just to verify
>> that it's been considered... what's wrong with this approach?
>>
>> 1. If an exception might occur, make a bitwise copy to temporary (i.e.
>> stack) storage.
>> 2. Allocate the new object in the variant's storage area.
>> 2e. (If an exception occurs at #2) destroy the new object and copy the
>> bits of the old object back. Rethrow.
>> 3. Make a bitwise copy of the new object to temporary (i.e. stack)
>> storage.
>> 4. Copy the bits of the old object back, then destroy the old object.
>> 5. Copy the bits of the new object back.
>>
>
> How does this differ from the "False Hopes" section of <
> http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty.memcpy-solution
> >?
> --
> Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
>
> --
>
It is exactly the same. However, we now have a slightly different
situation, once it is a standard library:
- STL is allowed to be implemented using UB (ie that the compiler knows is
OK) - ie maybe there is compiler magic
However (x2), you still have threading issues.
If my class Foo is being accessed by other threads, and Foo is built such
that this is OK as long as Foo is alive (ie in the destructor Foo notifies
all the threads using it that it is going away, and waits for them to be
notified)...
.... then some thread could access (read or write) Foo's memory when it is
actually temporarily a Bar.
Now if you could just put a lock around that memory until the switching was
done...
.... and not deadlock...
:-(
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1140346cf2f70005215ecb71
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Oct 5, 2015 at 1:16 PM, Nevin Liber <span dir=3D"ltr"><<a hr=
ef=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.c=
om</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><span class=3D"">On 5 October 2015 at 12:03, Matthew Woehlke <span dir=3D"=
ltr"><<a href=3D"mailto:mwoehlke.floss@gmail.com" target=3D"_blank">mwoe=
hlke.floss@gmail.com</a>></span> wrote:<br></span><div class=3D"gmail_ex=
tra"><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,20=
4,204);border-left-style:solid;padding-left:1ex"><span class=3D"">On 2015-1=
0-01 17:43, Tony V E wrote:<br></span><span class=3D"">I'm not sure thi=
s necessarily involves the compiler vs. a pure library<br>
implementation, and I also suspect it *doesn't work*, but just to verif=
y<br>
that it's been considered... what's wrong with this approach?<br>
<br>
1. If an exception might occur, make a bitwise copy to temporary (i.e.<br>
stack) storage.<br>
2. Allocate the new object in the variant's storage area.<br>
2e. (If an exception occurs at #2) destroy the new object and copy the<br>
bits of the old object back. Rethrow.<br>
3. Make a bitwise copy of the new object to temporary (i.e. stack) storage.=
<br>
4. Copy the bits of the old object back, then destroy the old object.<br>
5. Copy the bits of the new object back.<br></span></blockquote><div><br></=
div><div>How does this differ from the "False Hopes" section of &=
lt;<a href=3D"http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.=
html#variant.design.never-empty.memcpy-solution" target=3D"_blank">http://w=
ww.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.ne=
ver-empty.memcpy-solution</a>>?</div></div><span class=3D"">-- <br><div>=
=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@=
eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 <a=
href=3D"tel:%28847%29%20691-1404" value=3D"+18476911404" target=3D"_blank"=
>(847) 691-1404</a></div>
</span></div></div>
<p></p>
-- <br></blockquote><div><br></div><div>It is exactly the same.=C2=A0 Howev=
er, we now have a slightly different situation, once it is a standard libra=
ry:<br></div><div>- STL is allowed to be implemented using UB (ie that the =
compiler knows is OK) - ie maybe there is compiler magic<br></div><div><br>=
</div><div>However (x2), you still have threading issues.<br></div><div>If =
my class Foo is being accessed by other threads, and Foo is built such that=
this is OK as long as Foo is alive (ie in the destructor Foo notifies all =
the threads using it that it is going away, and waits for them to be notifi=
ed)...<br><br></div><div>... then some thread could access (read or write) =
Foo's memory when it is actually temporarily a Bar.<br><br></div></div>=
Now if you could just put a lock around that memory until the switching was=
done...<br><br></div><div class=3D"gmail_extra">... and not deadlock...<br=
><br>:-(<br><br></div><div class=3D"gmail_extra">Tony<br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1140346cf2f70005215ecb71--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Mon, 05 Oct 2015 13:31:51 -0400
Raw View
On 2015-10-05 13:16, Nevin Liber wrote:
> On 5 October 2015 at 12:03, Matthew Woehlke wrote:
>
>> On 2015-10-01 17:43, Tony V E wrote:
>> I'm not sure this necessarily involves the compiler vs. a pure library
>> implementation, and I also suspect it *doesn't work*, but just to verify
>> that it's been considered... what's wrong with this approach?
>>
>> 1. If an exception might occur, make a bitwise copy to temporary (i.e.
>> stack) storage.
>> 2. Allocate the new object in the variant's storage area.
>> 2e. (If an exception occurs at #2) destroy the new object and copy the
>> bits of the old object back. Rethrow.
>> 3. Make a bitwise copy of the new object to temporary (i.e. stack) storage.
>> 4. Copy the bits of the old object back, then destroy the old object.
>> 5. Copy the bits of the new object back.
>
> How does this differ from the "False Hopes" section of <
> http://www.boost.org/doc/libs/1_59_0/doc/html/variant/design.html#variant.design.never-empty.memcpy-solution
>> ?
Well, since we're now talking about the standard and not *restricted* to
a library solution, we could make it defined behavior ;-).
Otherwise, that's about the idea. As I said, just wanted to be sure it
had been considered. (I suspect the point about concurrent environments
is still going to kill it, though. Although I don't see the problem
aside from the fact that the old object's dtor hasn't run meaning that
something, somewhere, thinks the old object is still live *at the old
address*, which means it's roughly the same point I already mentioned.
There really isn't a way around that, even with kernel support, as
ultimately there exists some pathological case that would require being
able to read both objects at the same address. Mind, I can construct
that pathological case even without concurrency...)
--
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Mon, 05 Oct 2015 14:45:39 -0400
Raw View
On 2015-09-28 11:48, Nicol Bolas wrote:
> On Monday, September 28, 2015 at 6:46:54 AM UTC-4, Peter Koch Larsen wrote:
>> This could be a double-buffer or simply by storing a T* instead of
>> a T for such types.
>
> Ville already slammed down on the latter as being unacceptable. And I have
> to agree; dynamic allocation, *especially* without some form of `allocator`
> support, should be a non-starter. Even moreso if it's up to the
> implementation to decide when it is necessary (and I have no idea how you
> would enforce such an implementation through behavior). If you want dynamic
> allocated memory in your `variant`, feel free to put a `unique_ptr<T>` in
> the typelist.
....except that a T might be copyable and assignable, while a
unique_ptr<T> is not.
Is there any such thing in the language as a type that holds a T by
pointer, but otherwise acts like a T itself (i.e. makes a copy of the
"internal" object when it itself is copied)? That would solve the
'really big object' case without changing the value-like behavior.
The trick would be arranging for variant to take advantage of being able
to leverage that type to provide better exception guarantees, especially
if the wrapper is not allowed to be empty.
Oh, wait... that's relocatability...
--
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Mon, 5 Oct 2015 15:00:39 -0400
Raw View
--001a11410d941e1fe005216021bd
Content-Type: text/plain; charset=UTF-8
On Mon, Oct 5, 2015 at 2:45 PM, Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 2015-09-28 11:48, Nicol Bolas wrote:
> > On Monday, September 28, 2015 at 6:46:54 AM UTC-4, Peter Koch Larsen
> wrote:
> >> This could be a double-buffer or simply by storing a T* instead of
> >> a T for such types.
> >
> > Ville already slammed down on the latter as being unacceptable. And I
> have
> > to agree; dynamic allocation, *especially* without some form of
> `allocator`
> > support, should be a non-starter. Even moreso if it's up to the
> > implementation to decide when it is necessary (and I have no idea how you
> > would enforce such an implementation through behavior). If you want
> dynamic
> > allocated memory in your `variant`, feel free to put a `unique_ptr<T>` in
> > the typelist.
>
> ...except that a T might be copyable and assignable, while a
> unique_ptr<T> is not.
>
> Is there any such thing in the language as a type that holds a T by
> pointer, but otherwise acts like a T itself (i.e. makes a copy of the
> "internal" object when it itself is copied)?
There have been talks, and I think proposals, for a clone_ptr or value_ptr
or whatever you want to call it, that act like this.
> That would solve the
> 'really big object' case without changing the value-like behavior.
>
> The trick would be arranging for variant to take advantage of being able
> to leverage that type to provide better exception guarantees, especially
> if the wrapper is not allowed to be empty.
>
> Oh, wait... that's relocatability...
>
> --
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11410d941e1fe005216021bd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Oct 5, 2015 at 2:45 PM, 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><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 2015-=
09-28 11:48, Nicol Bolas wrote:<br>
> On Monday, September 28, 2015 at 6:46:54 AM UTC-4, Peter Koch Larsen w=
rote:<br>
>> This could be a double-buffer or simply by storing a T* instead of=
<br>
>> a T for such types.<br>
><br>
> Ville already slammed down on the latter as being unacceptable. And I =
have<br>
> to agree; dynamic allocation, *especially* without some form of `alloc=
ator`<br>
> support, should be a non-starter. Even moreso if it's up to the<br=
>
> implementation to decide when it is necessary (and I have no idea how =
you<br>
> would enforce such an implementation through behavior). If you want dy=
namic<br>
> allocated memory in your `variant`, feel free to put a `unique_ptr<=
T>` in<br>
> the typelist.<br>
<br>
....except that a T might be copyable and assignable, while a<br>
unique_ptr<T> is not.<br>
<br>
Is there any such thing in the language as a type that holds a T by<br>
pointer, but otherwise acts like a T itself (i.e. makes a copy of the<br>
"internal" object when it itself is copied)?</blockquote><div><br=
><br></div><div>There have been talks, and I think proposals, for a clone_p=
tr or value_ptr or whatever you want to call it, that act like this.<br></d=
iv><div><br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> That would solve th=
e<br>
'really big object' case without changing the value-like behavior.<=
br>
<br>
The trick would be arranging for variant to take advantage of being able<br=
>
to leverage that type to provide better exception guarantees, especially<br=
>
if the wrapper is not allowed to be empty.<br>
<br>
Oh, wait... that's relocatability...<br>
<div class=3D"HOEnZb"><div class=3D"h5"><br>
--<br>
Matthew<br>
<br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11410d941e1fe005216021bd--
.
Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Tue, 6 Oct 2015 08:51:35 +0100
Raw View
On 05/10/15 18:15, Tony V E wrote:
>
>
> On Mon, Sep 28, 2015 at 4:01 PM, Anthony Williams <anthony.ajw@gmail.com
> <mailto:anthony.ajw@gmail.com>> wrote:
>
> On 28/09/15 20:18, 'Matt Calabrese' via ISO C++ Standard - Future
> Proposals wrote:
> > On Mon, Sep 28, 2015 at 12:14 PM, Matt Calabrese <calabrese@google.com <mailto:calabrese@google.com>
> > <mailto:calabrese@google.com <mailto:calabrese@google.com>>> wrote:
> >
> > Similarly, what is expected of emplacement? No matter what your
> > field types are (including all fundamental types), it's possible for
> > a user to invoke an emplace operation that can throw. Because of
> > this, it seems to me that when doing emplacement that can throw,
> > you'd need double storage or to allow copy-construct then
> > move-assign (this latter point is probably not controversial for
> > types that are trivially copy-constructible/destructible)
> >
> >
> > Err, I mean *emplace somewhere then move-assign here, not copy then
> > move-assign.
>
> Yes. My current implementation just provides basic guarantee for emplace
> because the requirements are different to assignment and it's a
> proof-of-concept implementation.
>
> To provide the strong guarantee for emplace, you need to double-buffer
> if *any* type is missing the nothrow move constructor (rather than only
> if 2 types can throw), since you still need the backup even if the types
> are the same, whereas with assignment you can use the type's native
> assignment.
>
> Of course, if you never use the type's native assignment (to really
> provide the strong guarantee), then you need buffering for assignment
> too if one type has a throwing move.
>
> Also, you may end up using the buffer more often, unless you're willing
> to emplace-construct a temporary and then nothrow-move from there. If
> you were willing to do that, you'd probably not need emplace anyway as
> you could just say v=T(args);
>
> So, strong guarantee for emplacement increases the chance you'd need to
> double-buffer.
>
>
> Never-ending-thread :-(
>
> I need to be clear about this. We have (in your proposal) what is
> probably the minimum conditions for when extra buffering is required to
> enable strong(ish) *assignment*.
>
> However, for strongish emplace the set of conditions becomes "larger" or
> more unlikely (or however you want to describe it).
>
> The point of strongish assignment (IIUC) was to avoid the "invalid"
> state. But we can't completely remove invalid unless we also do similar
> on emplace. IMO, it isn't worth doing strongish assignment unless we
> can completely banish the invalid state. If we still have invalid for
> emplace, we might as well use it on failed assignment as well.
>
> So to get rid of invalid, ie to get strongish emplace, we need extra
> buffering if any type has a throwing constructor?
Yes.
variant<A,B>::emplace<B> needs either the move-constructor of the old
value (A or B) to be nothrow, or the emplace-constructor of B being used
in this case to be nothrow, otherwise it needs double-buffering.
Thus, for strong-guarantee emplace we need double-buffering if *any*
type in our typelist has a potentially-throwing move constructor, since
we can't in general know which constructor will be chosen for our types.
> We could narrow the requirements by emplacing to a temporary, then
> moving, however:
> 1. the type would need nothrow move
> 2. we would be defeating the point of calling emplace*
>
> [*] the point of emplace is either
> - the type is immovable
> - efficiency
> - convenience? ie a I had the args, why make me type the constructor?
>
> Do I understand correctly?
Yes.
> (basically the Lenexa variant is looking better and better. Kudos to
> the "Lenexa Ten")
The main thing I dislike about the Lenexa variant is the UB-if-invalid
behaviour. I prefer throw-if-invalid by a large margin.
I prefer never-empty with the strong guarantee though.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++11 thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 25 Oct 2015 17:06:59 -0700 (PDT)
Raw View
------=_Part_659_316963830.1445818020009
Content-Type: multipart/alternative;
boundary="----=_Part_660_1460607204.1445818020009"
------=_Part_660_1460607204.1445818020009
Content-Type: text/plain; charset=UTF-8
According to Herb Sutter, it is done
<http://herbsutter.com/2015/10/25/2568/>. Finally. And apparently, it's
just N4542/P0088R0. AKA: never-empty, but with an invalid state on
exceptions. And probably default construction on that.
Oh, and it'll throw instead of issue undefined behavior if you do things
with an invalid variant. Which means that visitation can't be a noexcept
operation. Not that it was `noexcept` before, but it would have been nice
to have it be noexcept if all of the operator()'s it could call were
noexcept too.
Oh well; at least it doesn't cause performance hassles (since any fetching
operations have to check the index anyway).
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_660_1460607204.1445818020009
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">According to Herb Sutter, <a href=3D"http://herbsutter.com=
/2015/10/25/2568/">it is done</a>. Finally. And apparently, it's just N=
4542/P0088R0. AKA: never-empty, but with an invalid state on exceptions. An=
d probably default construction on that.<br><br>Oh, and it'll throw ins=
tead of issue undefined behavior if you do things with an invalid variant. =
Which means that visitation can't be a noexcept operation. Not that it =
was `noexcept` before, but it would have been nice to have it be noexcept i=
f all of the operator()'s it could call were noexcept too.<br><br>Oh we=
ll; at least it doesn't cause performance hassles (since any fetching o=
perations have to check the index anyway).<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_660_1460607204.1445818020009--
------=_Part_659_316963830.1445818020009--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 25 Oct 2015 17:07:59 -0700 (PDT)
Raw View
------=_Part_3985_720601009.1445818079355
Content-Type: multipart/alternative;
boundary="----=_Part_3986_761553858.1445818079356"
------=_Part_3986_761553858.1445818079356
Content-Type: text/plain; charset=UTF-8
On Sunday, October 25, 2015 at 8:07:00 PM UTC-4, Nicol Bolas wrote:
>
> According to Herb Sutter, it is done
> <http://herbsutter.com/2015/10/25/2568/>. Finally. And apparently, it's
> just N4542/P0088R0. AKA: never-empty, but with an invalid state on
> exceptions. And probably default construction on that.
>
What I meant was default construction as specified in N4542/P0088R0.
Namely, construct the first 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3986_761553858.1445818079356
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Sunday, October 25, 2015 at 8:07:00 PM UTC-4, N=
icol Bolas wrote:<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">According to Herb Sutter, <a href=3D"http://herbsutter.com/2015/10/25/2=
568/" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'ht=
tp://www.google.com/url?q\75http%3A%2F%2Fherbsutter.com%2F2015%2F10%2F25%2F=
2568%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNGsRz9qSYKMwyeQC_mXJ7qoYfGNvA'=
;;return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75h=
ttp%3A%2F%2Fherbsutter.com%2F2015%2F10%2F25%2F2568%2F\46sa\75D\46sntz\0751\=
46usg\75AFQjCNGsRz9qSYKMwyeQC_mXJ7qoYfGNvA';return true;">it is done</a=
>. Finally. And apparently, it's just N4542/P0088R0. AKA: never-empty, =
but with an invalid state on exceptions. And probably default construction =
on that.<br></div></blockquote><div><br>What I meant was default constructi=
on as specified in N4542/P0088R0. Namely, construct the first type.</div><b=
r></div>
<p></p>
-- <br />
<br />
--- <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 />
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_3986_761553858.1445818079356--
------=_Part_3985_720601009.1445818079355--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 27 Oct 2015 10:03:18 -0700
Raw View
--089e01228a56ece96f0523190de2
Content-Type: text/plain; charset=UTF-8
On Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> According to Herb Sutter, it is done
> <http://herbsutter.com/2015/10/25/2568/>. Finally. And apparently, it's
> just N4542/P0088R0. AKA: never-empty, but with an invalid state on
> exceptions. And probably default construction on that.
>
I wouldn't exactly say it's done, as there is still a fair amount to do,
but there was consensus. FWIW, even I was weakly in favor of this, though
I'd still prefer constrained assignment. It was clear that it would be
difficult to push for such an approach as only Howard and I and a couple of
others really felt that constrained assignment was a better approach.
To be clear, the variant that the we are moving forward with is *not*
never-empty -- possible invalid state on exceptions during assignment and
emplacement is precisely why it is not never-empty. IIRC, there was
consensus that we will not default construction to the invalid state (I
don't know remember if there was a poll at this meeting for it, but there
was fairly clear agreement). The reason why it doesn't default to invalid
is because that would be one more way to get into the invalid state. The
idea from those in favor of the invalid state is that you can only get into
that state by way of failed assignment or emplacement, so in practice you
don't need to check for it (a sentiment that I strongly disagree with as
IMO it means the rare bugs will just be more subtle, but it is better than
an empty state that is more prominent). There was some bike-shedding about
naming the function for the invalid state and I think we ended up with
".corrupted_by_exception()."
On Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Oh, and it'll throw instead of issue undefined behavior if you do things
> with an invalid variant. Which means that visitation can't be a noexcept
> operation. Not that it was `noexcept` before, but it would have been nice
> to have it be noexcept if all of the operator()'s it could call were
> noexcept too.
>
Yeah, I am really against that aspect and I'm planning on writing a
proposal to turn it to UB, but I'm not sure how well that will go. IMO, any
operations on a variant when in the invalid state, other than checking if
you are in that invalid state, should be UB. It should just be a
precondition violation.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e01228a56ece96f0523190de2
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 S=
un, Oct 25, 2015 at 5:06 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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">According to Herb Sutter, =
<a href=3D"http://herbsutter.com/2015/10/25/2568/" target=3D"_blank">it is =
done</a>. Finally. And apparently, it's just N4542/P0088R0. AKA: never-=
empty, but with an invalid state on exceptions. And probably default constr=
uction on that.<br></div></blockquote><div><br></div><div>I wouldn't ex=
actly say it's done, as there is still a fair amount to do, but there w=
as consensus. FWIW, even I was weakly in favor of this, though I'd stil=
l prefer constrained assignment. It was clear that it would be difficult to=
push for such an approach as only Howard and I and a couple of others real=
ly felt that constrained assignment was a better approach.</div><div><br></=
div><div>To be clear, the variant that the we are moving forward with is <i=
>not</i> never-empty -- possible invalid state on exceptions during assignm=
ent and emplacement is precisely why it is not never-empty. IIRC, there was=
consensus that we will not default construction to the invalid state (I do=
n't know remember if there was a poll at this meeting for it, but there=
was fairly clear agreement). The reason why it doesn't default to inva=
lid is because that would be one more way to get into the invalid state. Th=
e idea from those in favor of the invalid state is that you can only get in=
to that state by way of failed assignment or emplacement, so in practice yo=
u don't need to check for it (a sentiment that I strongly disagree with=
as IMO it means the rare bugs will just be more subtle, but it is better t=
han an empty state that is more prominent). There was some bike-shedding ab=
out naming the function for the invalid state and I think we ended up with =
".corrupted_by_exception()."</div><div><br></div><div>On Sun, Oct=
25, 2015 at 5:06 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mai=
lto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></spa=
n>=C2=A0wrote:=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"><div dir=3D"ltr">Oh, and it'=
ll throw instead of issue undefined behavior if you do things with an inval=
id variant. Which means that visitation can't be a noexcept operation. =
Not that it was `noexcept` before, but it would have been nice to have it b=
e noexcept if all of the operator()'s it could call were noexcept too.<=
br></div></blockquote><div><br></div><div>Yeah, I am really against that as=
pect and I'm planning on writing a proposal to turn it to UB, but I'=
;m not sure how well that will go. IMO, any operations on a variant when in=
the invalid state, other than checking if you are in that invalid state, s=
hould be UB. It should just be a precondition violation.</div></div></div><=
/div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01228a56ece96f0523190de2--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 27 Oct 2015 10:06:06 -0700
Raw View
--001a113de976efeab90523191779
Content-Type: text/plain; charset=UTF-8
On Sun, Oct 25, 2015 at 5:07 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>
> On Sunday, October 25, 2015 at 8:07:00 PM UTC-4, Nicol Bolas wrote:
>>
>> According to Herb Sutter, it is done
>> <http://herbsutter.com/2015/10/25/2568/>. Finally. And apparently, it's
>> just N4542/P0088R0. AKA: never-empty, but with an invalid state on
>> exceptions. And probably default construction on that.
>>
>
> What I meant was default construction as specified in N4542/P0088R0.
> Namely, construct the first type.
>
I should have read this reply before responding to your previous post.
Yeah, I'm pretty sure that's what we went with, with no default
construction if the first type is not default constructible. I imagine some
of the details around all of this may still change, but I doubt there will
be very large design-level changes.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113de976efeab90523191779
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 S=
un, Oct 25, 2015 at 5:07 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> 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""><br><br>On Sunday, October 25, 2015 at 8:07:00 PM UTC-4, Nicol Bolas =
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">According to=
Herb Sutter, <a href=3D"http://herbsutter.com/2015/10/25/2568/" rel=3D"nof=
ollow" target=3D"_blank">it is done</a>. Finally. And apparently, it's =
just N4542/P0088R0. AKA: never-empty, but with an invalid state on exceptio=
ns. And probably default construction on that.<br></div></blockquote></span=
><div><br>What I meant was default construction as specified in N4542/P0088=
R0. Namely, construct the first type.</div></div></blockquote><div><br></di=
v><div>I should have read this reply before responding to your previous pos=
t. Yeah, I'm pretty sure that's what we went with, with no default =
construction if the first type is not default constructible. I imagine some=
of the details around all of this may still change, but I doubt there will=
be very large design-level changes.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113de976efeab90523191779--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 27 Oct 2015 12:37:49 -0500
Raw View
--001a1143f1c0b75d290523198b34
Content-Type: text/plain; charset=UTF-8
On 27 October 2015 at 12:03, 'Matt Calabrese' via ISO C++ Standard - Future
Proposals <std-proposals@isocpp.org> wrote:
> The idea from those in favor of the invalid state is that you can only get
> into that state by way of failed assignment or emplacement, so in practice
> you don't need to check for it (a sentiment that I strongly disagree with
> as IMO it means the rare bugs will just be more subtle, but it is better
> than an empty state that is more prominent).
>
I just don't see how it is any more subtle than never-empty (as opposed to
the strong exception safety guarantee, which no one actually proposed).
Even with never-empty, while you can reason about what *type* the variant
is engaged with, it is still very difficult (if not impossible w/o knowing
the "from" state) to reason about the *value* that type has.
> There was some bike-shedding about naming the function for the invalid
> state and I think we ended up with ".corrupted_by_exception()."
>
Ugh. Putting words like "corrupted" in function names makes it difficult
to use in many regulated industries.
> On Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> Oh, and it'll throw instead of issue undefined behavior if you do things
>> with an invalid variant. Which means that visitation can't be a noexcept
>> operation. Not that it was `noexcept` before, but it would have been nice
>> to have it be noexcept if all of the operator()'s it could call were
>> noexcept too.
>>
>
> Yeah, I am really against that aspect and I'm planning on writing a
> proposal to turn it to UB, but I'm not sure how well that will go.
>
In other words, you want to revert back to n4542 behavior, right? Do you
have an argument for it that hasn't been brought up in the 2000+ email
messages or in person at Lenexa or Kona?
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143f1c0b75d290523198b34
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 27 October 2015 at 12:03, 'Matt Calabrese' via =
ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto=
:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>&g=
t;</span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><=
div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div>The idea from those in fav=
or of the invalid state is that you can only get into that state by way of =
failed assignment or emplacement, so in practice you don't need to chec=
k for it (a sentiment that I strongly disagree with as IMO it means the rar=
e bugs will just be more subtle, but it is better than an empty state that =
is more prominent).</div></div></div></div></blockquote><div><br></div><div=
>I just don't see how it is any more subtle than never-empty (as oppose=
d to the strong exception safety guarantee, which no one actually proposed)=
..=C2=A0 Even with never-empty, while you can reason about what <i>type</i>=
=C2=A0the variant is engaged with, it is still very difficult (if not impos=
sible w/o knowing the "from" state) to reason about the <i>value<=
/i>=C2=A0that type has.</div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><d=
iv> There was some bike-shedding about naming the function for the invalid =
state and I think we ended up with ".corrupted_by_exception()."</=
div></div></div></div></blockquote><div><br></div><div>Ugh.=C2=A0 Putting w=
ords like "corrupted" in function names makes it difficult to use=
in many regulated industries.</div><div>=C2=A0</div><blockquote class=3D"g=
mail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_qu=
ote"><span><div>On Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas=C2=A0<span dir=
=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmcke=
sson@gmail.com</a>></span>=C2=A0wrote:=C2=A0<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr">Oh, and it'll throw instead of issue undefined behavio=
r if you do things with an invalid variant. Which means that visitation can=
't be a noexcept operation. Not that it was `noexcept` before, but it w=
ould have been nice to have it be noexcept if all of the operator()'s i=
t could call were noexcept too.<br></div></blockquote><div><br></div></span=
><div>Yeah, I am really against that aspect and I'm planning on writing=
a proposal to turn it to UB, but I'm not sure how well that will go.</=
div></div></div></div></blockquote><div><br></div><div>In other words, you =
want to revert back to n4542 behavior, right?=C2=A0 Do you have an argument=
for it that hasn't been brought up in the 2000+ email messages or in p=
erson at Lenexa or Kona?</div></div>-- <br><div>=C2=A0Nevin ":-)"=
Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D=
"_blank">nevin@eviloverlord.com</a>>=C2=A0 <a href=3D"tel:%28847%29%2069=
1-1404" value=3D"+18476911404" target=3D"_blank">(847) 691-1404</a></div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143f1c0b75d290523198b34--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 27 Oct 2015 12:42:58 -0500
Raw View
--001a1144fadc26be1a0523199e26
Content-Type: text/plain; charset=UTF-8
On 25 October 2015 at 19:06, Nicol Bolas <jmckesson@gmail.com> wrote:
> Which means that visitation can't be a noexcept operation. Not that it was
> `noexcept` before, but it would have been nice to have it be noexcept if
> all of the operator()'s it could call were noexcept too.
>
Making it UB doesn't help this, as visitation would still require a
precondition, making it a narrow contract, and hence would not be marked
noexcept in the standard (although vendors would be free to add it).
Note: if it is a variant where never-empty can be achieved, then there is
no precondition and it could be marked noexcept.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1144fadc26be1a0523199e26
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra">On 25 October 2015 at 19:06, Ni=
col Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" targ=
et=3D"_blank">jmckesson@gmail.com</a>></span> wrote:<br><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"><div dir=3D"ltr">Which means that=
visitation can't be a noexcept operation. Not that it was `noexcept` b=
efore, but it would have been nice to have it be noexcept if all of the ope=
rator()'s it could call were noexcept too.<br></div></blockquote></div>=
<br>Making it UB doesn't help this, as visitation would still require a=
precondition, making it a narrow contract, and hence would not be marked n=
oexcept in the standard (although vendors would be free to add it).</div><d=
iv class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">Note: if it i=
s a variant where never-empty can be achieved, then there is no preconditio=
n and it could be marked noexcept.<br>-- <br><div class=3D"gmail_signature"=
>=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin=
@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (=
847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1144fadc26be1a0523199e26--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 27 Oct 2015 11:35:55 -0700
Raw View
--089e01175e4d35704605231a59d8
Content-Type: text/plain; charset=UTF-8
On Tue, Oct 27, 2015 at 10:37 AM, Nevin Liber <nevin@eviloverlord.com>
wrote:
> On 27 October 2015 at 12:03, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>
>> The idea from those in favor of the invalid state is that you can only
>> get into that state by way of failed assignment or emplacement, so in
>> practice you don't need to check for it (a sentiment that I strongly
>> disagree with as IMO it means the rare bugs will just be more subtle, but
>> it is better than an empty state that is more prominent).
>>
>
> I just don't see how it is any more subtle than never-empty (as opposed to
> the strong exception safety guarantee, which no one actually proposed).
> Even with never-empty, while you can reason about what *type* the variant
> is engaged with, it is still very difficult (if not impossible w/o knowing
> the "from" state) to reason about the *value* that type has.
>
It's probably not worth us talking about this much as it's all kind of moot
as it's clear than those in favor of truly never-empty (myself included)
are in the minority and I doubt that will change with further proposals and
discussions. My personal thoughts, though, are that reasoning about the
*value* that a truly never-empty variant has is no different from reasoning
about any other type that has associated functions with the basic exception
guarantee. That is to say, you can't rely on a specific value after an
exception is thrown, but we get there without having an extra kind of state
for the object. This is not a unique concern to variant. In practice, with
the current variant, I will be explicitly stating a precondition of
!corrupted_by_exception() for every function that deals with a variant, and
I'll be asserting that precondition. I don't really care that much (even I
did vote weakly in favor), I just feel that in an ideal world we wouldn't
have it, and that the way to get to a truly never-empty variant isn't as
questionable as people think (i.e. it's not some unimplementable,
pie-in-the-sky alternative). I doubt I'd be able to ever successfully
convince the committee as a whole otherwise, though. I might write a paper
just on principle, and I've gotten encouragement at the meeting from others
who want constrained assignment and an approach similar to what I've
described here, but I don't expect it to actually go anywhere.
On Tue, Oct 27, 2015 at 10:37 AM, Nevin Liber <nevin@eviloverlord.com>
wrote:
>
>
>> There was some bike-shedding about naming the function for the invalid
>> state and I think we ended up with ".corrupted_by_exception()."
>>
>
> Ugh. Putting words like "corrupted" in function names makes it difficult
> to use in many regulated industries.
>
I agree with you, however LWG does not :/ It was sent back to LEWG with an
explicit request to make the name more complicated than something like
"invalid' so that people would not be using it except in really specific
circumstances. I do not agree with this, but this was the decision. Upon
that, we had a multi-play poll in LEWG with something like 30 options for
complicated names, and I think ".corrupted_by_exception()" is what we ended
up with (other suggestions were things like
".failure_state_by_exception()," which was a leading contender, and the
comedy option ".unvariant()," which got 1 vote). In general, the committee
feels that not being in the invalid state is some kind of understood
precondition that you wouldn't even assert, which again, I consider odd and
a very questionable recommendation. If it's there and it is checkable, I'd
personally recommend being explicit about the precondition and asserting
it, just like one would do with any other easily-checkable precondition.
On Tue, Oct 27, 2015 at 10:37 AM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
>
>
>> On Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas <jmckesson@gmail.com>
>> wrote:
>>
>>> Oh, and it'll throw instead of issue undefined behavior if you do things
>>> with an invalid variant. Which means that visitation can't be a noexcept
>>> operation. Not that it was `noexcept` before, but it would have been nice
>>> to have it be noexcept if all of the operator()'s it could call were
>>> noexcept too.
>>>
>>
>> Yeah, I am really against that aspect and I'm planning on writing a
>> proposal to turn it to UB, but I'm not sure how well that will go.
>>
>
> In other words, you want to revert back to n4542 behavior, right? Do you
> have an argument for it that hasn't been brought up in the 2000+ email
> messages or in person at Lenexa or Kona?
>
I'm late to the game on this, obviously, and have a lot of reading to do --
this is just my personal stance. I will see what has been discussed and try
to make the case, but I'm well aware that it will probably not go through.
Still, I really do feel that this is worthwhile to pursue, and I don't want
to give up without personally writing a paper on the topic.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e01175e4d35704605231a59d8
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=
ue, Oct 27, 2015 at 10:37 AM, Nevin Liber <span dir=3D"ltr"><<a href=3D"=
mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>=
></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bor=
der-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On=
27 October 2015 at 12:03, 'Matt Calabrese' via ISO C++ Standard - =
Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@isoc=
pp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:<br=
></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=
=3D""><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmai=
l_extra"><div class=3D"gmail_quote"><div>The idea from those in favor of th=
e invalid state is that you can only get into that state by way of failed a=
ssignment or emplacement, so in practice you don't need to check for it=
(a sentiment that I strongly disagree with as IMO it means the rare bugs w=
ill just be more subtle, but it is better than an empty state that is more =
prominent).</div></div></div></div></blockquote><div><br></div></span><div>=
I just don't see how it is any more subtle than never-empty (as opposed=
to the strong exception safety guarantee, which no one actually proposed).=
=C2=A0 Even with never-empty, while you can reason about what <i>type</i>=
=C2=A0the variant is engaged with, it is still very difficult (if not impos=
sible w/o knowing the "from" state) to reason about the <i>value<=
/i>=C2=A0that type has.</div></div></div></div></blockquote><div><br></div>=
<div>It's probably not worth us talking about this much as it's all=
kind of moot as it's clear than those in favor of truly never-empty (m=
yself included) are in the minority and I doubt that will change with furth=
er proposals and discussions. My personal thoughts, though, are that reason=
ing about the <i>value</i>=C2=A0that a truly never-empty variant has is no =
different from reasoning about any other type that has associated functions=
with the basic exception guarantee. That is to say, you can't rely on =
a specific value after an exception is thrown, but we get there without hav=
ing an extra kind of state for the object. This is not a unique concern to =
variant. In practice, with the current variant, I will be explicitly statin=
g a precondition of !corrupted_by_exception() for every function that deals=
with a variant, and I'll be asserting that precondition. I don't r=
eally care that much (even I did vote weakly in favor), I just feel that in=
an ideal world we wouldn't have it, and that the way to get to a truly=
never-empty variant isn't as questionable as people think (i.e. it'=
;s not some unimplementable, pie-in-the-sky alternative). I doubt I'd b=
e able to ever successfully convince the committee as a whole otherwise, th=
ough. I might write a paper just on principle, and I've gotten encourag=
ement at the meeting from others who want constrained assignment and an app=
roach similar to what I've described here, but I don't expect it to=
actually go anywhere.</div><div><br></div><div>On Tue, Oct 27, 2015 at 10:=
37 AM, Nevin Liber=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:nevin@evilo=
verlord.com" target=3D"_blank">nevin@eviloverlord.com</a>></span>=C2=A0w=
rote:<br></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 class=3D"gmail_extra"=
><div class=3D"gmail_quote"><span class=3D""><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<div> There was some bike-shedding about naming the function for the invali=
d state and I think we ended up with ".corrupted_by_exception()."=
</div></div></div></div></blockquote><div><br></div></span><div>Ugh.=C2=A0 =
Putting words like "corrupted" in function names makes it difficu=
lt to use in many regulated industries.</div></div></div></div></blockquote=
><div><br></div><div>I agree with you, however LWG does not :/ It was sent =
back to LEWG with an explicit request to make the name more complicated tha=
n something like "invalid' so that people would not be using it ex=
cept in really specific circumstances. I do not agree with this, but this w=
as the decision. Upon that, we had a multi-play poll in LEWG with something=
like 30 options for complicated names, and I think ".corrupted_by_exc=
eption()" is what we ended up with (other suggestions were things like=
".failure_state_by_exception()," which was a leading contender, =
and the comedy option ".unvariant()," which got 1 vote). In gener=
al, the committee feels that not being in the invalid state is some kind of=
understood precondition that you wouldn't even assert, which again, I =
consider odd and a very questionable recommendation. If it's there and =
it is checkable, I'd personally recommend being explicit about the prec=
ondition and asserting it, just like one would do with any other easily-che=
ckable precondition.</div><div><br></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"><div dir=3D"ltr">=
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><span class=3D"">On T=
ue, Oct 27, 2015 at 10:37 AM, Nevin Liber=C2=A0<span dir=3D"ltr"><<a hre=
f=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.co=
m</a>></span>=C2=A0wrote:<div>=C2=A0</div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-col=
or:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"l=
tr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span><div>On Sun=
, Oct 25, 2015 at 5:06 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=
=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&g=
t;</span>=C2=A0wrote:=C2=A0<br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr">Oh, =
and it'll throw instead of issue undefined behavior if you do things wi=
th an invalid variant. Which means that visitation can't be a noexcept =
operation. Not that it was `noexcept` before, but it would have been nice t=
o have it be noexcept if all of the operator()'s it could call were noe=
xcept too.<br></div></blockquote><div><br></div></span><div>Yeah, I am real=
ly against that aspect and I'm planning on writing a proposal to turn i=
t to UB, but I'm not sure how well that will go.</div></div></div></div=
></blockquote><div><br></div></span><div>In other words, you want to revert=
back to n4542 behavior, right?=C2=A0 Do you have an argument for it that h=
asn't been brought up in the 2000+ email messages or in person at Lenex=
a or Kona?</div></div></div></div></blockquote><div><br></div><div>I'm =
late to the game on this, obviously, and have a lot of reading to do -- thi=
s is just my personal stance. I will see what has been discussed and try to=
make the case, but I'm well aware that it will probably not go through=
.. Still, I really do feel that this is worthwhile to pursue, and I don'=
t want to give up without personally writing a paper on the topic.</div></d=
iv></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01175e4d35704605231a59d8--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 27 Oct 2015 16:57:39 -0700 (PDT)
Raw View
------=_Part_7343_2126932262.1445990259128
Content-Type: multipart/alternative;
boundary="----=_Part_7344_938539860.1445990259128"
------=_Part_7344_938539860.1445990259128
Content-Type: text/plain; charset=UTF-8
An idea just occurred to me.
Since the variant can be made invalid/corrupted/etc, there should probably
be a function called `repair_valid`. If the variant is invalid, it will
rebuild the variant as if constructed with the variant's default type. The
function will be noexcept if the default argument is noexcept. If the first
argument is not default constructable, then that function should SFINAE
disappear.
It could even have overloads that mimic variant emplacement operations. The
function doesn't even need to be a member.
On Tuesday, October 27, 2015 at 2:35:58 PM UTC-4, Matt Calabrese wrote:
>
> In practice, with the current variant, I will be explicitly stating a
> precondition of !corrupted_by_exception() for every function that deals
> with a variant, and I'll be asserting that precondition. I don't really
> care that much (even I did vote weakly in favor), I just feel that in an
> ideal world we wouldn't have it, and that the way to get to a truly
> never-empty variant isn't as questionable as people think (i.e. it's not
> some unimplementable, pie-in-the-sky alternative).
>
I don't think anyone opposed your idea as being "unimplementable" or
"pie-in-the-sky". It was more "over my dead body".
In general, the committee feels that not being in the invalid state is some
> kind of understood precondition that you wouldn't even assert, which again,
> I consider odd and a very questionable recommendation. If it's there and it
> is checkable, I'd personally recommend being explicit about the
> precondition and asserting it, just like one would do with any other
> easily-checkable precondition.
>
Except that in normal use, you'll never hit it.
The invalid/corrupted state will only be encountered if assignment or
emplacement on a variant fails. That's actually exceedingly rare. First,
assignment/emplacement on objects is a lot less common than most people
think. Usually, objects passed around by value are move constructed, and
then moved into some other object that's being constructed. The typical
syntax being `auto var = ...`. In-object reassignment is a lot less
frequent.
It is at least theoretically possible to structure your code so that you
can guarantee that no variant is invalid, even if your variant contains
throwing move types. In which case, there's no need to check for anything.
Indeed, static analysis tools can be used to detect places where a variant
could theoretically become invalid. That might be a good safety core
guideline: don't assign/emplace into a live variant if the selected
operation for the available types could throw. That's something that can be
tested for statically.
Second, most objects fail on assignment/emplacement due to problems that
are usually not recoverable. Most applications don't even try to recover
from `std::bad_alloc`; if that failed, the application terminates. Maybe it
spits out a message or something, but that's it. Other applications that
cannot afford to terminate will handle it, but the handling will almost
never be local. And thus, the variant's disposition will likely be
irrelevant; the object will have been destroyed somewhere in the stack
unwinding.
So even if the invalid state is reached, the object will be likely
destroyed before anyone touches it. Unfortunately, verifying this requires
a bit more than static analysis can pull off.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7344_938539860.1445990259128
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">An idea just occurred to me.<br><br>Since the variant can =
be made invalid/corrupted/etc, there should probably be a function called `=
repair_valid`. If the variant is invalid, it will rebuild the variant as if=
constructed with the variant's default type. The function will be noex=
cept if the default argument is noexcept. If the first argument is not defa=
ult constructable, then that function should SFINAE disappear.<br><br>It co=
uld even have overloads that mimic variant emplacement operations. The func=
tion doesn't even need to be a member.<br><br>On Tuesday, October 27, 2=
015 at 2:35:58 PM UTC-4, Matt Calabrese wrote:<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><div>In practice, with the curre=
nt variant, I will be explicitly stating a precondition of !corrupted_by_ex=
ception() for every function that deals with a variant, and I'll be ass=
erting that precondition. I don't really care that much (even I did vot=
e weakly in favor), I just feel that in an ideal world we wouldn't have=
it, and that the way to get to a truly never-empty variant isn't as qu=
estionable as people think (i.e. it's not some unimplementable, pie-in-=
the-sky alternative).</div></div></div></div></blockquote><div><br>I don=
9;t think anyone opposed your idea as being "unimplementable" or =
"pie-in-the-sky". It was more "over my dead body".<br><=
/div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div><div>In general, the committee feels that not being in t=
he invalid state is some kind of understood precondition that you wouldn=
9;t even assert, which again, I consider odd and a very questionable recomm=
endation. If it's there and it is checkable, I'd personally recomme=
nd being explicit about the precondition and asserting it, just like one wo=
uld do with any other easily-checkable precondition.</div></div></div></div=
></blockquote><div><br>Except that in normal use, you'll never hit it.<=
br><br>The invalid/corrupted state will only be encountered if assignment o=
r emplacement on a variant fails. That's actually exceedingly rare. Fir=
st, assignment/emplacement on objects is a lot less common than most people=
think. Usually, objects passed around by value are move constructed, and t=
hen moved into some other object that's being constructed. The typical =
syntax being `auto var =3D ...`. In-object reassignment is a lot less frequ=
ent.<br><br>It is at least theoretically possible to structure your code so=
that you can guarantee that no variant is invalid, even if your variant co=
ntains throwing move types.=20
In which case, there's no need to check for anything.<br><br>Indeed, st=
atic analysis tools can be used to detect places where a variant could theo=
retically become invalid. That might be a good safety core guideline: don&#=
39;t assign/emplace into a live variant if the selected operation for the a=
vailable types could throw. That's something that can be tested for sta=
tically.<br><br>Second, most objects fail on assignment/emplacement due to =
problems that are usually not recoverable. Most applications don't even=
try to recover from `std::bad_alloc`; if that failed, the application term=
inates. Maybe it spits out a message or something, but that's it. Other=
applications that cannot afford to terminate will handle it, but the handl=
ing will almost never be local. And thus, the variant's disposition wil=
l likely be irrelevant; the object will have been destroyed somewhere in th=
e stack unwinding.<br><br>So even if the invalid state is reached, the obje=
ct will be likely destroyed before anyone touches it. Unfortunately, verify=
ing this requires a bit more than static analysis can pull off.<br></div></=
div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7344_938539860.1445990259128--
------=_Part_7343_2126932262.1445990259128--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 27 Oct 2015 19:03:45 -0500
Raw View
--001a11c01300eb81d305231eef91
Content-Type: text/plain; charset=UTF-8
On 27 October 2015 at 18:57, Nicol Bolas <jmckesson@gmail.com> wrote:
> An idea just occurred to me.
>
> Since the variant can be made invalid/corrupted/etc, there should probably
> be a function called `repair_valid`. If the variant is invalid, it will
> rebuild the variant as if constructed with the variant's default type.
>
Why do you need a special function, given that you can do the exact same
thing with assignment, complete with having to handle it possibly
throwing? Plus, if you are going to repair it, you are far better off
being explicit about what state you are putting it into.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c01300eb81d305231eef91
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 27 October 2015 at 18:57, Nicol Bolas <span dir=3D"ltr"=
><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gma=
il.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"><div dir=3D"ltr">An idea just occ=
urred to me.<br><br>Since the variant can be made invalid/corrupted/etc, th=
ere should probably be a function called `repair_valid`. If the variant is =
invalid, it will rebuild the variant as if constructed with the variant'=
;s default type.</div></blockquote><div><br></div><div>Why do you need a sp=
ecial function, given that you can do the exact same thing with assignment,=
complete with having to handle it possibly throwing?=C2=A0 Plus, if you ar=
e going to repair it, you are far better off being explicit about what stat=
e you are putting it into.</div></div>-- <br><div>=C2=A0Nevin ":-)&quo=
t; Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=
=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 <a href=3D"tel:%28847%29%2=
0691-1404" value=3D"+18476911404" target=3D"_blank">(847) 691-1404</a></div=
>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c01300eb81d305231eef91--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 27 Oct 2015 17:27:09 -0700
Raw View
--001a1134fb0a4a9b0d05231f4187
Content-Type: text/plain; charset=UTF-8
On Tue, Oct 27, 2015 at 4:57 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> An idea just occurred to me.
>
> Since the variant can be made invalid/corrupted/etc, there should probably
> be a function called `repair_valid`. If the variant is invalid, it will
> rebuild the variant as if constructed with the variant's default type. The
> function will be noexcept if the default argument is noexcept. If the first
> argument is not default constructable, then that function should SFINAE
> disappear.
>
> It could even have overloads that mimic variant emplacement operations.
> The function doesn't even need to be a member.
>
Seems reasonable. I'm guessing the idea here is that it's a shorthand for
emplacement without the user having to explicitly specify the underlying
field type?
On Tue, Oct 27, 2015 at 4:57 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, October 27, 2015 at 2:35:58 PM UTC-4, Matt Calabrese wrote:
>>
>> In practice, with the current variant, I will be explicitly stating a
>> precondition of !corrupted_by_exception() for every function that deals
>> with a variant, and I'll be asserting that precondition. I don't really
>> care that much (even I did vote weakly in favor), I just feel that in an
>> ideal world we wouldn't have it, and that the way to get to a truly
>> never-empty variant isn't as questionable as people think (i.e. it's not
>> some unimplementable, pie-in-the-sky alternative).
>>
>
> I don't think anyone opposed your idea as being "unimplementable" or
> "pie-in-the-sky". It was more "over my dead body".
>
True. At least a couple of respected library folks I spoke with at the
meeting thought my solution was better than alternatives, but the seemingly
more numerous "over my dead body" contingent would probably put a stop to
that. I might still finish my paper on this "just because", but I doubt it
will change anything.
On Tue, Oct 27, 2015 at 4:57 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> In general, the committee feels that not being in the invalid state is
>> some kind of understood precondition that you wouldn't even assert, which
>> again, I consider odd and a very questionable recommendation. If it's there
>> and it is checkable, I'd personally recommend being explicit about the
>> precondition and asserting it, just like one would do with any other
>> easily-checkable precondition.
>>
>
> Except that in normal use, you'll never hit it.
>
Right, I just think that the distinction between "normal" and abnormal
cases is somewhat of a misguided distinction to make when you're talking
about preconditions and checks in functions. Violation of *any*
precondition is by some definition an abnormal case, and explicit statement
of preconditions on functions and implementations providing asserts to
check these preconditions upfront shouldn't really be dependent on how rare
someone perceives the violation to be. Asserts are there to check for odd
programmer mistakes, no matter how rare, and I think the choice of what to
assert on shouldn't be made based on how likely or unlikely it is that the
mistake will come up. Anyway, this is moot because I doubt consensus will
be changed, and while I do not like the invalid state, it's more just an
annoyance than something that would prevent correct code from being
written. That we don't default-construct to the state helps a little, but I
still don't like it.
On Tue, Oct 27, 2015 at 4:57 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> It is at least theoretically possible to structure your code so that you
> can guarantee that no variant is invalid, even if your variant contains
> throwing move types.
>
Perhaps, but you'd probably want to sanity check that your expectations are
actually correct if you are relying on them, in which case you'd be doing
some combination of static_asserting and asserting at run-time.
Anyway, again, I don't want to revive the controversy. I doubt I'll be able
to sway anyone else's opinion on the matter and I don't have much of a
desire to push further.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134fb0a4a9b0d05231f4187
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=
ue, Oct 27, 2015 at 4:57 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><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">An idea just occurred to m=
e.<br><br>Since the variant can be made invalid/corrupted/etc, there should=
probably be a function called `repair_valid`. If the variant is invalid, i=
t will rebuild the variant as if constructed with the variant's default=
type. The function will be noexcept if the default argument is noexcept. I=
f the first argument is not default constructable, then that function shoul=
d SFINAE disappear.<br><br>It could even have overloads that mimic variant =
emplacement operations. The function doesn't even need to be a member.<=
/div></blockquote><div><br></div><div>Seems reasonable. I'm guessing th=
e idea here is that it's a shorthand for emplacement without the user h=
aving to explicitly specify the underlying field type?</div><div>=C2=A0</di=
v><div>On Tue, Oct 27, 2015 at 4:57 PM, Nicol Bolas=C2=A0<span dir=3D"ltr">=
<<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmai=
l.com</a>></span>=C2=A0wrote:</div><blockquote class=3D"gmail_quote" sty=
le=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"><sp=
an class=3D"">On Tuesday, October 27, 2015 at 2:35:58 PM UTC-4, Matt Calabr=
ese wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div><div><div>In practice, wit=
h the current variant, I will be explicitly stating a precondition of !corr=
upted_by_exception() for every function that deals with a variant, and I=
9;ll be asserting that precondition. I don't really care that much (eve=
n I did vote weakly in favor), I just feel that in an ideal world we wouldn=
't have it, and that the way to get to a truly never-empty variant isn&=
#39;t as questionable as people think (i.e. it's not some unimplementab=
le, pie-in-the-sky alternative).</div></div></div></div></blockquote></span=
><div><br>I don't think anyone opposed your idea as being "unimple=
mentable" or "pie-in-the-sky". It was more "over my dea=
d body".<br></div></div></blockquote><div><br></div><div>True. At leas=
t a couple of respected library folks I spoke with at the meeting thought m=
y solution was better than alternatives, but the seemingly more numerous &q=
uot;over my dead body" contingent would probably put a stop to that. I=
might still finish my paper on this "just because", but I doubt =
it will change anything.</div><div><br></div><div>On Tue, Oct 27, 2015 at 4=
:57 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@=
gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div><div><div>In general, the committee feels that not be=
ing in the invalid state is some kind of understood precondition that you w=
ouldn't even assert, which again, I consider odd and a very questionabl=
e recommendation. If it's there and it is checkable, I'd personally=
recommend being explicit about the precondition and asserting it, just lik=
e one would do with any other easily-checkable precondition.</div></div></d=
iv></div></blockquote></span><div><br>Except that in normal use, you'll=
never hit it.<br></div></div></blockquote><div><br></div><div>Right, I jus=
t think that the distinction between "normal" and abnormal cases =
is somewhat of a misguided distinction to make when you're talking abou=
t preconditions and checks in functions. Violation of <i>any</i> preconditi=
on is by some definition an abnormal case, and explicit statement of precon=
ditions on functions and implementations providing asserts to check these p=
reconditions upfront shouldn't really be dependent on how rare someone =
perceives the violation to be. Asserts are there to check for odd programme=
r mistakes, no matter how rare, and I think the choice of what to assert on=
shouldn't be made based on how likely or unlikely it is that the mista=
ke will come up. Anyway, this is moot because I doubt consensus will be cha=
nged, and while I do not like the invalid state, it's more just an anno=
yance than something that would prevent correct code from being written. Th=
at we don't default-construct to the state helps a little, but I still =
don't like it.</div><div><br></div><div>On Tue, Oct 27, 2015 at 4:57 PM=
, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.=
com" target=3D"_blank">jmckesson@gmail.com</a>></span>=C2=A0wrote:=C2=A0=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>It is at least theoretically p=
ossible to structure your code so that you can guarantee that no variant is=
invalid, even if your variant contains throwing move types.<br></div></div=
></blockquote><div><br></div><div>Perhaps, but you'd probably want to s=
anity check that your expectations are actually correct if you are relying =
on them, in which case you'd be doing some combination of static_assert=
ing and asserting at run-time.</div><div><br></div><div>Anyway, again, I do=
n't want to revive the controversy. I doubt I'll be able to sway an=
yone else's opinion on the matter and I don't have much of a desire=
to push further.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134fb0a4a9b0d05231f4187--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 28 Oct 2015 03:02:13 +0200
Raw View
On 28 October 2015 at 02:27, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals
>>> In practice, with the current variant, I will be explicitly stating a
>>> precondition of !corrupted_by_exception() for every function that deals with
>>> a variant, and I'll be asserting that precondition. I don't really care that
>>> much (even I did vote weakly in favor), I just feel that in an ideal world
>>> we wouldn't have it, and that the way to get to a truly never-empty variant
>>> isn't as questionable as people think (i.e. it's not some unimplementable,
>>> pie-in-the-sky alternative).
>> I don't think anyone opposed your idea as being "unimplementable" or
>> "pie-in-the-sky". It was more "over my dead body".
> True. At least a couple of respected library folks I spoke with at the
> meeting thought my solution was better than alternatives, but the seemingly
> more numerous "over my dead body" contingent would probably put a stop to
> that. I might still finish my paper on this "just because", but I doubt it
> will change anything.
Note this part of what Nevin wrote very carefully:
"Making it UB doesn't help this, as visitation would still require a
precondition, making it a narrow contract, and hence would not be
marked noexcept in the standard (although vendors would be free to add
it).
Note: if it is a variant where never-empty can be achieved, then there
is no precondition and it could be marked noexcept."
If visitation is made UB with a precondition, it won't be noexcept anyway.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Tue, 27 Oct 2015 23:18:52 -0300
Raw View
On 10/27/2015 10:02 PM, Ville Voutilainen wrote:
> Note: if it is a variant where never-empty can be achieved, then there
> is no precondition and it could be marked noexcept."
I do not think such a mythical beast exists, `emplace` will execute=20
arbitrary user defined code after all. Consider:
struct nasty { operator int() const { throw 42; } };
variant<int, float> v;
// v has an int now (I think)
v.emplace<int>(nasty{});
// what now?
Is the Kona variant empty when `emplace` exits via an exception?
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Nevin \":-)\" Liber" <"Nevin ":-)" Liber" <nliber@gmail.com>>
Date: Tue, 27 Oct 2015 21:50:58 -0500
Raw View
On Oct 27, 2015, at 9:18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <kaballo86@hot=
mail.com> wrote:
>=20
> I do not think such a mythical beast exists, `emplace` will execute arbit=
rary user defined code after all. Consider:
>=20
> struct nasty { operator int() const { throw 42; } };
>=20
> variant<int, float> v;
> // v has an int now (I think)
> v.emplace<int>(nasty{});
> // what now?
I don't see why this is a problem. Just because something that creates an i=
nt can throw doesn't mean that the emplace can throw.=20
Otherwise, how do you mark any function anywhere that takes a parameter as =
noexcept?
A common example is assignment that uses the copy-swap idiom can be marked =
noexcept if the rhs is passed in by value and the swap is noexcept.=20
--=20
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (312) 623-5420
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 28 Oct 2015 00:06:41 -0300
Raw View
On 10/27/2015 11:50 PM, Nevin - Liber wrote:
> On Oct 27, 2015, at 9:18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <kaballo86@h=
otmail.com> wrote:
>>
>> I do not think such a mythical beast exists, `emplace` will execute arbi=
trary user defined code after all. Consider:
>>
>> struct nasty { operator int() const { throw 42; } };
>>
>> variant<int, float> v;
>> // v has an int now (I think)
>> v.emplace<int>(nasty{});
>> // what now?
>
> I don't see why this is a problem. Just because something that creates an=
int can throw doesn't mean that the emplace can throw.
It is a problem because it happens within the body of `emplace`, not=20
while evaluating its arguments. I tried the following:
std::experimental::optional<int> o({});
std::cout << bool(o);
try {
o.emplace(nasty{});
} catch (...) {
std::cout << bool(o);
}
and that prints '10' on both implementations I tried. The Lenexa variant=20
would have behaved in a similar way, becoming empty after the failed=20
emplacement. I believe the Kona variant does the same, but I will have=20
to wait for the post-mailing.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Nevin \":-)\" Liber" <"Nevin ":-)" Liber" <nliber@gmail.com>>
Date: Tue, 27 Oct 2015 22:30:18 -0500
Raw View
> On Oct 27, 2015, at 10:06 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <kaballo86@=
hotmail.com> wrote:
>=20
> std::experimental::optional<int> o({});
> std::cout << bool(o);
> try {
> o.emplace(nasty{});
> } catch (...) {
> std::cout << bool(o);
> }
Why is this conceptually different than
struct Bad {
operator string() const { throw 42; }
};
string s(bad());
Last I checked, string has a noexcept move constructor.
If what you say is true, I'm looking forward to reading your proposal to re=
move noexcept from all the move constructors / assignment operators that ar=
e in the standard library.=20
--=20
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (312) 623-5420
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Agust=c3=adn_K-ballo_Berg=c3=a9?= <kaballo86@hotmail.com>
Date: Wed, 28 Oct 2015 00:42:57 -0300
Raw View
On 10/28/2015 12:30 AM, Nevin - Liber wrote:
>
>
>> On Oct 27, 2015, at 10:06 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <kaballo86=
@hotmail.com> wrote:
>>
>> std::experimental::optional<int> o({});
>> std::cout << bool(o);
>> try {
>> o.emplace(nasty{});
>> } catch (...) {
>> std::cout << bool(o);
>> }
>
> Why is this conceptually different than
>
> struct Bad {
> operator string() const { throw 42; }
> };
>
> string s(bad());
>
> Last I checked, string has a noexcept move constructor.
No move constructor, noexcept or otherwise, is involved in the=20
`variant`/`optional` example.
> If what you say is true, I'm looking forward to reading your proposal to =
remove noexcept from all the move constructors / assignment operators that =
are in the standard library.
I fail to see how such a paper would be relevant, note that we are not=20
talking about move construction/assignment but about `emplace` here,=20
which runs arbitrary user defined code (after having disposed of the=20
active member) deep within its bowels, as I said in my original mail.
I added the `optional` snippet so that you could confirm what I am=20
describing by your own means, please do spend some time with it before=20
moving the conversation forward.
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 27 Oct 2015 23:56:32 -0500
Raw View
--001a113da7d2062b7e0523230764
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On 27 October 2015 at 22:42, Agust=C3=ADn K-ballo Berg=C3=A9 <kaballo86@hot=
mail.com>
wrote:
> I fail to see how such a paper would be relevant, note that we are not
> talking about move construction/assignment but about `emplace` here, whic=
h
> runs arbitrary user defined code (after having disposed of the active
> member) deep within its bowels, as I said in my original mail.
>
emplace *does not* run arbitrary user defined code. When it is
instantiated (since it is a function template), it calls a *specific*
constructor. If that constructor is noexcept, there is *no reason* that
the emplace cannot also be noexcept. That would be conditionally noexcept,
unless the compiler knows that all
constructors called are noexcept, in which case the emplace would be
unconditionally noexcept(true).
How can it know? It certainly can if all the types are fundamental types.
Reflection may solve this in the future for user defined types.
Weird platforms that map floating point exceptions into C++ exceptions
notwithstanding, variant<int, float> *cannot* get into the invalid state,
so its emplace function template can be marked noexcept(true).
I added the `optional` snippet so that you could confirm what I am
> describing by your own means, please do spend some time with it before
> moving the conversation forward.
struct nasty { operator int() const { throw 42; } };
> std::experimental::optional<int> o({});
std::cout << bool(o);
> try {
> o.emplace(nasty{});
> } catch (...) {
> std::cout << bool(o);
> }
1. nasty is default constructed.
2. nasty throws an exception when converted to an int.
I don't see where *any* code of the optional<int> implementation is being
executed.
Because int is a fundamental type, the emplace method could be marked
noexcept. If what you are saying was true, if the emplace method for
optional<int> was marked noexcept(true), then the program would terminate.
Care to make a wager? :-)
This has nothing to do with optional/variant. These are the language rules
of C++11/14.
--=20
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--=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/.
--001a113da7d2062b7e0523230764
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 27 October 2015 at 22:42, Agust=C3=ADn K-ballo Berg=C3=
=A9 <span dir=3D"ltr"><<a href=3D"mailto:kaballo86@hotmail.com" target=
=3D"_blank">kaballo86@hotmail.com</a>></span> wrote:<br><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" sty=
le=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">I fail to see how su=
ch a paper would be relevant, note that we are not talking about move const=
ruction/assignment but about `emplace` here, which runs arbitrary user defi=
ned code (after having disposed of the active member) deep within its bowel=
s, as I said in my original mail.<br></blockquote><div><br></div><div>empla=
ce <i>does not</i>=C2=A0run arbitrary user defined code.=C2=A0 When it is i=
nstantiated (since it is a function template), it calls a <i>specific</i> c=
onstructor.=C2=A0 If that constructor is noexcept, there is <i>no reason</i=
>=C2=A0that the emplace cannot also be noexcept.=C2=A0 That would be condit=
ionally noexcept, unless the compiler knows that all </div><div>constructor=
s called are noexcept, in which case the emplace would be unconditionally n=
oexcept(true).</div><div><br></div><div>How can it know?=C2=A0 It certainly=
can if all the types are fundamental types.=C2=A0 Reflection may solve thi=
s in the future for user defined types.</div><div><br></div><div>Weird plat=
forms that map floating point exceptions into C++ exceptions notwithstandin=
g, variant<int, float> <i>cannot</i>=C2=A0get into the invalid state,=
so its emplace function template can be marked noexcept(true).</div><div><=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex">I added the `optional` snippet so that you could =
confirm what I am describing by your own means, please do spend some time w=
ith it before moving the conversation forward.</blockquote><div><br></div><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa=
dding-left:1ex"><span style=3D"font-size:13px">=C2=A0 =C2=A0=C2=A0</span><s=
pan style=3D"color:rgb(80,0,80);font-size:13px">struct nasty { operator int=
() const { throw 42; } };</span></blockquote><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"><span style=3D"font-size:13px">std::experimental::optional<in</span>=
<span style=3D"font-size:13px">t> o({});</span></blockquote><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex"><span style=3D"font-size:13px">=C2=A0 =C2=A0 std::cout << bool(o=
);<br></span><span style=3D"font-size:13px">=C2=A0 =C2=A0 try {<br></span><=
span style=3D"font-size:13px">=C2=A0 =C2=A0 =C2=A0 o.emplace(nasty{});<br><=
/span><span style=3D"font-size:13px">=C2=A0 =C2=A0 } catch (...) {<br></spa=
n><span style=3D"font-size:13px">=C2=A0 =C2=A0 =C2=A0 std::cout << bo=
ol(o);<br></span><span style=3D"font-size:13px">=C2=A0 =C2=A0 }</span></blo=
ckquote><div>=C2=A0</div><div><br></div><div>1. =C2=A0nasty is default cons=
tructed.</div><div>2. =C2=A0nasty throws an exception when converted to an =
int.</div><div><br></div><div>I don't see where <i>any</i> code of the =
optional<int> implementation is being executed.</div><div><br></div><=
div>Because int is a fundamental type, the emplace method could be marked n=
oexcept.=C2=A0 If what you are saying was true, if the emplace method for o=
ptional<int> was marked noexcept(true), then the program would termin=
ate.=C2=A0 Care to make a wager? :-)</div><div><br></div><div>This has noth=
ing to do with optional/variant.=C2=A0 These are the language rules of C++1=
1/14.</div></div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin ":-=
)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" ta=
rget=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113da7d2062b7e0523230764--
.
Author: Casey Carter <cartec69@gmail.com>
Date: Tue, 27 Oct 2015 22:22:42 -0700 (PDT)
Raw View
------=_Part_3174_198138202.1446009762671
Content-Type: multipart/alternative;
boundary="----=_Part_3175_1345574698.1446009762672"
------=_Part_3175_1345574698.1446009762672
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, October 27, 2015 at 11:57:15 PM UTC-5, Nevin ":-)" Liber wrote:
>
> On 27 October 2015 at 22:42, Agust=C3=ADn K-ballo Berg=C3=A9 <kaba...@hot=
mail.com=20
> <javascript:>> wrote:
>
> I fail to see how such a paper would be relevant, note that we are not=20
> talking about move construction/assignment but about `emplace` here, whic=
h=20
> runs arbitrary user defined code (after having disposed of the active=20
> member) deep within its bowels, as I said in my original mail.
>
>
> emplace *does not* run arbitrary user defined code. When it is=20
> instantiated (since it is a function template), it calls a *specific*=20
> constructor. If that constructor is noexcept, there is *no reason* that=
=20
> the emplace cannot also be noexcept. That would be conditionally noexcep=
t,=20
> unless the compiler knows that all=20
> constructors called are noexcept, in which case the emplace would be=20
> unconditionally noexcept(true).
>
>
N4542's member template <size_t I, class...Args> void emplace(Args&&...) ha=
s=20
effects specified as:
Destructs the currently contained value if valid() is true. Then=20
> initializes the contained value as if constructing a value of type tuple_=
element<I,=20
> variant> with the arguments std::forward(args)....
so in the case of v.emplace<I>{nasty{}}, v will destroy its contained=20
value, and then initialize its int member with something like new (&xxx)=20
int(nasty{}). That expression matches the copy constructor, which requires=
=20
the nasty to be converted to int, which throws leaving the variant in the=
=20
invalid (corrupted_by_exception?) state.
--=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_3175_1345574698.1446009762672
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, October 27, 2015 at 11:57:15 PM UTC-5, Nevin ":-)" Li=
ber 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">On =
27 October 2015 at 22:42, Agust=C3=ADn K-ballo Berg=C3=A9 <span dir=3D"ltr"=
><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"S1s=
VPanFEgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:'=
;;return true;" onclick=3D"this.href=3D'javascript:';return true;">=
kaba...@hotmail.com</a>></span> wrote:<br><div><blockquote style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,20=
4);border-left-style:solid;padding-left:1ex">I fail to see how such a paper=
would be relevant, note that we are not talking about move construction/as=
signment but about `emplace` here, which runs arbitrary user defined code (=
after having disposed of the active member) deep within its bowels, as I sa=
id in my original mail.<br></blockquote><div><br></div><div>emplace <i>does=
not</i>=C2=A0run arbitrary user defined code.=C2=A0 When it is instantiate=
d (since it is a function template), it calls a <i>specific</i> constructor=
..=C2=A0 If that constructor is noexcept, there is <i>no reason</i>=C2=A0tha=
t the emplace cannot also be noexcept.=C2=A0 That would be conditionally no=
except, unless the compiler knows that all </div><div>constructors called a=
re noexcept, in which case the emplace would be unconditionally noexcept(tr=
ue).</div><div><br></div></div></div></blockquote><div><br></div><div>N4542=
's member <font face=3D"courier new, monospace">template <size_t I, =
class...Args></font><font face=3D"courier new, monospace"><size_t i,=3D"=
" class...=3D"" args=3D"">=C2=A0void emplace(Args&&...)</size_t></f=
ont>=C2=A0has effects specified as:</div><div><br></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;">Destructs the currently contained value if <font face=3D"courie=
r new, monospace">valid()</font> is true. Then initializes
the contained value as if constructing a value of type <font face=3D"courie=
r new, monospace">tuple_element<I, variant></font><i, variant=3D""><f=
ont face=3D"courier new, monospace"> </font>with the arguments <font face=
=3D"courier new, monospace">std::forward</font><args><font face=3D"courier =
new, monospace">(args)...</font>.</args></i,></blockquote><div><i, variant=
=3D""><args><br></args></i,></div><div><i, variant=3D""><args>so in the cas=
e of <font face=3D"courier new, monospace">v.emplace<I>{nasty{}}</fon=
t>, v will destroy its contained value, and then initialize its int member =
with something like <font face=3D"courier new, monospace">new (&xxx) in=
t(nasty{}). </font><font face=3D"arial, sans-serif">That expression matches=
the copy constructor, which requires the </font><font face=3D"courier new,=
monospace">nasty</font><font face=3D"arial, sans-serif"> to be converted t=
o </font><font face=3D"courier new, monospace">int</font><font face=3D"aria=
l, sans-serif">, which throws leaving the variant in the invalid (corrupted=
_by_exception?) state.</font></args></i,></div><size_t i,=3D"" class...=3D"=
" args=3D""></size_t><div><font face=3D"courier new, monospace"><br></font>=
</div>
<p></p>
-- <br />
<br />
--- <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 />
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_3175_1345574698.1446009762672--
------=_Part_3174_198138202.1446009762671--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Wed, 28 Oct 2015 00:28:43 -0500
Raw View
--001a1143026e2101d20523237a16
Content-Type: text/plain; charset=UTF-8
On 28 October 2015 at 00:22, Casey Carter <cartec69@gmail.com> wrote:
> so in the case of v.emplace<I>{nasty{}}, v will destroy its contained
> value,
>
How?? The exception is thrown before
> and then initialize its int member with something like new (&xxx)
> int(nasty{}). That expression matches the copy constructor, which
> requires the nasty to be converted to int, which throws leaving the
> variant in the invalid (corrupted_by_exception?) state.
>
Ah, now I see it. Nasty. :-)
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143026e2101d20523237a16
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 28 October 2015 at 00:22, Casey Carter <span dir=3D"ltr=
"><<a href=3D"mailto:cartec69@gmail.com" target=3D"_blank">cartec69@gmai=
l.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gma=
il_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div>so in the case of <font face=
=3D"courier new, monospace">v.emplace<I>{nasty{}}</font>, v will dest=
roy its contained value,</div></blockquote><div><br></div><div>How??=C2=A0 =
The exception is thrown before =C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><=
div> and then initialize its int member with something like <font face=3D"c=
ourier new, monospace">new (&xxx) int(nasty{}). </font><font face=3D"ar=
ial, sans-serif">That expression matches the copy constructor, which requir=
es the </font><font face=3D"courier new, monospace">nasty</font><font face=
=3D"arial, sans-serif"> to be converted to </font><font face=3D"courier new=
, monospace">int</font><font face=3D"arial, sans-serif">, which throws leav=
ing the variant in the invalid (corrupted_by_exception?) state.</font></div=
></blockquote><div><br></div><div>Ah, now I see it.=C2=A0 Nasty. :-)</div><=
/div>-- <br><div class=3D"gmail_signature">=C2=A0Nevin ":-)" Libe=
r=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_bla=
nk">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143026e2101d20523237a16--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 28 Oct 2015 06:03:51 -0700 (PDT)
Raw View
------=_Part_453_1575733440.1446037431688
Content-Type: multipart/alternative;
boundary="----=_Part_454_1210147190.1446037431688"
------=_Part_454_1210147190.1446037431688
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 27, 2015 at 8:04:28 PM UTC-4, Nevin ":-)" Liber wrote:
>
> On 27 October 2015 at 18:57, Nicol Bolas <jmck...@gmail.com <javascript:>>
> wrote:
>
>> An idea just occurred to me.
>>
>> Since the variant can be made invalid/corrupted/etc, there should
>> probably be a function called `repair_valid`. If the variant is invalid, it
>> will rebuild the variant as if constructed with the variant's default type.
>>
>
> Why do you need a special function, given that you can do the exact same
> thing with assignment, complete with having to handle it possibly throwing?
>
I thought the point of a function is to not repeat code. Remember the "If
the variant is invalid" part. Which means that the function will
effectively be:
if(!v.is_valid())
//construction/assignment/etc.
I'd rather not have to copy&paste that.
> Plus, if you are going to repair it, you are far better off being explicit
> about what state you are putting it into.
>
First, it's being just as explicit as default construction, which is the
most likely to be non-throwing on construction. Second, I did say that it
could be extended to arbitrary emplacement operations. The main point is
that it's conditional.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_454_1210147190.1446037431688
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Tuesday, October 27, 2015 at 8:04:28 PM UTC-4, Nevin ":-)&q=
uot; Liber wrote:<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">On 27 October 2015 at 18:57, Nicol Bolas <span dir=3D"ltr"><<a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"_9X6L6-1EgAJ" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return tru=
e;" onclick=3D"this.href=3D'javascript:';return true;">jmck...@gmai=
l.com</a>></span> wrote:<br><div><div 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">An idea just occurred to me.<br><br>Sin=
ce the variant can be made invalid/corrupted/etc, there should probably be =
a function called `repair_valid`. If the variant is invalid, it will rebuil=
d the variant as if constructed with the variant's default type.</div><=
/blockquote><div><br></div><div>Why do you need a special function, given t=
hat you can do the exact same thing with assignment, complete with having t=
o handle it possibly throwing?</div></div></div></div></blockquote><div><br=
>I thought the point of a function is to not repeat code. Remember the &quo=
t;If the variant is invalid" part. Which means that the function will =
effectively be:<br><br><div class=3D"prettyprint" style=3D"background-color=
: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid=
; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by=
-prettify">if</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(!</span><span style=3D"color: #000;" class=3D"styled-by-prettify">v</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">is_valid</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">())</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D=
"color: #800;" class=3D"styled-by-prettify">//construction/assignment/etc.<=
/span></div></code></div><br>I'd rather not have to copy&paste that=
..<br>=C2=A0</div><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><div class=3D"gmail_quote"><div>Plus, if you are going to repair i=
t, you are far better off being explicit about what state you are putting i=
t into.<br></div></div></div></div></blockquote><div><br>First, it's be=
ing just as explicit as default construction, which is the most likely to b=
e non-throwing on construction. Second, I did say that it could be extended=
to arbitrary emplacement operations. The main point is that it's condi=
tional.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
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_454_1210147190.1446037431688--
------=_Part_453_1575733440.1446037431688--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 28 Oct 2015 06:17:24 -0700 (PDT)
Raw View
------=_Part_7878_1760640261.1446038244968
Content-Type: multipart/alternative;
boundary="----=_Part_7879_145529882.1446038244977"
------=_Part_7879_145529882.1446038244977
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, October 28, 2015 at 12:57:15 AM UTC-4, Nevin ":-)" Liber=20
wrote:
>
> On 27 October 2015 at 22:42, Agust=C3=ADn K-ballo Berg=C3=A9 <kaba...@hot=
mail.com=20
> <javascript:>> wrote:
>
> I fail to see how such a paper would be relevant, note that we are not=20
> talking about move construction/assignment but about `emplace` here, whic=
h=20
> runs arbitrary user defined code (after having disposed of the active=20
> member) deep within its bowels, as I said in my original mail.
>
>
> emplace *does not* run arbitrary user defined code. When it is=20
> instantiated (since it is a function template), it calls a *specific*=20
> constructor. If that constructor is noexcept, there is *no reason* that=
=20
> the emplace cannot also be noexcept. That would be conditionally noexcep=
t,=20
> unless the compiler knows that all=20
> constructors called are noexcept, in which case the emplace would be=20
> unconditionally noexcept(true).
>
I think you may have misunderstood his point.
`emplace` does in fact call a specific constructor. However, implicit=20
conversions to the appropriate types for that constructor happen *within*=
=20
the `emplace` operation itself, right before calling the constructor. At=20
some point, `emplace` will do this:
new(mem) T(std::forward<Args>(args)...);
And that is when the conversion happens, and therefore that is where the=20
exception is emitted. So even if the constructor selected is `noexcept`,=20
the conversions used to select it may not be.
It should be noted that none of the other standard library `emplace`-type=
=20
functions state that the function is `noexcept` if the selected constructor=
=20
is also `noexcept`.
--=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_7879_145529882.1446038244977
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Wednesday, October 28, 2015 at 12:57:15 AM UTC-4, Nevin ":-=
)" Liber wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On 27 October 2015 at 22:42, Agust=C3=ADn K-ballo Berg=C3=A9 <span=
dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-m=
ailto=3D"S1sVPanFEgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'jav=
ascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;">kaba...@hotmail.com</a>></span> wrote:<br><div><div><blockqu=
ote style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-col=
or:rgb(204,204,204);border-left-style:solid;padding-left:1ex">I fail to see=
how such a paper would be relevant, note that we are not talking about mov=
e construction/assignment but about `emplace` here, which runs arbitrary us=
er defined code (after having disposed of the active member) deep within it=
s bowels, as I said in my original mail.<br></blockquote><div><br></div><di=
v>emplace <i>does not</i>=C2=A0run arbitrary user defined code.=C2=A0 When =
it is instantiated (since it is a function template), it calls a <i>specifi=
c</i> constructor.=C2=A0 If that constructor is noexcept, there is <i>no re=
ason</i>=C2=A0that the emplace cannot also be noexcept.=C2=A0 That would be=
conditionally noexcept, unless the compiler knows that all </div><div>cons=
tructors called are noexcept, in which case the emplace would be unconditio=
nally noexcept(true).</div></div></div></div></blockquote><div><br>I think =
you may have misunderstood his point.<br><br>`emplace` does in fact call a =
specific constructor. However, implicit conversions to the appropriate type=
s for that constructor happen <i>within</i> the `emplace` operation itself,=
right before calling the constructor. At some point, `emplace` will do thi=
s:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 25=
0, 250); border-color: rgb(187, 187, 187); border-style: solid; border-widt=
h: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"s=
ubprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">ne=
w</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">mem</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">forward</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify"><</span><span style=3D"color: #606;" class=3D"styled-by-prettify">=
Args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">args</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)...);</span></di=
v></code></div><br>And that is when the conversion happens, and therefore t=
hat is where the exception is emitted. So even if the constructor selected =
is `noexcept`, the conversions used to select it may not be.<br><br>It shou=
ld be noted that none of the other standard library `emplace`-type function=
s state that the function is `noexcept` if the selected constructor is also=
`noexcept`.</div><br>
<p></p>
-- <br />
<br />
--- <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 />
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_7879_145529882.1446038244977--
------=_Part_7878_1760640261.1446038244968--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 28 Oct 2015 12:03:08 -0400
Raw View
--001a11c377a29e345b05232c5462
Content-Type: text/plain; charset=UTF-8
On Sun, Oct 25, 2015 at 8:06 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> According to Herb Sutter, it is done
> <http://herbsutter.com/2015/10/25/2568/>. Finally. And apparently, it's
> just N4542/P0088R0. AKA: never-empty, but with an invalid state on
> exceptions. And probably default construction on that.
>
> Oh, and it'll throw instead of issue undefined behavior if you do things
> with an invalid variant. Which means that visitation can't be a noexcept
> operation. Not that it was `noexcept` before, but it would have been nice
> to have it be noexcept if all of the operator()'s it could call were
> noexcept too.
>
>
Feel free to mark your visitation code as noexcept. It just means it will
terminate on exception. And if you assume your variants are never in a bad
state, or if you assume bad state variants are basically UB, then terminate
is as good as anything. You get to decide.
Tony
> Oh well; at least it doesn't cause performance hassles (since any fetching
> operations have to check the index anyway).
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c377a29e345b05232c5462
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sun, Oct 25, 2015 at 8:06 PM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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">Acco=
rding to Herb Sutter, <a href=3D"http://herbsutter.com/2015/10/25/2568/" ta=
rget=3D"_blank">it is done</a>. Finally. And apparently, it's just N454=
2/P0088R0. AKA: never-empty, but with an invalid state on exceptions. And p=
robably default construction on that.<br><br>Oh, and it'll throw instea=
d of issue undefined behavior if you do things with an invalid variant. Whi=
ch means that visitation can't be a noexcept operation. Not that it was=
`noexcept` before, but it would have been nice to have it be noexcept if a=
ll of the operator()'s it could call were noexcept too.<br><br></div></=
blockquote><div><br></div><div>Feel free to mark your visitation code as no=
except.=C2=A0 It just means it will terminate on exception.=C2=A0 And if yo=
u assume your variants are never in a bad state, or if you assume bad state=
variants are basically UB, then terminate is as good as anything.=C2=A0 Yo=
u get to decide.<br><br></div><div>Tony<br></div><div>=C2=A0</div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><div dir=3D"ltr">Oh well; at least it doesn't cau=
se performance hassles (since any fetching operations have to check the ind=
ex anyway).<br></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c377a29e345b05232c5462--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 28 Oct 2015 13:08:16 -0400
Raw View
--001a11c264a48d176705232d3d59
Content-Type: text/plain; charset=UTF-8
On Tue, Oct 27, 2015 at 1:03 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> According to Herb Sutter, it is done
>> <http://herbsutter.com/2015/10/25/2568/>. Finally. And apparently, it's
>> just N4542/P0088R0. AKA: never-empty, but with an invalid state on
>> exceptions. And probably default construction on that.
>>
>
> I wouldn't exactly say it's done, as there is still a fair amount to do,
> but there was consensus. FWIW, even I was weakly in favor of this, though
> I'd still prefer constrained assignment. It was clear that it would be
> difficult to push for such an approach as only Howard and I and a couple of
> others really felt that constrained assignment was a better approach.
>
> To be clear, the variant that the we are moving forward with is *not*
> never-empty -- possible invalid state on exceptions during assignment and
> emplacement is precisely why it is not never-empty. IIRC, there was
> consensus that we will not default construction to the invalid state (I
> don't know remember if there was a poll at this meeting for it, but there
> was fairly clear agreement). The reason why it doesn't default to invalid
> is because that would be one more way to get into the invalid state. The
> idea from those in favor of the invalid state is that you can only get into
> that state by way of failed assignment or emplacement, so in practice you
> don't need to check for it (a sentiment that I strongly disagree with as
> IMO it means the rare bugs will just be more subtle, but it is better than
> an empty state that is more prominent). There was some bike-shedding about
> naming the function for the invalid state and I think we ended up with
> ".corrupted_by_exception()."
>
> On Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> Oh, and it'll throw instead of issue undefined behavior if you do things
>> with an invalid variant. Which means that visitation can't be a noexcept
>> operation. Not that it was `noexcept` before, but it would have been nice
>> to have it be noexcept if all of the operator()'s it could call were
>> noexcept too.
>>
>
> Yeah, I am really against that aspect and I'm planning on writing a
> proposal to turn it to UB, but I'm not sure how well that will go. IMO, any
> operations on a variant when in the invalid state, other than checking if
> you are in that invalid state, should be UB. It should just be a
> precondition violation.
>
Considering that UB -> exceptions is what brought consensus within plenary,
I think it would be wrong to submit a proposal suggesting otherwise, unless
you have new, novel information to add.
Of course that never stopped anyone before, possibly myself included.
Tony
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c264a48d176705232d3d59
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Oct 27, 2015 at 1:03 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Sun, Oct 25, 2015=
at 5:06 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@=
gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> wrote:<br><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa=
dding-left:1ex"><div dir=3D"ltr">According to Herb Sutter, <a href=3D"http:=
//herbsutter.com/2015/10/25/2568/" target=3D"_blank">it is done</a>. Finall=
y. And apparently, it's just N4542/P0088R0. AKA: never-empty, but with =
an invalid state on exceptions. And probably default construction on that.<=
br></div></blockquote><div><br></div></span><div>I wouldn't exactly say=
it's done, as there is still a fair amount to do, but there was consen=
sus. FWIW, even I was weakly in favor of this, though I'd still prefer =
constrained assignment. It was clear that it would be difficult to push for=
such an approach as only Howard and I and a couple of others really felt t=
hat constrained assignment was a better approach.</div><div><br></div><div>=
To be clear, the variant that the we are moving forward with is <i>not</i> =
never-empty -- possible invalid state on exceptions during assignment and e=
mplacement is precisely why it is not never-empty. IIRC, there was consensu=
s that we will not default construction to the invalid state (I don't k=
now remember if there was a poll at this meeting for it, but there was fair=
ly clear agreement). The reason why it doesn't default to invalid is be=
cause that would be one more way to get into the invalid state. The idea fr=
om those in favor of the invalid state is that you can only get into that s=
tate by way of failed assignment or emplacement, so in practice you don'=
;t need to check for it (a sentiment that I strongly disagree with as IMO i=
t means the rare bugs will just be more subtle, but it is better than an em=
pty state that is more prominent). There was some bike-shedding about namin=
g the function for the invalid state and I think we ended up with ".co=
rrupted_by_exception()."</div><span class=3D""><div><br></div><div>On =
Sun, Oct 25, 2015 at 5:06 PM, Nicol Bolas=C2=A0<span dir=3D"ltr"><<a hre=
f=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&=
gt;</span>=C2=A0wrote:=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr">Oh, a=
nd it'll throw instead of issue undefined behavior if you do things wit=
h an invalid variant. Which means that visitation can't be a noexcept o=
peration. Not that it was `noexcept` before, but it would have been nice to=
have it be noexcept if all of the operator()'s it could call were noex=
cept too.<br></div></blockquote><div><br></div></span><div>Yeah, I am reall=
y against that aspect and I'm planning on writing a proposal to turn it=
to UB, but I'm not sure how well that will go. IMO, any operations on =
a variant when in the invalid state, other than checking if you are in that=
invalid state, should be UB. It should just be a precondition violation.</=
div></div></div></div></blockquote><div><br><br></div><div>Considering that=
UB -> exceptions is what brought consensus within plenary, I think it w=
ould be wrong to submit a proposal suggesting otherwise, unless you have ne=
w, novel information to add.<br></div><div>Of course that never stopped any=
one before, possibly myself included.<br><br></div><div>Tony<br></div><div>=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div c=
lass=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c264a48d176705232d3d59--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 28 Oct 2015 13:09:11 -0400
Raw View
--089e011605f4db1c8a05232d40f7
Content-Type: text/plain; charset=UTF-8
On Tue, Oct 27, 2015 at 1:37 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 27 October 2015 at 12:03, 'Matt Calabrese' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org> wrote:
>
>
>> The idea from those in favor of the invalid state is that you can only
>> get into that state by way of failed assignment or emplacement, so in
>> practice you don't need to check for it (a sentiment that I strongly
>> disagree with as IMO it means the rare bugs will just be more subtle, but
>> it is better than an empty state that is more prominent).
>>
>
> I just don't see how it is any more subtle than never-empty (as opposed to
> the strong exception safety guarantee, which no one actually proposed).
> Even with never-empty, while you can reason about what *type* the variant
> is engaged with, it is still very difficult (if not impossible w/o knowing
> the "from" state) to reason about the *value* that type has.
>
>
>> There was some bike-shedding about naming the function for the invalid
>> state and I think we ended up with ".corrupted_by_exception()."
>>
>
> Ugh. Putting words like "corrupted" in function names makes it difficult
> to use in many regulated industries.
>
That's worth bringing up in the committee. Are you considering an email,
or shall I?
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e011605f4db1c8a05232d40f7
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Oct 27, 2015 at 1:37 PM, Nevin Liber <span dir=3D"ltr"><<a h=
ref=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.=
com</a>></span> wrote:<br><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=
"><span class=3D"">On 27 October 2015 at 12:03, 'Matt Calabrese' vi=
a ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a href=3D"mail=
to:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>=
></span> wrote:<br></span><div class=3D"gmail_extra"><div class=3D"gmail=
_quote"><span class=3D""><div>=C2=A0</div><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>T=
he idea from those in favor of the invalid state is that you can only get i=
nto that state by way of failed assignment or emplacement, so in practice y=
ou don't need to check for it (a sentiment that I strongly disagree wit=
h as IMO it means the rare bugs will just be more subtle, but it is better =
than an empty state that is more prominent).</div></div></div></div></block=
quote><div><br></div></span><div>I just don't see how it is any more su=
btle than never-empty (as opposed to the strong exception safety guarantee,=
which no one actually proposed).=C2=A0 Even with never-empty, while you ca=
n reason about what <i>type</i>=C2=A0the variant is engaged with, it is sti=
ll very difficult (if not impossible w/o knowing the "from" state=
) to reason about the <i>value</i>=C2=A0that type has.</div><span class=3D"=
"><div>=C2=A0</div><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 cla=
ss=3D"gmail_extra"><div class=3D"gmail_quote"><div> There was some bike-she=
dding about naming the function for the invalid state and I think we ended =
up with ".corrupted_by_exception()."</div></div></div></div></blo=
ckquote><div><br></div></span><div>Ugh.=C2=A0 Putting words like "corr=
upted" in function names makes it difficult to use in many regulated i=
ndustries.</div></div></div></div></blockquote><div><br></div><div>That'=
;s worth bringing up in the committee.=C2=A0 Are you considering an email, =
or shall I?<br></div></div><br></div><div class=3D"gmail_extra">Tony<br><br=
></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e011605f4db1c8a05232d40f7--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 28 Oct 2015 13:13:37 -0400
Raw View
--047d7b3a8290a948cf05232d50db
Content-Type: text/plain; charset=UTF-8
On Tue, Oct 27, 2015 at 7:57 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> An idea just occurred to me.
>
> Since the variant can be made invalid/corrupted/etc, there should probably
> be a function called `repair_valid`. If the variant is invalid, it will
> rebuild the variant as if constructed with the variant's default type. The
> function will be noexcept if the default argument is noexcept. If the first
> argument is not default constructable, then that function should SFINAE
> disappear.
>
> It could even have overloads that mimic variant emplacement operations.
> The function doesn't even need to be a member.
>
Both any and optional have or will have a function called reset().
(Currently optional calls it clear() but we want to make the naming
consistent.)
There was talk of giving variant a reset() function, which would default
construct the first type. Although you can argue that that is not quite
the same kind of reset() as any/optional/shared_ptr/etc. (It is the same
in that they all go to their default-constructed state, but not the same in
that they all set the state to empty, but variant would not.)
Note, however, that this repair_valid, whatever it is called, could still
throw, and not repair anything. (And thus shouldn't be called 'repair'.)
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b3a8290a948cf05232d50db
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Oct 27, 2015 at 7:57 PM, Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.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">An i=
dea just occurred to me.<br><br>Since the variant can be made invalid/corru=
pted/etc, there should probably be a function called `repair_valid`. If the=
variant is invalid, it will rebuild the variant as if constructed with the=
variant's default type. The function will be noexcept if the default a=
rgument is noexcept. If the first argument is not default constructable, th=
en that function should SFINAE disappear.<br><br>It could even have overloa=
ds that mimic variant emplacement operations. The function doesn't even=
need to be a member.<span class=3D""><br></span></div></blockquote><div><b=
r></div><div>Both any and optional have or will have a function called rese=
t().=C2=A0 (Currently optional calls it clear() but we want to make the nam=
ing consistent.)<br><br></div><div>There was talk of giving variant a reset=
() function, which would default construct the first type.=C2=A0 Although y=
ou can argue that that is not quite the same kind of reset() as any/optiona=
l/shared_ptr/etc.=C2=A0 (It is the same in that they all go to their defaul=
t-constructed state, but not the same in that they all set the state to emp=
ty, but variant would not.)<br><br></div><div>Note, however, that this repa=
ir_valid, whatever it is called, could still throw, and not repair anything=
..=C2=A0 (And thus shouldn't be called 'repair'.)<br><br></div><=
div>Tony<br></div><div><br></div><br></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b3a8290a948cf05232d50db--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 28 Oct 2015 11:14:05 -0700
Raw View
--089e0115f052f12ffc05232e2832
Content-Type: text/plain; charset=UTF-8
On Tue, Oct 27, 2015 at 6:02 PM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:
>
> Note this part of what Nevin wrote very carefully:
>
> "Making it UB doesn't help this, as visitation would still require a
> precondition, making it a narrow contract, and hence would not be
> marked noexcept in the standard (although vendors would be free to add
> it).
>
> Note: if it is a variant where never-empty can be achieved, then there
> is no precondition and it could be marked noexcept."
>
> If visitation is made UB with a precondition, it won't be noexcept anyway.
There's an important difference between something that is simply
noexcept(false) with preconditions and something that is *guaranteed* by
the standard to reliably throw a specific exception on an operation such as
..get<T>() or visit() when you give that function a variant that is invalid.
Really this should be a precondition failure, as either the user is
invoking the function when they incorrectly believe it is valid, or they
are intentionally invoking the function without knowing whether they are
valid or not and relying on the fact that the function will throw on the
invalid case as a means to do basic control flow. IMO, neither of these
cases should be encouraged.
In other words, what we have with fully specified throwing on .get<T>() and
visit() is analogous to the throwing behavior of std::vector's .at(). The
non-throwing version would be analogous to std::vector's operator[].
Perhaps not all people consider std::vector's .at() function a mistake (at
the very least, it's understood to be contentious), but realize that this
is the same kind of difference that we are discussing when dealing with
variant's behavior on functions like .get<T>() and visit().
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0115f052f12ffc05232e2832
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=
ue, Oct 27, 2015 at 6:02 PM, Ville Voutilainen <span dir=3D"ltr"><<a hre=
f=3D"mailto:ville.voutilainen@gmail.com" target=3D"_blank">ville.voutilaine=
n@gmail.com</a>></span> wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Note this p=
art of what Nevin wrote very carefully:<br>
<span class=3D""><br>
"Making it UB doesn't help this, as visitation would still require=
a<br>
precondition, making it a narrow contract, and hence would not be<br>
marked noexcept in the standard (although vendors would be free to add<br>
it).<br>
<br>
Note: if it is a variant where never-empty can be achieved, then there<br>
is no precondition and it could be marked noexcept."<br>
<br>
</span>If visitation is made UB with a precondition, it won't be noexce=
pt anyway.</blockquote><div><br></div><div>There's an important differe=
nce between something that is simply noexcept(false) with preconditions and=
something that is <i>guaranteed</i>=C2=A0by the standard to reliably throw=
a specific exception on an operation such as .get<T>() or visit() wh=
en you give that function a variant that is invalid. Really this should be =
a precondition failure, as either the user is invoking the function when th=
ey incorrectly believe it is valid, or they are intentionally invoking the =
function without knowing whether they are valid or not and relying on the f=
act that the function will throw on the invalid case as a means to do basic=
control flow. IMO, neither of these cases should be encouraged.</div><div>=
<br></div><div>In other words, what we have with fully specified throwing o=
n .get<T>() and visit() is analogous to the throwing behavior of std:=
:vector's .at(). The non-throwing version would be analogous to std::ve=
ctor's operator[]. Perhaps not all people consider std::vector's .a=
t() function a mistake (at the very least, it's understood to be conten=
tious), but realize that this is the same kind of difference that we are di=
scussing when dealing with variant's behavior on functions like .get<=
;T>() and visit().</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0115f052f12ffc05232e2832--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 28 Oct 2015 11:15:19 -0700
Raw View
--089e01175e4d5ee9db05232e2d6f
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tue, Oct 27, 2015 at 7:18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <
kaballo86@hotmail.com> wrote:
> On 10/27/2015 10:02 PM, Ville Voutilainen wrote:
>
>> Note: if it is a variant where never-empty can be achieved, then there
>> is no precondition and it could be marked noexcept."
>>
>
> I do not think such a mythical beast exists, `emplace` will execute
> arbitrary user defined code after all. Consider:
>
> struct nasty { operator int() const { throw 42; } };
>
> variant<int, float> v;
> // v has an int now (I think)
> v.emplace<int>(nasty{});
> // what now?
>
> Is the Kona variant empty when `emplace` exits via an exception?
I brought up this exact kind of case many pages ago, but it was
disregarded/ignored or in retrospect maybe just misunderstood because it's
subtle. Both because of corner cases like this, and especially if you are
dealing with dependent types, it's more difficult in practice to correctly
say "my type cannot be invalid." Yeah, it's still rare and only comes up
via exception, but I'd rather just have it *actually* never empty by way of
the type system.
--=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/.
--089e01175e4d5ee9db05232e2d6f
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=
ue, Oct 27, 2015 at 7:18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <span dir=3D"l=
tr"><<a href=3D"mailto:kaballo86@hotmail.com" target=3D"_blank">kaballo8=
6@hotmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span=
class=3D"">On 10/27/2015 10:02 PM, Ville Voutilainen wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Note: if it is a variant where never-empty can be achieved, then there<br>
is no precondition and it could be marked noexcept."<br>
</blockquote>
<br></span>
I do not think such a mythical beast exists, `emplace` will execute arbitra=
ry user defined code after all. Consider:<br>
<br>
=C2=A0 struct nasty { operator int() const { throw 42; } };<br>
<br>
=C2=A0 variant<int, float> v;<br>
=C2=A0 // v has an int now (I think)<br>
=C2=A0 v.emplace<int>(nasty{});<br>
=C2=A0 // what now?<br>
<br>
Is the Kona variant empty when `emplace` exits via an exception?</blockquot=
e><div><br></div><div>I brought up this exact kind of case many pages ago, =
but it was disregarded/ignored or in retrospect maybe just misunderstood be=
cause it's subtle. Both because of corner cases like this, and especial=
ly if you are dealing with dependent types, it's more difficult in prac=
tice to correctly say "my type cannot be invalid." Yeah, it's=
still rare and only comes up via exception, but I'd rather just have i=
t <i>actually</i>=C2=A0never empty by way of the type system.</div></div></=
div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01175e4d5ee9db05232e2d6f--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 28 Oct 2015 11:30:46 -0700
Raw View
--089e0115f05296057d05232e6436
Content-Type: text/plain; charset=UTF-8
On Wed, Oct 28, 2015 at 10:08 AM, Tony V E <tvaneerd@gmail.com> wrote:
> Considering that UB -> exceptions is what brought consensus within
> plenary, I think it would be wrong to submit a proposal suggesting
> otherwise, unless you have new, novel information to add.
> Of course that never stopped anyone before, possibly myself included.
>
Yeah, I understand that. To be clear, I'm not optimistic about changing
consensus on the throwing behavior of .get<T>() and visit() (though I'm
certainly more optimistic than trying to eliminate the empty state). On
principle, I just feel that it's important to try, regardless.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0115f05296057d05232e6436
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Oct 28, 2015 at 10:08 AM, Tony V E <span dir=3D"ltr"><<a href=3D"mai=
lto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=
wrote:</div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Con=
sidering that UB -> exceptions is what brought consensus within plenary,=
I think it would be wrong to submit a proposal suggesting otherwise, unles=
s you have new, novel information to add.<br></div><div>Of course that neve=
r stopped anyone before, possibly myself included.</div></div></div></div><=
/blockquote><div><br></div><div>Yeah, I understand that. To be clear, I'=
;m not optimistic about changing consensus on the throwing behavior of .get=
<T>() and visit() (though I'm certainly more optimistic than tryi=
ng to eliminate the empty state). On principle, I just feel that it's i=
mportant to try, regardless.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0115f05296057d05232e6436--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 28 Oct 2015 16:49:33 -0400
Raw View
--047d7b3a8290f49e67052330546d
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wed, Oct 28, 2015 at 2:15 PM, 'Matt Calabrese' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> On Tue, Oct 27, 2015 at 7:18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <
> kaballo86@hotmail.com> wrote:
>
>> On 10/27/2015 10:02 PM, Ville Voutilainen wrote:
>>
>>> Note: if it is a variant where never-empty can be achieved, then there
>>> is no precondition and it could be marked noexcept."
>>>
>>
>> I do not think such a mythical beast exists, `emplace` will execute
>> arbitrary user defined code after all. Consider:
>>
>> struct nasty { operator int() const { throw 42; } };
>>
>> variant<int, float> v;
>> // v has an int now (I think)
>> v.emplace<int>(nasty{});
>> // what now?
>>
>> Is the Kona variant empty when `emplace` exits via an exception?
>
>
> I brought up this exact kind of case many pages ago, but it was
> disregarded/ignored or in retrospect maybe just misunderstood because it'=
s
> subtle. Both because of corner cases like this, and especially if you are
> dealing with dependent types, it's more difficult in practice to correctl=
y
> say "my type cannot be invalid." Yeah, it's still rare and only comes up
> via exception, but I'd rather just have it *actually* never empty by way
> of the type system.
>
The interesting thing here is that it means a proposal (such as your idea)
to only allow assignment/emplace on types that satisfy the constrains,
really doesn't work. Note that the above variant is <int, float>. ie
there are no types in which emplace can't throw.
I _think_ you could meta-program your way out of this, by determining which
constructor would be called, then casting/constructing temporaries to the
constructor args. ie:
v.emplace<int>(nasty{})
becomes:
int const & arg0 =3D int(nasty{}); // might throw here
destroy_current_value();
new (v.storage) int(arg0);
I'm not sure how to determine the correct constructor and build the arg
list, but I think/hope some expert could do it.
Also needs to handle rvalue refs, etc.
Tony
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=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/.
--047d7b3a8290f49e67052330546d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Oct 28, 2015 at 2:15 PM, 'Matt Calabrese' via ISO C++ S=
tandard - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-prop=
osals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><span class=3D"">On Tue, Oct 27, 2015=
at 7:18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <span dir=3D"ltr"><<a href=
=3D"mailto:kaballo86@hotmail.com" target=3D"_blank">kaballo86@hotmail.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"><span>On 10/27/2015 =
10:02 PM, Ville Voutilainen wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Note: if it is a variant where never-empty can be achieved, then there<br>
is no precondition and it could be marked noexcept."<br>
</blockquote>
<br></span>
I do not think such a mythical beast exists, `emplace` will execute arbitra=
ry user defined code after all. Consider:<br>
<br>
=C2=A0 struct nasty { operator int() const { throw 42; } };<br>
<br>
=C2=A0 variant<int, float> v;<br>
=C2=A0 // v has an int now (I think)<br>
=C2=A0 v.emplace<int>(nasty{});<br>
=C2=A0 // what now?<br>
<br>
Is the Kona variant empty when `emplace` exits via an exception?</blockquot=
e><div><br></div></span><div>I brought up this exact kind of case many page=
s ago, but it was disregarded/ignored or in retrospect maybe just misunders=
tood because it's subtle. Both because of corner cases like this, and e=
specially if you are dealing with dependent types, it's more difficult =
in practice to correctly say "my type cannot be invalid." Yeah, i=
t's still rare and only comes up via exception, but I'd rather just=
have it <i>actually</i>=C2=A0never empty by way of the type system.</div><=
/div></div></div></blockquote><div><br></div><div>The interesting thing her=
e is that it means a proposal (such as your idea) to only allow assignment/=
emplace on types that satisfy the constrains, really doesn't work.=C2=
=A0 Note that the above variant is <int, float>.=C2=A0 ie there are n=
o types in which emplace can't throw.<br><br></div><div>I _think_ you c=
ould meta-program your way out of this, by determining which constructor wo=
uld be called, then casting/constructing temporaries to the constructor arg=
s. ie:<br><br></div><div>=C2=A0=C2=A0=C2=A0 v.emplace<int>(nasty{})<b=
r></div><div>becomes:<br><br></div><div>=C2=A0=C2=A0=C2=A0 int const & =
arg0 =3D int(nasty{});=C2=A0 // might throw here<br></div><div>=C2=A0=C2=A0=
=C2=A0 destroy_current_value();<br></div><div>=C2=A0=C2=A0=C2=A0 new (v.sto=
rage) int(arg0);<br><br></div><div>I'm not sure how to determine the co=
rrect constructor and build the arg list, but I think/hope some expert coul=
d do it.<br></div><div>Also needs to handle rvalue refs, etc.<br><br></div>=
<div>Tony<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><di=
v class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b3a8290f49e67052330546d--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 28 Oct 2015 15:12:30 -0700 (PDT)
Raw View
------=_Part_1093_920983467.1446070350107
Content-Type: multipart/alternative;
boundary="----=_Part_1094_1858093853.1446070350107"
------=_Part_1094_1858093853.1446070350107
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, October 28, 2015 at 4:49:37 PM UTC-4, Tony V E wrote:
>
>
>
> On Wed, Oct 28, 2015 at 2:15 PM, 'Matt Calabrese' via ISO C++ Standard -=
=20
> Future Proposals <std-pr...@isocpp.org <javascript:>> wrote:
>
>> On Tue, Oct 27, 2015 at 7:18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <
>> kaba...@hotmail.com <javascript:>> wrote:
>>
>>> On 10/27/2015 10:02 PM, Ville Voutilainen wrote:
>>>
>>>> Note: if it is a variant where never-empty can be achieved, then there
>>>> is no precondition and it could be marked noexcept."
>>>>
>>>
>>> I do not think such a mythical beast exists, `emplace` will execute=20
>>> arbitrary user defined code after all. Consider:
>>>
>>> struct nasty { operator int() const { throw 42; } };
>>>
>>> variant<int, float> v;
>>> // v has an int now (I think)
>>> v.emplace<int>(nasty{});
>>> // what now?
>>>
>>> Is the Kona variant empty when `emplace` exits via an exception?
>>
>>
>> I brought up this exact kind of case many pages ago, but it was=20
>> disregarded/ignored or in retrospect maybe just misunderstood because it=
's=20
>> subtle. Both because of corner cases like this, and especially if you ar=
e=20
>> dealing with dependent types, it's more difficult in practice to correct=
ly=20
>> say "my type cannot be invalid." Yeah, it's still rare and only comes up=
=20
>> via exception, but I'd rather just have it *actually* never empty by way=
=20
>> of the type system.
>>
>
> The interesting thing here is that it means a proposal (such as your idea=
)=20
> to only allow assignment/emplace on types that satisfy the constrains,=20
> really doesn't work. Note that the above variant is <int, float>. ie=20
> there are no types in which emplace can't throw.
>
> I _think_ you could meta-program your way out of this, by determining=20
> which constructor would be called, then casting/constructing temporaries =
to=20
> the constructor args. ie:
>
> v.emplace<int>(nasty{})
> becomes:
>
> int const & arg0 =3D int(nasty{}); // might throw here
> destroy_current_value();
> new (v.storage) int(arg0);
>
> I'm not sure how to determine the correct constructor and build the arg=
=20
> list, but I think/hope some expert could do it.
> Also needs to handle rvalue refs, etc.
>
Basically, what you would have to do is:
1) Determine the typelist for the constructor that would be called from=20
`forward<Args>(args)...`.
2) Construct a forwarding tuple of those types, initializing it with=20
`forward<Args>(args)...`. Exceptions get thrown here, so the variant=20
remains untouched.
3) Perform the assignment, initializing the new value from the tuple by=20
using some form of `experimental::apply`.
That's pretty non-trivial overhead, having to go through an intermediate=20
forwarding tuple. And I have no idea how you'd even implement step 1.=20
Particularly considering that it's a constructor rather than a normal=20
function call.
--=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_1094_1858093853.1446070350107
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Wednesday, October 28, 2015 at 4:49:37 PM UTC-4, Tony V E wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><div><br>=
<div class=3D"gmail_quote">On Wed, Oct 28, 2015 at 2:15 PM, 'Matt Calab=
rese' via ISO C++ Standard - Future Proposals <span dir=3D"ltr"><<a =
href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"jQ1Cp6H5EgA=
J" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return=
true;" onclick=3D"this.href=3D'javascript:';return true;">std-pr..=
..@isocpp.org</a>></span> wrote:<br><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><span>On Tue, Oct 27, 2015 at 7:=
18 PM, Agust=C3=ADn K-ballo Berg=C3=A9 <span dir=3D"ltr"><<a href=3D"jav=
ascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"jQ1Cp6H5EgAJ" rel=3D"n=
ofollow" onmousedown=3D"this.href=3D'javascript:';return true;" onc=
lick=3D"this.href=3D'javascript:';return true;">kaba...@hotmail.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"><span>On 10/27/201=
5 10:02 PM, Ville Voutilainen wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Note: if it is a variant where never-empty can be achieved, then there<br>
is no precondition and it could be marked noexcept."<br>
</blockquote>
<br></span>
I do not think such a mythical beast exists, `emplace` will execute arbitra=
ry user defined code after all. Consider:<br>
<br>
=C2=A0 struct nasty { operator int() const { throw 42; } };<br>
<br>
=C2=A0 variant<int, float> v;<br>
=C2=A0 // v has an int now (I think)<br>
=C2=A0 v.emplace<int>(nasty{});<br>
=C2=A0 // what now?<br>
<br>
Is the Kona variant empty when `emplace` exits via an exception?</blockquot=
e><div><br></div></span><div>I brought up this exact kind of case many page=
s ago, but it was disregarded/ignored or in retrospect maybe just misunders=
tood because it's subtle. Both because of corner cases like this, and e=
specially if you are dealing with dependent types, it's more difficult =
in practice to correctly say "my type cannot be invalid." Yeah, i=
t's still rare and only comes up via exception, but I'd rather just=
have it <i>actually</i>=C2=A0never empty by way of the type system.</div><=
/div></div></div></blockquote><div><br></div><div>The interesting thing her=
e is that it means a proposal (such as your idea) to only allow assignment/=
emplace on types that satisfy the constrains, really doesn't work.=C2=
=A0 Note that the above variant is <int, float>.=C2=A0 ie there are n=
o types in which emplace can't throw.<br><br></div><div>I _think_ you c=
ould meta-program your way out of this, by determining which constructor wo=
uld be called, then casting/constructing temporaries to the constructor arg=
s. ie:<br><br></div><div>=C2=A0=C2=A0=C2=A0 v.emplace<int>(nasty{})<b=
r></div><div>becomes:<br><br></div><div>=C2=A0=C2=A0=C2=A0 int const & =
arg0 =3D int(nasty{});=C2=A0 // might throw here<br></div><div>=C2=A0=C2=A0=
=C2=A0 destroy_current_value();<br></div><div>=C2=A0=C2=A0=C2=A0 new (v.sto=
rage) int(arg0);<br><br></div><div>I'm not sure how to determine the co=
rrect constructor and build the arg list, but I think/hope some expert coul=
d do it.<br></div><div>Also needs to handle rvalue refs, etc.<br></div></di=
v></div></div></blockquote><div><br>Basically, what you would have to do is=
:<br><br>1) Determine the typelist for the constructor that would be called=
from `forward<Args>(args)...`.<br><br>2) Construct a forwarding tupl=
e of those types, initializing it with `forward<Args>(args)...`. Exce=
ptions get thrown here, so the variant remains untouched.<br><br>3) Perform=
the assignment, initializing the new value from the tuple by using some fo=
rm of `experimental::apply`.<br><br>That's pretty non-trivial overhead,=
having to go through an intermediate forwarding tuple. And I have no idea =
how you'd even implement step 1. Particularly considering that it's=
a constructor rather than a normal function call.</div>
<p></p>
-- <br />
<br />
--- <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 />
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_1094_1858093853.1446070350107--
------=_Part_1093_920983467.1446070350107--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 28 Oct 2015 15:12:50 -0700
Raw View
--001a113d58a6cef4890523317e11
Content-Type: text/plain; charset=UTF-8
On Wed, Oct 28, 2015 at 1:49 PM, Tony V E <tvaneerd@gmail.com> wrote:
>
> The interesting thing here is that it means a proposal (such as your idea)
> to only allow assignment/emplace on types that satisfy the constrains,
> really doesn't work. Note that the above variant is <int, float>. ie
> there are no types in which emplace can't throw.
>
It can work as I described a few pages back, though it depends on the most
contentious aspect of things that I don't think a lot of people would
stomach (behavior of variants and optionals when containing copyable but
not copy-assignable types). All of this is moot because I doubt any paper
I'd write on the topic would make a difference. I'd more just write it on
principle and to have the idea more formally presented with all of the
details in one place.
In short, much like assignment is constrained, a variant's emplace would be
constrained (you can always emplace if the constructor is noexcept, even if
move constructors can throw, so it's not quite as limiting as constrained
homogeneous assignment). If there is a fallback field type (a
noexcept-default-constructible field type), an emplace that throws is also
fine, since you can fall back to that type upon exception. If there is *not*
a fallback type and you need an emplace that can potentially throw, the
solution regarding emplacement is the same as I suggested regarding
constrained assignment -- you emplace via your
optional<nonempty_variant<T...>>. If emplacement into an optional fails by
way of exception, your optional is left in the nullopt state, so everything
works fine. In other words, the optional's nullopt state in this case is
very analogous to the invalid state, only you get the benefit of the
separation of abstraction that an optional provides (it also gets things
like what to do on a get() or visit() of an "invalid" variant correct
implicitly, since such an invalid variant doesn't actually exist!). People
can use the underlying non-empty variant directly if they understand the
constraints. For others, they can just default to always use variant<T...>,
which has similar semantics to variant with an invalid state (i.e. the
variant that we are moving forward with). Functions can take a never-empty
variant by reference or value and deal with its constrained operations and
there is no possibility of it being empty, which is useful even if at the
top-level you are holding such an optional variant (preconditions are
simplified due to the stronger type invariants). Anyone who holds a
variant<T...> can get a reference to a never-empty one by simply
dereferencing it.
So basically, variant<T...> would just be an alias of
optional<nonempty_variant<T...>> or perhaps a better name,
optional<one_of<T...>>. Anyway, again, I don't really expect to change
consensus here, just understand that this kind of model really is
consistent and provides the full set of functionality that a variant with
an invalid state provides, only in a different manner and through more
fine-grained abstractions. It provides a never-empty abstraction by way of
constraints, at the cost of variant/optional semantics that some people
subjectively do not like. The decision for when you can/should use a
never-empty variant would be a bit subtle, but at least you get failed
compilation if you do something that is not able to be implemented without
potentially violating the never-empty guarantee. I'd rather see *that* than
have an intrinsic invalid state that we explicitly deter people from
checking for because it is perceived to be rare. I'd take a compile-time
error over a rare and subtle run-time bug anytime. Notably, you can also
trivially implement a variant with an intrinsic invalid state on top of
such an abstraction (it would just encapsulate the optional<one_of<T...>>
and forward along the functionality, automatically dereferencing internally
when necessary).
Anyway, this is silly to talk about here. I already bowed out of the
discussion once and I don't think it's worthwhile to continue in this
thread. If I write a paper on it, then we can at least have something to
talk about and point to, but either way, I don't want that to slow down
getting a standard variant, and I really doubt such a paper would change
consensus in any case. No matter what is standardized, in practice there
will be multiple user-land variant implementations anyway, just as there
are multiple flavors of containers that have similar complexities, so it
ultimately doesn't really matter all that much. In practice, people can
work with any of the variants that have been discussed. I strongly
encourage a never-empty variant in the standard, but that's pretty much not
happening.
If people want to continue discussing my views on this, hold off until I
put up a draft. Talking about it in this thread is really difficult to keep
track of.
On Wed, Oct 28, 2015 at 1:49 PM, Tony V E <tvaneerd@gmail.com> wrote:
> I _think_ you could meta-program your way out of this, by determining
> which constructor would be called, then casting/constructing temporaries to
> the constructor args. ie:
>
> v.emplace<int>(nasty{})
> becomes:
>
> int const & arg0 = int(nasty{}); // might throw here
> destroy_current_value();
> new (v.storage) int(arg0);
>
> I'm not sure how to determine the correct constructor and build the arg
> list, but I think/hope some expert could do it.
> Also needs to handle rvalue refs, etc.
>
The accepted invocation_traits proposal *almost* provides a way to do this,
but I don't think you can use it with constructors. Regardless, I don't
think such an approach is actually necessary here.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113d58a6cef4890523317e11
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Oct 28, 2015 at 1:49 PM, Tony V E <span dir=3D"ltr"><<a href=3D"mail=
to:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>The interesting thing here is that it means a propo=
sal (such as your idea) to only allow assignment/emplace on types that sati=
sfy the constrains, really doesn't work.=C2=A0 Note that the above vari=
ant is <int, float>.=C2=A0 ie there are no types in which emplace can=
't throw.<br></div></div></div></div></blockquote><div><br></div><div>I=
t can work as I described a few pages back, though it depends on the most c=
ontentious aspect of things that I don't think a lot of people would st=
omach (behavior of variants and optionals when containing copyable but not =
copy-assignable types). All of this is moot because I doubt any paper I'=
;d write on the topic would make a difference. I'd more just write it o=
n principle and to have the idea more formally presented with all of the de=
tails in one place.</div><div><br></div><div>In short, much like assignment=
is constrained, a variant's emplace would be constrained (you can alwa=
ys emplace if the constructor is noexcept, even if move constructors can th=
row, so it's not quite as limiting as constrained homogeneous assignmen=
t). If there is a fallback field type (a noexcept-default-constructible fie=
ld type), an emplace that throws is also fine, since you can fall back to t=
hat type upon exception. If there is <i>not</i> a fallback type and you nee=
d an emplace that can potentially throw, the solution regarding emplacement=
is the same as I suggested regarding constrained assignment -- you emplace=
via your optional<nonempty_variant<T...>>. If emplacement into=
an optional fails by way of exception, your optional is left in the nullop=
t state, so everything works fine. In other words, the optional's nullo=
pt state in this case is very analogous to the invalid state, only you get =
the benefit of the separation of abstraction that an optional provides (it =
also gets things like what to do on a get() or visit() of an "invalid&=
quot; variant correct implicitly, since such an invalid variant doesn't=
actually exist!). People can use the underlying non-empty variant directly=
if they understand the constraints. For others, they can just default to a=
lways use variant<T...>, which has similar semantics to variant with =
an invalid state (i.e. the variant that we are moving forward with). Functi=
ons can take a never-empty variant by reference or value and deal with its =
constrained operations and there is no possibility of it being empty, which=
is useful even if at the top-level you are holding such an optional varian=
t (preconditions are simplified due to the stronger type invariants). Anyon=
e who holds a variant<T...> can get a reference to a never-empty one =
by simply dereferencing it.</div><div><br></div><div>So basically, variant&=
lt;T...> would just be an alias of optional<nonempty_variant<T...&=
gt;> or perhaps a better name, optional<one_of<T...>>. Anywa=
y, again, I don't really expect to change consensus here, just understa=
nd that this kind of model really is consistent and provides the full set o=
f functionality that a variant with an invalid state provides, only in a di=
fferent manner and through more fine-grained abstractions. It provides a ne=
ver-empty abstraction by way of constraints, at the cost of variant/optiona=
l semantics that some people subjectively do not like. The decision for whe=
n you can/should use a never-empty variant would be a bit subtle, but at le=
ast you get failed compilation if you do something that is not able to be i=
mplemented without potentially violating the never-empty guarantee. I'd=
rather see <i>that</i> than have an intrinsic invalid state that we explic=
itly deter people from checking for because it is perceived to be rare. I&#=
39;d take a compile-time error over a rare and subtle run-time bug anytime.=
Notably, you can also trivially implement a variant with an intrinsic inva=
lid state on top of such an abstraction (it would just encapsulate the opti=
onal<one_of<T...>> and forward along the functionality, automat=
ically dereferencing internally when necessary).</div><div><br></div><div>A=
nyway, this is silly to talk about here. I already bowed out of the discuss=
ion once and I don't think it's worthwhile to continue in this thre=
ad. If I write a paper on it, then we can at least have something to talk a=
bout and point to, but either way, I don't want that to slow down getti=
ng a standard variant, and I really doubt such a paper would change consens=
us in any case. No matter what is standardized, in practice there will be m=
ultiple user-land variant implementations anyway, just as there are multipl=
e flavors of containers that have similar complexities, so it ultimately do=
esn't really matter all that much. In practice, people can work with an=
y of the variants that have been discussed. I strongly encourage a never-em=
pty variant in the standard, but that's pretty much not happening.</div=
><div><br></div><div>If people want to continue discussing my views on this=
, hold off until I put up a draft. Talking about it in this thread is reall=
y difficult to keep track of.</div><div><br></div><div>On Wed, Oct 28, 2015=
at 1:49 PM, Tony V E=C2=A0<span dir=3D"ltr"><<a href=3D"mailto:tvaneerd=
@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span>=C2=A0wrote:=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div>I _think_ you could meta-program your way out of th=
is, by determining which constructor would be called, then casting/construc=
ting temporaries to the constructor args. ie:<br><br></div><div>=C2=A0=C2=
=A0=C2=A0 v.emplace<int>(nasty{})<br></div><div>becomes:<br><br></div=
><div>=C2=A0=C2=A0=C2=A0 int const & arg0 =3D int(nasty{});=C2=A0 // mi=
ght throw here<br></div><div>=C2=A0=C2=A0=C2=A0 destroy_current_value();<br=
></div><div>=C2=A0=C2=A0=C2=A0 new (v.storage) int(arg0);<br><br></div><div=
>I'm not sure how to determine the correct constructor and build the ar=
g list, but I think/hope some expert could do it.<br></div><div>Also needs =
to handle rvalue refs, etc.</div></div></div></div></blockquote><div><br></=
div><div>The accepted invocation_traits proposal <i>almost</i> provides a w=
ay to do this, but I don't think you can use it with constructors. Rega=
rdless, I don't think such an approach is actually necessary here.</div=
></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113d58a6cef4890523317e11--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 28 Oct 2015 15:22:37 -0700
Raw View
On Wednesday 28 October 2015 15:12:30 Nicol Bolas wrote:
> 1) Determine the typelist for the constructor that would be called from
> `forward<Args>(args)...`.
>
[cut]
> That's pretty non-trivial overhead, having to go through an intermediate
> forwarding tuple. And I have no idea how you'd even implement step 1.
> Particularly considering that it's a constructor rather than a normal
> function call.
If you could determine the typelist for the constructor that would be called,
the emplace function's templates should be exactly that, so that any exception
occurs before the real emplace function gets called.
That is, instead of
v.emplace<int, nasty>(nasty{});
it should be
v.emplace<int, int>(nasty{});
Then the nasty::operator int() gets called so that it will bind to the int&&
first argument.
It's functionally equivalent to the tuple solution, but with no extra copy of
the arguments. (Unless you can create a tuple of rvalue references; can you?)
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Wed, 28 Oct 2015 17:25:02 -0500
Raw View
--001a1143026ec39fa3052331ac3c
Content-Type: text/plain; charset=UTF-8
On 28 October 2015 at 15:49, Tony V E <tvaneerd@gmail.com> wrote:
>
> The interesting thing here is that it means a proposal (such as your idea)
> to only allow assignment/emplace on types that satisfy the constrains,
> really doesn't work. Note that the above variant is <int, float>. ie
> there are no types in which emplace can't throw.
>
I agree. And even if experts can get the metaprogramming correct, it
becomes both fragile and a teachability nightmare, not to mention it would
encourage people to inappropriately and incorrectly sprinkle noexcept all
over their code just to get it to work. We'd be more likely to eliminate
emplace as a method.
And then there is the problem:
calabrese::variant<deque<int>, vector<int>> dv;
Once dv holds a vector, it can *never* be changed to hold a deque, as every
constructor deque has may throw (at least as specified in the standard).
(Real code, of course, would be aggregates with members who are deque,
vector, etc., but the same problem is there.)
While (obviously) not everyone agrees, I consider the ability to change the
type of what the variant holds to be a fundamental property. Otherwise, I
might as well just use a union.
--
Nevin ":-)" Liber <mailto:nevin@c <nevin@eviloverlord.com>plusplusguy.com>
(847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1143026ec39fa3052331ac3c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On 28 October 2015 at 15:49, Tony V E <span dir=3D"ltr">&l=
t;<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.co=
m</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_q=
uote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><div class=3D"gma=
il_extra">The interesting thing here is that it means a proposal (such as y=
our idea) to only allow assignment/emplace on types that satisfy the constr=
ains, really doesn't work.=C2=A0 Note that the above variant is <int=
, float>.=C2=A0 ie there are no types in which emplace can't throw.<=
br></div></div></blockquote><div><br></div><div>I agree.=C2=A0 And even if =
experts can get the metaprogramming correct, it becomes both fragile and a =
teachability nightmare, not to mention it would encourage people to inappro=
priately and incorrectly sprinkle noexcept all over their code just to get =
it to work.=C2=A0 We'd be more likely to eliminate emplace as a method.=
</div><div><br></div><div><br></div><div>And then there is the problem:</di=
v><div><br></div><div><font face=3D"monospace, monospace" size=3D"1">calabr=
ese::variant<deque<int>, vector<int>> dv;</font></div><di=
v><br></div><div>Once dv holds a vector, it can <i>never</i>=C2=A0be change=
d to hold a deque, as every constructor deque has may throw (at least as sp=
ecified in the standard). =C2=A0(Real code, of course, would be aggregates =
with members who are deque, vector, etc., but the same problem is there.)</=
div><div><br></div><div><br></div><div>While (obviously) not everyone agree=
s, I consider the ability to change the type of what the variant holds to b=
e a fundamental property.=C2=A0 Otherwise, I might as well just use a union=
..</div></div>-- <br><div>=C2=A0Nevin ":-)" Liber=C2=A0 <mailto=
:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@c</a><a =
href=3D"http://plusplusguy.com">plusplusguy.com</a>>=C2=A0 <a href=3D"te=
l:%28847%29%20691-1404" value=3D"+18476911404" target=3D"_blank">(847) 691-=
1404</a></div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1143026ec39fa3052331ac3c--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 28 Oct 2015 16:45:40 -0700 (PDT)
Raw View
------=_Part_8034_1658045967.1446075940409
Content-Type: multipart/alternative;
boundary="----=_Part_8035_719804685.1446075940410"
------=_Part_8035_719804685.1446075940410
Content-Type: text/plain; charset=UTF-8
On Wednesday, October 28, 2015 at 6:12:53 PM UTC-4, Matt Calabrese wrote:
>
> On Wed, Oct 28, 2015 at 1:49 PM, Tony V E <tvan...@gmail.com <javascript:>
> > wrote:
>>
>> The interesting thing here is that it means a proposal (such as your
>> idea) to only allow assignment/emplace on types that satisfy the
>> constrains, really doesn't work. Note that the above variant is <int,
>> float>. ie there are no types in which emplace can't throw.
>>
>
> It can work as I described a few pages back, though it depends on the most
> contentious aspect of things that I don't think a lot of people would
> stomach (behavior of variants and optionals when containing copyable but
> not copy-assignable types). All of this is moot because I doubt any paper
> I'd write on the topic would make a difference. I'd more just write it on
> principle and to have the idea more formally presented with all of the
> details in one place.
>
> In short, much like assignment is constrained, a variant's emplace would
> be constrained (you can always emplace if the constructor is noexcept, even
> if move constructors can throw, so it's not quite as limiting as
> constrained homogeneous assignment). If there is a fallback field type (a
> noexcept-default-constructible field type), an emplace that throws is also
> fine, since you can fall back to that type upon exception. If there is
> *not* a fallback type and you need an emplace that can potentially throw,
> the solution regarding emplacement is the same as I suggested regarding
> constrained assignment -- you emplace via your
> optional<nonempty_variant<T...>>. If emplacement into an optional fails by
> way of exception, your optional is left in the nullopt state, so everything
> works fine. In other words, the optional's nullopt state in this case is
> very analogous to the invalid state, only you get the benefit of the
> separation of abstraction that an optional provides (it also gets things
> like what to do on a get() or visit() of an "invalid" variant correct
> implicitly, since such an invalid variant doesn't actually exist!). People
> can use the underlying non-empty variant directly if they understand the
> constraints. For others, they can just default to always use variant<T...>,
> which has similar semantics to variant with an invalid state (i.e. the
> variant that we are moving forward with). Functions can take a never-empty
> variant by reference or value and deal with its constrained operations and
> there is no possibility of it being empty, which is useful even if at the
> top-level you are holding such an optional variant (preconditions are
> simplified due to the stronger type invariants). Anyone who holds a
> variant<T...> can get a reference to a never-empty one by simply
> dereferencing it.
>
> So basically, variant<T...> would just be an alias of
> optional<nonempty_variant<T...>> or perhaps a better name,
> optional<one_of<T...>>. Anyway, again, I don't really expect to change
> consensus here, just understand that this kind of model really is
> consistent and provides the full set of functionality that a variant with
> an invalid state provides, only in a different manner and through more
> fine-grained abstractions. It provides a never-empty abstraction by way of
> constraints, at the cost of variant/optional semantics that some people
> subjectively do not like. The decision for when you can/should use a
> never-empty variant would be a bit subtle, but at least you get failed
> compilation if you do something that is not able to be implemented without
> potentially violating the never-empty guarantee. I'd rather see *that*
> than have an intrinsic invalid state that we explicitly deter people from
> checking for because it is perceived to be rare. I'd take a compile-time
> error over a rare and subtle run-time bug anytime. Notably, you can also
> trivially implement a variant with an intrinsic invalid state on top of
> such an abstraction (it would just encapsulate the optional<one_of<T...>>
> and forward along the functionality, automatically dereferencing internally
> when necessary).
>
> Anyway, this is silly to talk about here. I already bowed out of the
> discussion once and I don't think it's worthwhile to continue in this
> thread. If I write a paper on it, then we can at least have something to
> talk about and point to, but either way, I don't want that to slow down
> getting a standard variant, and I really doubt such a paper would change
> consensus in any case. No matter what is standardized, in practice there
> will be multiple user-land variant implementations anyway, just as there
> are multiple flavors of containers that have similar complexities, so it
> ultimately doesn't really matter all that much. In practice, people can
> work with any of the variants that have been discussed. I strongly
> encourage a never-empty variant in the standard, but that's pretty much not
> happening.
>
> If people want to continue discussing my views on this, hold off until I
> put up a draft. Talking about it in this thread is really difficult to keep
> track of.
>
When you're putting together your proposal, you should make certain to
include the necessary changes to `optional` that your version requires.
Because `optional`as it currently exists doesn't do all of the things you
need it to in order to make `optional<_variant<T...>>` be functionally
equivalent to `n4542_variant<T...>`. For example, your idea requires that
`optional<T>` synthesize a copy/move assignment operator even if `T`
doesn't support them. You should make it clear that your proposal relies on
such behavior.
Oh, and when you're putting together your paper, it'd be a good idea to
make sure everyone understand that this is what you want to be true:
throwing_copymove tc;
tc = throwing_copymove{}; //Legal C++
experimental::any a;
a = tc; //Legal C++
optional<throwing_copymove> otc{throwing_copymove{}};
otc = tc; //Legal C++
otc = optional<throwing_copymove>{throwing_copymove{}}; //Also legal C++
std::vector<throwing_copymove> vtc;
vtc = std::vector<throwing_copymove>{{}, {}}; //Legal C++
one_of<throwing_copymove> thing_tc;
thing_tc = vtc; //Not legal C++
thing_tc = one_of<throwing_copymove>{}; //Also not legal C++
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_8035_719804685.1446075940410
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Wednesday, October 28, 2015 at 6:12:53 PM UTC-4, Matt Calabrese =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote">On Wed, Oct 28, 2015 at 1:49 PM, Tony V E <span di=
r=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mail=
to=3D"38pX5Cz-EgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javasc=
ript:';return true;" onclick=3D"this.href=3D'javascript:';retur=
n true;">tvan...@gmail.com</a>></span> 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"><div><div class=3D"gmail_quote"><div>The interesting thing here is=
that it means a proposal (such as your idea) to only allow assignment/empl=
ace on types that satisfy the constrains, really doesn't work.=C2=A0 No=
te that the above variant is <int, float>.=C2=A0 ie there are no type=
s in which emplace can't throw.<br></div></div></div></div></blockquote=
><div><br></div><div>It can work as I described a few pages back, though it=
depends on the most contentious aspect of things that I don't think a =
lot of people would stomach (behavior of variants and optionals when contai=
ning copyable but not copy-assignable types). All of this is moot because I=
doubt any paper I'd write on the topic would make a difference. I'=
d more just write it on principle and to have the idea more formally presen=
ted with all of the details in one place.</div><div><br></div><div>In short=
, much like assignment is constrained, a variant's emplace would be con=
strained (you can always emplace if the constructor is noexcept, even if mo=
ve constructors can throw, so it's not quite as limiting as constrained=
homogeneous assignment). If there is a fallback field type (a noexcept-def=
ault-constructible field type), an emplace that throws is also fine, since =
you can fall back to that type upon exception. If there is <i>not</i> a fal=
lback type and you need an emplace that can potentially throw, the solution=
regarding emplacement is the same as I suggested regarding constrained ass=
ignment -- you emplace via your optional<nonempty_variant<T...<wbr>&g=
t;>. If emplacement into an optional fails by way of exception, your opt=
ional is left in the nullopt state, so everything works fine. In other word=
s, the optional's nullopt state in this case is very analogous to the i=
nvalid state, only you get the benefit of the separation of abstraction tha=
t an optional provides (it also gets things like what to do on a get() or v=
isit() of an "invalid" variant correct implicitly, since such an =
invalid variant doesn't actually exist!). People can use the underlying=
non-empty variant directly if they understand the constraints. For others,=
they can just default to always use variant<T...>, which has similar=
semantics to variant with an invalid state (i.e. the variant that we are m=
oving forward with). Functions can take a never-empty variant by reference =
or value and deal with its constrained operations and there is no possibili=
ty of it being empty, which is useful even if at the top-level you are hold=
ing such an optional variant (preconditions are simplified due to the stron=
ger type invariants). Anyone who holds a variant<T...> can get a refe=
rence to a never-empty one by simply dereferencing it.</div><div><br></div>=
<div>So basically, variant<T...> would just be an alias of optional&l=
t;nonempty_variant<T...<wbr>>> or perhaps a better name, optional&=
lt;one_of<T...>>. Anyway, again, I don't really expect to chan=
ge consensus here, just understand that this kind of model really is consis=
tent and provides the full set of functionality that a variant with an inva=
lid state provides, only in a different manner and through more fine-graine=
d abstractions. It provides a never-empty abstraction by way of constraints=
, at the cost of variant/optional semantics that some people subjectively d=
o not like. The decision for when you can/should use a never-empty variant =
would be a bit subtle, but at least you get failed compilation if you do so=
mething that is not able to be implemented without potentially violating th=
e never-empty guarantee. I'd rather see <i>that</i> than have an intrin=
sic invalid state that we explicitly deter people from checking for because=
it is perceived to be rare. I'd take a compile-time error over a rare =
and subtle run-time bug anytime. Notably, you can also trivially implement =
a variant with an intrinsic invalid state on top of such an abstraction (it=
would just encapsulate the optional<one_of<T...>> and forward =
along the functionality, automatically dereferencing internally when necess=
ary).</div><div><br></div><div>Anyway, this is silly to talk about here. I =
already bowed out of the discussion once and I don't think it's wor=
thwhile to continue in this thread. If I write a paper on it, then we can a=
t least have something to talk about and point to, but either way, I don=
9;t want that to slow down getting a standard variant, and I really doubt s=
uch a paper would change consensus in any case. No matter what is standardi=
zed, in practice there will be multiple user-land variant implementations a=
nyway, just as there are multiple flavors of containers that have similar c=
omplexities, so it ultimately doesn't really matter all that much. In p=
ractice, people can work with any of the variants that have been discussed.=
I strongly encourage a never-empty variant in the standard, but that's=
pretty much not happening.</div><div><br></div><div>If people want to cont=
inue discussing my views on this, hold off until I put up a draft. Talking =
about it in this thread is really difficult to keep track of.</div></div></=
div></div></blockquote><br>When you're putting together your proposal, =
you should make certain to include the necessary changes to `optional` that=
your version requires. Because `optional`as it currently exists doesn'=
t do all of the things you need it to in order to make `optional<_varian=
t<T...>>` be functionally equivalent to `n4542_variant<T...>=
`. For example, your idea requires that `optional<T>` synthesize a co=
py/move assignment operator even if `T` doesn't support them. You shoul=
d make it clear that your proposal relies on such behavior.<br><br>Oh, and =
when you're putting together your paper, it'd be a good idea to mak=
e sure everyone understand that this is what you want to be true:<br><br><d=
iv class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); bor=
der-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word=
-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprin=
t"><span style=3D"color: #000;" class=3D"styled-by-prettify">throwing_copym=
ove tc</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>tc </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> throwing_copymove</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">{};</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #800;" class=3D"styled-by-prettify">//Legal C++</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br>experimental</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">any a</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>a </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> tc</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">/=
/Legal C++</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br><br>optional</span><span style=3D"color: #080;" class=3D"styled-by-pret=
tify"><throwing_copymove></span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> otc</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">throwing_copymove</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{}};</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>otc </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> t=
c</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: #800;" class=3D"styled-by-prettify">//Legal C++</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>otc </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> optional</span><span style=3D"colo=
r: #080;" class=3D"styled-by-prettify"><throwing_copymove></span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">throwing_copymove</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{}};</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #800;" class=3D"styled-by-prettify">//Also legal C++</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br>std</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"color: =
#080;" class=3D"styled-by-prettify"><throwing_copymove></span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> vtc</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>vtc </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">vector</span><span style=3D"color: #080;" class=3D"styled-b=
y-prettify"><throwing_copymove></span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">{{},</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">{}};</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//L=
egal C++</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r><br>one_of</span><span style=3D"color: #080;" class=3D"styled-by-prettify=
"><throwing_copymove></span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> thing_tc</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>thing_tc </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> vtc</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">//Not legal C++</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>thing_tc </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> one_of</span><span =
style=3D"color: #080;" class=3D"styled-by-prettify"><throwing_copymove&g=
t;</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: #800;" class=3D"styled-by-prettify">//Also not legal C++</sp=
an></div></code></div><br>
<p></p>
-- <br />
<br />
--- <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 />
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_8035_719804685.1446075940410--
------=_Part_8034_1658045967.1446075940409--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 28 Oct 2015 17:30:42 -0700
Raw View
--001a1134fb0ad01ffb0523336bd6
Content-Type: text/plain; charset=UTF-8
On Wed, Oct 28, 2015 at 4:45 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> When you're putting together your proposal, you should make certain to
> include the necessary changes to `optional` that your version requires.
>
Yes, I know the requirements of my own suggestions and what the
controversial aspects are. I do not believe in brushing aspects under the
rug or pretending that issues aren't contentious. The entire point of the
paper is to describe all of those controversial aspects in detail, why they
are logically consistent with a valid generalization even though they are
initially unintuitive to some people, along with comparisons to the
alternative approaches. The result is something with finer-grained
abstractions (which is both good and bad), it changes potential run-time
errors into compile-time errors, and simplifies contracts. If people weigh
aspects of the idea in different ways than I do and/or favor intuition over
functionality, which for better or for worse is often the case, then I
can't argue with that. You've already made it very clear that you
personally don't like it, and I don't expect to change your opinion or
general consensus. That's not the point -- it's just an idea that warrants
being formally represented and understood. Despite you being extremely
vocally against the idea in this thread, people other than myself side with
this approach over others, including those who are standard library
implementors. If you're really so against it, then take comfort in the fact
that, paper or not, it's extremely unlikely this approach would change
consensus.
Anyway, if you really want to try to tear apart the paper for whatever
reason, come to Jacksonville assuming I end up actually submitting a paper
about this, though I doubt your personal attendance will be necessary. I
don't know if I would present it at all, or if I did, that it would even be
in the form of a proposal.
Relax.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134fb0ad01ffb0523336bd6
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Oct 28, 2015 at 4:45 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex">When you're putting together =
your proposal, you should make certain to include the necessary changes to =
`optional` that your version requires.<br></blockquote><div><br></div><div>=
Yes, I know the requirements of my own suggestions and what the controversi=
al aspects are. I do not believe in brushing aspects under the rug or prete=
nding that issues aren't contentious. The entire point of the paper is =
to describe all of those controversial aspects in detail, why they are logi=
cally consistent with a valid generalization even though they are initially=
unintuitive to some people, along with comparisons to the alternative appr=
oaches. The result is something with finer-grained abstractions (which is b=
oth good and bad), it changes potential run-time errors into compile-time e=
rrors, and simplifies contracts. If people weigh aspects of the idea in dif=
ferent ways than I do and/or favor intuition over functionality, which for =
better or for worse is often the case, then I can't argue with that. Yo=
u've already made it very clear that you personally don't like it, =
and I don't expect to change your opinion or general consensus. That=
9;s not the point -- it's just an idea that warrants being formally rep=
resented and understood. Despite you being extremely vocally against the id=
ea in this thread, people other than myself side with this approach over ot=
hers, including those who are standard library implementors. If you're =
really so against it, then take comfort in the fact that, paper or not, it&=
#39;s extremely unlikely this approach would change consensus.</div><div><b=
r></div><div>Anyway, if you really want to try to tear apart the paper for =
whatever reason, come to Jacksonville assuming I end up actually submitting=
a paper about this, though I doubt your personal attendance will be necess=
ary. I don't know if I would present it at all, or if I did, that it wo=
uld even be in the form of a proposal.</div><div><br></div><div>Relax.</div=
></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134fb0ad01ffb0523336bd6--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Wed, 28 Oct 2015 19:43:03 -0500
Raw View
--001a113dccc25d0c850523339a7d
Content-Type: text/plain; charset=UTF-8
On 28 October 2015 at 12:09, Tony V E <tvaneerd@gmail.com> wrote:
> That's worth bringing up in the committee. Are you considering an email,
> or shall I?
>
You're the chair of the mythical bike shedding SG, aren't you? :-)
Feel free to write it. I wasn't in Kona this time, so I don't feel right
in bringing it up based on hearsay. (I'm not doubting Matt, but I didn't
see that particular name in any of the wiki notes, which means I probably
didn't look hard enough.)
Nevin :-)
--
Nevin ":-)" Liber <mailto:nevin@c <nevin@eviloverlord.com>plusplusguy.com>
(847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113dccc25d0c850523339a7d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra">On 28 October 2015 at 12:09, To=
ny V E <span dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=
=3D"_blank">tvaneerd@gmail.com</a>></span> wrote:<br><div 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>That's worth bringing up in=
the committee.=C2=A0 Are you considering an email, or shall I?</div></bloc=
kquote><div><br></div><div>You're the chair of the mythical bike sheddi=
ng SG, aren't you? :-)</div><div><br></div><div>Feel free to write it.=
=C2=A0 I wasn't in Kona this time, so I don't feel right in bringin=
g it up based on hearsay. =C2=A0(I'm not doubting Matt, but I didn'=
t see that particular name in any of the wiki notes, which means I probably=
didn't look hard enough.)</div><div>=C2=A0Nevin :-)</div></div>-- <br>=
<div class=3D"gmail_signature">=C2=A0Nevin ":-)" Liber=C2=A0 <=
mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@c<=
/a><a href=3D"http://plusplusguy.com">plusplusguy.com</a>>=C2=A0 (847) 6=
91-1404</div>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113dccc25d0c850523339a7d--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 28 Oct 2015 17:50:51 -0700
Raw View
--089e0115f052ea2bdc052333b34b
Content-Type: text/plain; charset=UTF-8
On Wed, Oct 28, 2015 at 5:43 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
>
> Feel free to write it. I wasn't in Kona this time, so I don't feel right
> in bringing it up based on hearsay. (I'm not doubting Matt, but I didn't
> see that particular name in any of the wiki notes, which means I probably
> didn't look hard enough.)
>
I could be remembering incorrectly, but at the very least I'm pretty sure
the name did have "corrupted" in it in some form, and I'm relatively
certain it was ".corrupted_by_exception()." If I'm wrong, then that's my
mistake. Either way, I'm sure this is something that wouldn't exactly be
controversial to revisit. Maybe we can revive a push for ".unvariant()" ;)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0115f052ea2bdc052333b34b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Oct 28, 2015 at 5:43 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"m=
ailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&=
gt;</span> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div>Feel free to write it.=C2=
=A0 I wasn't in Kona this time, so I don't feel right in bringing i=
t up based on hearsay. =C2=A0(I'm not doubting Matt, but I didn't s=
ee that particular name in any of the wiki notes, which means I probably di=
dn't look hard enough.)</div></div></div></div></blockquote><div><br></=
div><div>I could be remembering incorrectly, but at the very least I'm =
pretty sure the name did have "corrupted" in it in some form, and=
I'm relatively certain it was ".corrupted_by_exception()." I=
f I'm wrong, then that's my mistake. Either way, I'm sure this =
is something that wouldn't exactly be controversial to revisit. Maybe w=
e can revive a push for ".unvariant()" ;)</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0115f052ea2bdc052333b34b--
.
Author: Patrice Roy <patricer@gmail.com>
Date: Wed, 28 Oct 2015 21:45:52 -0400
Raw View
--047d7bdc0dd2a19a84052334781e
Content-Type: text/plain; charset=UTF-8
The name was picked by a two-level straw poll. We had a long list of names,
eliminated a bunch, and ended up with this. I doubt it would turn into a
dogmatic issue should there be a reasonable reason (!) to use something
else, and there were other not-so-bad candidates. It was a close call.
What we were trying to avoid was a name that would make it likely people
would see it as usable (valid(), good(), things that seem usable like
that). We had a host of options, and no-one seemed to think that
corrupted_... would be inconvenient for some users, but it might be an
oversight on our part. Please write a paper if this is a real problem;
we'll look into it.
2015-10-28 13:09 GMT-04:00 Tony V E <tvaneerd@gmail.com>:
>
>
> On Tue, Oct 27, 2015 at 1:37 PM, Nevin Liber <nevin@eviloverlord.com>
> wrote:
>
>> On 27 October 2015 at 12:03, 'Matt Calabrese' via ISO C++ Standard -
>> Future Proposals <std-proposals@isocpp.org> wrote:
>>
>>
>>> The idea from those in favor of the invalid state is that you can only
>>> get into that state by way of failed assignment or emplacement, so in
>>> practice you don't need to check for it (a sentiment that I strongly
>>> disagree with as IMO it means the rare bugs will just be more subtle, but
>>> it is better than an empty state that is more prominent).
>>>
>>
>> I just don't see how it is any more subtle than never-empty (as opposed
>> to the strong exception safety guarantee, which no one actually proposed).
>> Even with never-empty, while you can reason about what *type* the
>> variant is engaged with, it is still very difficult (if not impossible w/o
>> knowing the "from" state) to reason about the *value* that type has.
>>
>>
>>> There was some bike-shedding about naming the function for the invalid
>>> state and I think we ended up with ".corrupted_by_exception()."
>>>
>>
>> Ugh. Putting words like "corrupted" in function names makes it difficult
>> to use in many regulated industries.
>>
>
> That's worth bringing up in the committee. Are you considering an email,
> or shall I?
>
> Tony
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7bdc0dd2a19a84052334781e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>The name was picked by a two-level straw poll. We had=
a long list of names, eliminated a bunch, and ended up with this. I doubt =
it would turn into a dogmatic issue should there be a reasonable reason (!)=
to use something else, and there were other not-so-bad candidates. It was =
a close call.<br><br></div>What we were trying to avoid was a name that wou=
ld make it likely people would see it as usable (valid(), good(), things th=
at seem usable like that). We had a host of options, and no-one seemed to t=
hink that corrupted_... would be inconvenient for some users, but it might =
be an oversight on our part. Please write a paper if this is a real problem=
; we'll look into it.<br></div><div class=3D"gmail_extra"><br><div clas=
s=3D"gmail_quote">2015-10-28 13:09 GMT-04:00 Tony V E <span dir=3D"ltr"><=
;<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com=
</a>></span>:<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"><br><di=
v class=3D"gmail_extra"><br><div class=3D"gmail_quote"><span class=3D"">On =
Tue, Oct 27, 2015 at 1:37 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"=
mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.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=
>On 27 October 2015 at 12:03, 'Matt Calabrese' via ISO C++ Standard=
- Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals@i=
socpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrote:=
<br></span><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"=
gmail_extra"><div class=3D"gmail_quote"><div>The idea from those in favor o=
f the invalid state is that you can only get into that state by way of fail=
ed assignment or emplacement, so in practice you don't need to check fo=
r it (a sentiment that I strongly disagree with as IMO it means the rare bu=
gs will just be more subtle, but it is better than an empty state that is m=
ore prominent).</div></div></div></div></blockquote><div><br></div></span><=
div>I just don't see how it is any more subtle than never-empty (as opp=
osed to the strong exception safety guarantee, which no one actually propos=
ed).=C2=A0 Even with never-empty, while you can reason about what <i>type</=
i>=C2=A0the variant is engaged with, it is still very difficult (if not imp=
ossible w/o knowing the "from" state) to reason about the <i>valu=
e</i>=C2=A0that type has.</div><span><div>=C2=A0</div><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 class=3D"gmail_extra"><div class=3D"gmail_q=
uote"><div> There was some bike-shedding about naming the function for the =
invalid state and I think we ended up with ".corrupted_by_exception().=
"</div></div></div></div></blockquote><div><br></div></span><div>Ugh.=
=C2=A0 Putting words like "corrupted" in function names makes it =
difficult to use in many regulated industries.</div></div></div></div></blo=
ckquote><div><br></div></span><div>That's worth bringing up in the comm=
ittee.=C2=A0 Are you considering an email, or shall I?<span class=3D"HOEnZb=
"><font color=3D"#888888"><br></font></span></div></div><span class=3D"HOEn=
Zb"><font color=3D"#888888"><br></font></span></div><span class=3D"HOEnZb">=
<font color=3D"#888888"><div class=3D"gmail_extra">Tony<br><br></div></font=
></span></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--047d7bdc0dd2a19a84052334781e--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Thu, 29 Oct 2015 10:26:21 -0400
Raw View
--089e0115fdda5bcfe205233f18bb
Content-Type: text/plain; charset=UTF-8
If only we could come up with a good name for the SG...
On Wed, Oct 28, 2015 at 8:43 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 28 October 2015 at 12:09, Tony V E <tvaneerd@gmail.com> wrote:
>
>> That's worth bringing up in the committee. Are you considering an email,
>> or shall I?
>>
>
> You're the chair of the mythical bike shedding SG, aren't you? :-)
>
> Feel free to write it. I wasn't in Kona this time, so I don't feel right
> in bringing it up based on hearsay. (I'm not doubting Matt, but I didn't
> see that particular name in any of the wiki notes, which means I probably
> didn't look hard enough.)
> Nevin :-)
> --
> Nevin ":-)" Liber <mailto:nevin@c <nevin@eviloverlord.com>
> plusplusguy.com> (847) 691-1404
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0115fdda5bcfe205233f18bb
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">If only we could come up with a good name for the SG...<br=
></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Wed, Oc=
t 28, 2015 at 8:43 PM, Nevin Liber <span dir=3D"ltr"><<a href=3D"mailto:=
nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>></s=
pan> 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"><div class=
=3D"gmail_extra"><span class=3D"">On 28 October 2015 at 12:09, Tony V E <sp=
an dir=3D"ltr"><<a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">=
tvaneerd@gmail.com</a>></span> wrote:<br></span><div class=3D"gmail_quot=
e"><span class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0=
.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>That's worth br=
inging up in the committee.=C2=A0 Are you considering an email, or shall I?=
</div></blockquote><div><br></div></span><div>You're the chair of the m=
ythical bike shedding SG, aren't you? :-)</div><div><br></div><div>Feel=
free to write it.=C2=A0 I wasn't in Kona this time, so I don't fee=
l right in bringing it up based on hearsay. =C2=A0(I'm not doubting Mat=
t, but I didn't see that particular name in any of the wiki notes, whic=
h means I probably didn't look hard enough.)</div><span class=3D"HOEnZb=
"><font color=3D"#888888"><div>=C2=A0Nevin :-)</div></font></span></div><sp=
an class=3D"HOEnZb"><font color=3D"#888888">-- <br><div>=C2=A0Nevin ":=
-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" t=
arget=3D"_blank">nevin@c</a><a href=3D"http://plusplusguy.com" target=3D"_b=
lank">plusplusguy.com</a>>=C2=A0 <a href=3D"tel:%28847%29%20691-1404" va=
lue=3D"+18476911404" target=3D"_blank">(847) 691-1404</a></div>
</font></span></div></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--089e0115fdda5bcfe205233f18bb--
.
Author: "'Matt Calabrese' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 29 Oct 2015 10:45:58 -0700
Raw View
--001a113b056a364cc1052341e2b0
Content-Type: text/plain; charset=UTF-8
On Thu, Oct 29, 2015 at 7:26 AM, Tony V E <tvaneerd@gmail.com> wrote:
> If only we could come up with a good name for the SG...
>
Heh.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113b056a364cc1052341e2b0
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, Oct 29, 2015 at 7:26 AM, Tony V E <span dir=3D"ltr"><<a href=3D"mail=
to:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</a>></span> =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">If only we could =
come up with a good name for the SG...</div></blockquote><div><br></div><di=
v>Heh.=C2=A0</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113b056a364cc1052341e2b0--
.
Author: carterd@gmail.com
Date: Sat, 31 Oct 2015 03:47:01 -0700 (PDT)
Raw View
------=_Part_35_1104154190.1446288421949
Content-Type: multipart/alternative;
boundary="----=_Part_36_1773489931.1446288421949"
------=_Part_36_1773489931.1446288421949
Content-Type: text/plain; charset=UTF-8
In my variant implementation
<https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/Misc/Variant.h>
the value is set from the first default-constructible bounded type found in
the list, or otherwise it static asserts if none found.
I'm using the variant in my JSON library
<https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/String/Json.h>to
much success.
On Friday, June 5, 2015 at 1:17:51 AM UTC-7, Markus Grech wrote:
>
> Hi everyone,
>
> I would like to voice my concerns about default construction of
> std::variant and std::monostate. The proposal did not make clear to me why
> default constructed empty state is such a big issue in the first place and
> the current alternative suffers from significant drawbacks:
>
> - To me it is very surprising that variant tries to default-construct
> the first type. Why not the 2nd, 5th type? I'd rather have variant have no
> default constructor than some arbitrary decision.
> - It is yet another special case that users need to be taught about
> and frankly, it's not pretty either. Users have to remember "Oh, I have to
> use this std::monostate workaround if my type is not default
> constructible!". *Hacks* (another spelling for 'workaround') are *bad*.
> - It does not play well with changes. Imagine if the user-defined type
> that was previously default constructible has its default constructor
> removed. Now the users needs to add std::monostate all over the place and
> fix up all the indices for index-based access.
>
> There needs to be a better solution. I do think that having an empty state
> semantically fails at the idea of variant in the first place ("either A or
> B", not "either A, B or empty"), but it is not the end of the world. The
> current std::monostate design however has significant issues that IMHO
> deserve another look.
>
> Markus
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_36_1773489931.1446288421949
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">In my <a href=3D"https://github.com/Qarterd/Honeycomb/blob=
/master/src/common/Honey/Misc/Variant.h">variant implementation</a> the val=
ue is set from the first default-constructible bounded type found in the li=
st, or otherwise it static asserts if none found.<br><br>I'm using the =
variant in my <a href=3D"https://github.com/Qarterd/Honeycomb/blob/master/s=
rc/common/Honey/String/Json.h">JSON library </a>to much success.<br><br>On =
Friday, June 5, 2015 at 1:17:51 AM UTC-7, Markus Grech wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Hi everyone,<div><br></div>=
<div>I would like to voice my concerns about default construction of std::v=
ariant and std::monostate. The proposal did not make clear to me why defaul=
t constructed empty state is such a big issue in the first place and the cu=
rrent alternative suffers from significant drawbacks:</div><div><ul><li><sp=
an style=3D"line-height:normal">To me it is very surprising that variant tr=
ies to default-construct the first type. Why not the 2nd, 5th type? I'd=
rather have variant have no default constructor than some arbitrary decisi=
on.</span></li><li><span style=3D"line-height:normal">It is yet another spe=
cial case that users need to be taught about and frankly, it's not pret=
ty either. Users have to remember "Oh, I have to use this std::monosta=
te workaround if my type is not default constructible!". <i>Hacks</i> =
(another spelling for 'workaround') are <i>bad</i>.</span></li><li>=
<span style=3D"line-height:normal">It does not play well with changes. Imag=
ine if the user-defined type that was previously default constructible has =
its default constructor removed. Now the users needs to add std::monostate =
all over the place and fix up all the indices for index-based access.</span=
></li></ul><div>There needs to be a better solution. I do think that having=
an empty state semantically fails at the idea of variant in the first plac=
e ("either A or B", not "either A, B or empty"), but it=
is not the end of the world. The current std::monostate design however has=
significant issues that IMHO deserve another look.</div></div><div><br></d=
iv><div>Markus</div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_36_1773489931.1446288421949--
------=_Part_35_1104154190.1446288421949--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Sat, 31 Oct 2015 13:51:38 -0400
Raw View
--001a1140346c2a33f105236a32ac
Content-Type: text/plain; charset=UTF-8
On Sat, Oct 31, 2015 at 6:47 AM, <carterd@gmail.com> wrote:
> In my variant implementation
> <https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/Misc/Variant.h>
> the value is set from the first default-constructible bounded type found in
> the list, or otherwise it static asserts if none found.
>
An issue there is that it becomes too easy to change the default value of a
variant<Foo,Bar>. The author/maintainer of Foo, by removing the default
constructor, *silently* changes the value of some variant in a far off
piece of code they might not even know exists.
Whereas all the other code using Foo's default constructor fails *loudly*,
ie at compile time. The maintainer can go fix those cases (or at least
inform others), but users of variant<Foo,Bar> may not be informed.
And maybe that variant<Foo,Bar> code will/should still work, but code often
ends up relying on things that it shouldn't, and most likely some code will
fail badly when its starting state is changed.
>
> I'm using the variant in my JSON library
> <https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/String/Json.h>to
> much success.
>
> On Friday, June 5, 2015 at 1:17:51 AM UTC-7, Markus Grech wrote:
>>
>> Hi everyone,
>>
>> I would like to voice my concerns about default construction of
>> std::variant and std::monostate. The proposal did not make clear to me why
>> default constructed empty state is such a big issue in the first place and
>> the current alternative suffers from significant drawbacks:
>>
>> - To me it is very surprising that variant tries to default-construct
>> the first type. Why not the 2nd, 5th type? I'd rather have variant have no
>> default constructor than some arbitrary decision.
>> - It is yet another special case that users need to be taught about
>> and frankly, it's not pretty either. Users have to remember "Oh, I have to
>> use this std::monostate workaround if my type is not default
>> constructible!". *Hacks* (another spelling for 'workaround') are *bad*
>> .
>> - It does not play well with changes. Imagine if the user-defined
>> type that was previously default constructible has its default constructor
>> removed. Now the users needs to add std::monostate all over the place and
>> fix up all the indices for index-based access.
>>
>> There needs to be a better solution. I do think that having an empty
>> state semantically fails at the idea of variant in the first place ("either
>> A or B", not "either A, B or empty"), but it is not the end of the world.
>> The current std::monostate design however has significant issues that IMHO
>> deserve another look.
>>
>> Markus
>>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1140346c2a33f105236a32ac
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sat, Oct 31, 2015 at 6:47 AM, <span dir=3D"ltr"><<a href=3D"mail=
to:carterd@gmail.com" target=3D"_blank">carterd@gmail.com</a>></span> wr=
ote:<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">In my <a href=3D"ht=
tps://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/Misc/Varian=
t.h" target=3D"_blank">variant implementation</a> the value is set from the=
first default-constructible bounded type found in the list, or otherwise i=
t static asserts if none found.<br></div></blockquote><div><br></div><div>A=
n issue there is that it becomes too easy to change the default value of a =
variant<Foo,Bar>.=C2=A0 The author/maintainer of Foo, by removing the=
default constructor, *silently* changes the value of some variant in a far=
off piece of code they might not even know exists.<br><br></div><div>Where=
as all the other code using Foo's default constructor fails *loudly*, i=
e at compile time.=C2=A0 The maintainer can go fix those cases (or at least=
inform others), but users of variant<Foo,Bar> may not be informed.<b=
r><br></div><div>And maybe that variant<Foo,Bar> code will/should sti=
ll work, but code often ends up relying on things that it shouldn't, an=
d most likely some code will fail badly when its starting state is changed.=
<br></div><div><br></div><div>=C2=A0<br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><br>I'm using the variant in my <a href=3D"https://g=
ithub.com/Qarterd/Honeycomb/blob/master/src/common/Honey/String/Json.h" tar=
get=3D"_blank">JSON library </a>to much success.<br><br>On Friday, June 5, =
2015 at 1:17:51 AM UTC-7, Markus Grech wrote:<blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr">Hi everyone,<div><br></div><div>I would like to =
voice my concerns about default construction of std::variant and std::monos=
tate. The proposal did not make clear to me why default constructed empty s=
tate is such a big issue in the first place and the current alternative suf=
fers from significant drawbacks:</div><div><ul><li><span style=3D"line-heig=
ht:normal">To me it is very surprising that variant tries to default-constr=
uct the first type. Why not the 2nd, 5th type? I'd rather have variant =
have no default constructor than some arbitrary decision.</span></li><li><s=
pan style=3D"line-height:normal">It is yet another special case that users =
need to be taught about and frankly, it's not pretty either. Users have=
to remember "Oh, I have to use this std::monostate workaround if my t=
ype is not default constructible!". <i>Hacks</i> (another spelling for=
'workaround') are <i>bad</i>.</span></li><li><span style=3D"line-h=
eight:normal">It does not play well with changes. Imagine if the user-defin=
ed type that was previously default constructible has its default construct=
or removed. Now the users needs to add std::monostate all over the place an=
d fix up all the indices for index-based access.</span></li></ul><div>There=
needs to be a better solution. I do think that having an empty state seman=
tically fails at the idea of variant in the first place ("either A or =
B", not "either A, B or empty"), but it is not the end of th=
e world. The current std::monostate design however has significant issues t=
hat IMHO deserve another look.</div></div><div><br></div><div>Markus</div><=
/div></blockquote></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1140346c2a33f105236a32ac--
.
Author: Dan Carter <carterd@gmail.com>
Date: Sat, 31 Oct 2015 13:45:27 -0700
Raw View
This is a multi-part message in MIME format.
--------------000600040401050409070705
Content-Type: text/plain; charset=UTF-8
It is a *variant* after all, if you default construct it then you're
making a statement that your code can handle it being initialized to
*any* default constructible, this gives the author of Foo the *freedom*
to remove their default constructor if they wish. The nature of working
with variants means that you're willing to accept a different kind of
contract than working with basic types. The only rule here is that the
variant can not exist in an uninitialized state (that's what optionals
are for).
In my JSON library
<https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/String/Json.h>
for example Null is an explicit bounded type, and JSON values are
default constructed by initializing their variant superclass to Null.
They do not default construct their variant superclass, as they are
never supposed to be initialized to double/string etc. which would be
allowed by the variant contract if Null ever changed.
On 2015-10-31, 10:51 AM, Tony V E wrote:
>
> On Sat, Oct 31, 2015 at 6:47 AM, <carterd@gmail.com
> <mailto:carterd@gmail.com>> wrote:
>
> In my variant implementation
> <https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/Misc/Variant.h>
> the value is set from the first default-constructible bounded type
> found in the list, or otherwise it static asserts if none found.
>
>
> An issue there is that it becomes too easy to change the default value
> of a variant<Foo,Bar>. The author/maintainer of Foo, by removing the
> default constructor, *silently* changes the value of some variant in a
> far off piece of code they might not even know exists.
>
> Whereas all the other code using Foo's default constructor fails
> *loudly*, ie at compile time. The maintainer can go fix those cases
> (or at least inform others), but users of variant<Foo,Bar> may not be
> informed.
>
> And maybe that variant<Foo,Bar> code will/should still work, but code
> often ends up relying on things that it shouldn't, and most likely
> some code will fail badly when its starting state is changed.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------000600040401050409070705
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3DUTF-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
It is a *variant* after all, if you default construct it then you're
making a statement that your code can handle it being initialized to
*any* default constructible, this gives the author of Foo the
*freedom* to remove their default constructor if they wish. The
nature of working with variants means that you're willing to accept
a different kind of contract than working with basic types. The only
rule here is that the variant can not exist in an uninitialized
state (that's what optionals are for).<br>
<br>
In my <a
href=3D"https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/S=
tring/Json.h">JSON
library</a> for example Null is an explicit bounded type, and JSON
values are default constructed by initializing their variant
superclass to Null. They do not default construct their variant
superclass, as they are never supposed to be initialized to
double/string etc. which would be allowed by the variant contract if
Null ever changed.<br>
<br>
<div class=3D"moz-cite-prefix">On 2015-10-31, 10:51 AM, Tony V E
wrote:</div>
<blockquote
cite=3D"mid:CAOHCbis5PDB4cvhRa4CSS1krR1gQdJ97mg-YkuW2fh2Nv=3DC0yA@mail.gmai=
l.com"
type=3D"cite">
<div dir=3D"ltr"><br>
<div class=3D"gmail_extra">
<div class=3D"gmail_quote">On Sat, Oct 31, 2015 at 6:47 AM, <span
dir=3D"ltr"><<a moz-do-not-send=3D"true"
href=3D"mailto:carterd@gmail.com" target=3D"_blank">carterd=
@gmail.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">In my <a moz-do-not-send=3D"true"
href=3D"https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/M=
isc/Variant.h"
target=3D"_blank">variant implementation</a> the value
is set from the first default-constructible bounded type
found in the list, or otherwise it static asserts if
none found.<br>
</div>
</blockquote>
<div><br>
</div>
<div>An issue there is that it becomes too easy to change
the default value of a variant<Foo,Bar>.=C2=A0 The
author/maintainer of Foo, by removing the default
constructor, *silently* changes the value of some variant
in a far off piece of code they might not even know
exists.<br>
<br>
</div>
<div>Whereas all the other code using Foo's default
constructor fails *loudly*, ie at compile time.=C2=A0 The
maintainer can go fix those cases (or at least inform
others), but users of variant<Foo,Bar> may not be
informed.<br>
<br>
</div>
<div>And maybe that variant<Foo,Bar> code will/should
still work, but code often ends up relying on things that
it shouldn't, and most likely some code will fail badly
when its starting state is changed.<br>
</div>
</div>
</div>
</div>
</blockquote>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--------------000600040401050409070705--
.
Author: Dan Carter <dan@carter.email>
Date: Sat, 31 Oct 2015 14:30:53 -0700
Raw View
This is a multi-part message in MIME format.
--------------090209010400000600090609
Content-Type: text/plain; charset=UTF-8
One thing to add, in this system if you want to narrow variant's default
construction contract you could have something like
std::variant_default_types<variant> which returns a tuple, and variant
would then select the first default constructible.
On 2015-10-31, 1:45 PM, Dan Carter wrote:
> It is a *variant* after all, if you default construct it then you're
> making a statement that your code can handle it being initialized to
> *any* default constructible, this gives the author of Foo the
> *freedom* to remove their default constructor if they wish. The nature
> of working with variants means that you're willing to accept a
> different kind of contract than working with basic types. The only
> rule here is that the variant can not exist in an uninitialized state
> (that's what optionals are for).
>
> In my JSON library
> <https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/String/Json.h>
> for example Null is an explicit bounded type, and JSON values are
> default constructed by initializing their variant superclass to Null.
> They do not default construct their variant superclass, as they are
> never supposed to be initialized to double/string etc. which would be
> allowed by the variant contract if Null ever changed.
>
> On 2015-10-31, 10:51 AM, Tony V E wrote:
>>
>> On Sat, Oct 31, 2015 at 6:47 AM, <carterd@gmail.com
>> <mailto:carterd@gmail.com>> wrote:
>>
>> In my variant implementation
>> <https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/Misc/Variant.h>
>> the value is set from the first default-constructible bounded
>> type found in the list, or otherwise it static asserts if none found.
>>
>>
>> An issue there is that it becomes too easy to change the default
>> value of a variant<Foo,Bar>. The author/maintainer of Foo, by
>> removing the default constructor, *silently* changes the value of
>> some variant in a far off piece of code they might not even know exists.
>>
>> Whereas all the other code using Foo's default constructor fails
>> *loudly*, ie at compile time. The maintainer can go fix those cases
>> (or at least inform others), but users of variant<Foo,Bar> may not be
>> informed.
>>
>> And maybe that variant<Foo,Bar> code will/should still work, but code
>> often ends up relying on things that it shouldn't, and most likely
>> some code will fail badly when its starting state is changed.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------090209010400000600090609
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3DUTF-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
One thing to add, in this system if you want to narrow variant's
default construction contract you could have something like
std::variant_default_types<variant> which returns a tuple, and
variant would then select the first default constructible.<br>
<br>
<div class=3D"moz-cite-prefix">On 2015-10-31, 1:45 PM, Dan Carter
wrote:<br>
</div>
<blockquote cite=3D"mid:56352867.4090308@gmail.com" type=3D"cite">
<meta content=3D"text/html; charset=3DUTF-8" http-equiv=3D"Content-Ty=
pe">
It is a *variant* after all, if you default construct it then
you're making a statement that your code can handle it being
initialized to *any* default constructible, this gives the author
of Foo the *freedom* to remove their default constructor if they
wish. The nature of working with variants means that you're
willing to accept a different kind of contract than working with
basic types. The only rule here is that the variant can not exist
in an uninitialized state (that's what optionals are for).<br>
<br>
In my <a moz-do-not-send=3D"true"
href=3D"https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/S=
tring/Json.h">JSON
library</a> for example Null is an explicit bounded type, and
JSON values are default constructed by initializing their variant
superclass to Null. They do not default construct their variant
superclass, as they are never supposed to be initialized to
double/string etc. which would be allowed by the variant contract
if Null ever changed.<br>
<br>
<div class=3D"moz-cite-prefix">On 2015-10-31, 10:51 AM, Tony V E
wrote:</div>
<blockquote
cite=3D"mid:CAOHCbis5PDB4cvhRa4CSS1krR1gQdJ97mg-YkuW2fh2Nv=3DC0yA@mail.gmai=
l.com"
type=3D"cite">
<div dir=3D"ltr"><br>
<div class=3D"gmail_extra">
<div class=3D"gmail_quote">On Sat, Oct 31, 2015 at 6:47 AM, <sp=
an
dir=3D"ltr"><<a moz-do-not-send=3D"true"
href=3D"mailto:carterd@gmail.com" target=3D"_blank">carte=
rd@gmail.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">In my <a moz-do-not-send=3D"true"
href=3D"https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/M=
isc/Variant.h"
target=3D"_blank">variant implementation</a> the value
is set from the first default-constructible bounded
type found in the list, or otherwise it static asserts
if none found.<br>
</div>
</blockquote>
<div><br>
</div>
<div>An issue there is that it becomes too easy to change
the default value of a variant<Foo,Bar>.=C2=A0 The
author/maintainer of Foo, by removing the default
constructor, *silently* changes the value of some
variant in a far off piece of code they might not even
know exists.<br>
<br>
</div>
<div>Whereas all the other code using Foo's default
constructor fails *loudly*, ie at compile time.=C2=A0 The
maintainer can go fix those cases (or at least inform
others), but users of variant<Foo,Bar> may not be
informed.<br>
<br>
</div>
<div>And maybe that variant<Foo,Bar> code
will/should still work, but code often ends up relying
on things that it shouldn't, and most likely some code
will fail badly when its starting state is changed.<br>
</div>
</div>
</div>
</div>
</blockquote>
<br>
</blockquote>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <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 />
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 />
--------------090209010400000600090609--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Sat, 31 Oct 2015 23:59:53 -0400
Raw View
--001a11c36bdc6b6e08052372b1cf
Content-Type: text/plain; charset=UTF-8
On Sat, Oct 31, 2015 at 4:45 PM, Dan Carter <carterd@gmail.com> wrote:
> It is a *variant* after all, if you default construct it then you're
> making a statement that your code can handle it being initialized to *any*
> default constructible,
>
You make that statement when you write the code. But for the next 3 years
the code only ever sees variants defaulted to Foo. So code evolves, and
somewhere over those 3 years it turns out the code is silently depending on
the variant starting as a Foo, but no one notices.
I don't think your default construction rule is wrong or crazy, but I think
the above is a valid consideration.
If variant default constructed to a different one every time it was
compiled :-) then maybe I wouldn't be as worried.
Tony
> this gives the author of Foo the *freedom* to remove their default
> constructor if they wish. The nature of working with variants means that
> you're willing to accept a different kind of contract than working with
> basic types. The only rule here is that the variant can not exist in an
> uninitialized state (that's what optionals are for).
>
> In my JSON library
> <https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/String/Json.h>
> for example Null is an explicit bounded type, and JSON values are default
> constructed by initializing their variant superclass to Null. They do not
> default construct their variant superclass, as they are never supposed to
> be initialized to double/string etc. which would be allowed by the variant
> contract if Null ever changed.
>
> On 2015-10-31, 10:51 AM, Tony V E wrote:
>
>
> On Sat, Oct 31, 2015 at 6:47 AM, <carterd@gmail.com> wrote:
>
>> In my variant implementation
>> <https://github.com/Qarterd/Honeycomb/blob/master/src/common/Honey/Misc/Variant.h>
>> the value is set from the first default-constructible bounded type found in
>> the list, or otherwise it static asserts if none found.
>>
>
> An issue there is that it becomes too easy to change the default value of
> a variant<Foo,Bar>. The author/maintainer of Foo, by removing the default
> constructor, *silently* changes the value of some variant in a far off
> piece of code they might not even know exists.
>
> Whereas all the other code using Foo's default constructor fails *loudly*,
> ie at compile time. The maintainer can go fix those cases (or at least
> inform others), but users of variant<Foo,Bar> may not be informed.
>
> And maybe that variant<Foo,Bar> code will/should still work, but code
> often ends up relying on things that it shouldn't, and most likely some
> code will fail badly when its starting state is changed.
>
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c36bdc6b6e08052372b1cf
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Sat, Oct 31, 2015 at 4:45 PM, Dan Carter <span dir=3D"ltr"><<a hr=
ef=3D"mailto:carterd@gmail.com" target=3D"_blank">carterd@gmail.com</a>>=
</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
It is a *variant* after all, if you default construct it then you'r=
e
making a statement that your code can handle it being initialized to
*any* default constructible,</div></blockquote><div><br></div><div>You =
make that statement when you write the code.=C2=A0 But for the next 3 years=
the code only ever sees variants defaulted to Foo.=C2=A0 So code evolves, =
and somewhere over those 3 years it turns out the code is silently dependin=
g on the variant starting as a Foo, but no one notices.<br><br></div>I don&=
#39;t think your default construction rule is wrong or crazy, but I think t=
he above is a valid consideration.<br><div><br><div>If variant default cons=
tructed to a different one every time it was compiled :-) then maybe I woul=
dn't be as worried.<br><br>Tony<br><br></div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid=
rgb(204,204,204);padding-left:1ex"><div bgcolor=3D"#FFFFFF" text=3D"#00000=
0"> this gives the author of Foo the
*freedom* to remove their default constructor if they wish. The
nature of working with variants means that you're willing to accept
a different kind of contract than working with basic types. The only
rule here is that the variant can not exist in an uninitialized
state (that's what optionals are for).<br>
<br>
In my <a href=3D"https://github.com/Qarterd/Honeycomb/blob/master/src/c=
ommon/Honey/String/Json.h" target=3D"_blank">JSON
library</a> for example Null is an explicit bounded type, and JSON
values are default constructed by initializing their variant
superclass to Null. They do not default construct their variant
superclass, as they are never supposed to be initialized to
double/string etc. which would be allowed by the variant contract if
Null ever changed.<span class=3D""><br>
<br>
<div>On 2015-10-31, 10:51 AM, Tony V E
wrote:</div>
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
<div class=3D"gmail_extra">
<div class=3D"gmail_quote">On Sat, Oct 31, 2015 at 6:47 AM, <span=
dir=3D"ltr"><<a href=3D"mailto:carterd@gmail.com" target=3D"_blank">car=
terd@gmail.com</a>></span>
wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir=3D"ltr">In my <a href=3D"https://github.com/Qarterd/=
Honeycomb/blob/master/src/common/Honey/Misc/Variant.h" target=3D"_blank">va=
riant implementation</a> the value
is set from the first default-constructible bounded type
found in the list, or otherwise it static asserts if
none found.<br>
</div>
</blockquote>
<div><br>
</div>
<div>An issue there is that it becomes too easy to change
the default value of a variant<Foo,Bar>.=C2=A0 The
author/maintainer of Foo, by removing the default
constructor, *silently* changes the value of some variant
in a far off piece of code they might not even know
exists.<br>
<br>
</div>
<div>Whereas all the other code using Foo's default
constructor fails *loudly*, ie at compile time.=C2=A0 The
maintainer can go fix those cases (or at least inform
others), but users of variant<Foo,Bar> may not be
informed.<br>
<br>
</div>
<div>And maybe that variant<Foo,Bar> code will/should
still work, but code often ends up relying on things that
it shouldn't, and most likely some code will fail badly
when its starting state is changed.<br>
</div>
</div>
</div>
</div>
</blockquote>
<br>
</span></div><div class=3D""><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <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" target=3D"_=
blank">std-proposals+unsubscribe@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c36bdc6b6e08052372b1cf--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 31 Oct 2015 21:12:36 -0700 (PDT)
Raw View
------=_Part_2222_431846508.1446351156441
Content-Type: multipart/alternative;
boundary="----=_Part_2223_1133062970.1446351156441"
------=_Part_2223_1133062970.1446351156441
Content-Type: text/plain; charset=UTF-8
On Saturday, October 31, 2015 at 4:45:30 PM UTC-4, Dan Carter wrote:
> It is a *variant* after all, if you default construct it then you're
> making a statement that your code can handle it being initialized to *any*
> default constructible, this gives the author of Foo the *freedom* to remove
> their default constructor if they wish. The nature of working with variants
> means that you're willing to accept a different kind of contract than
> working with basic types.
>
No, that's *your* contract, not the contract. I see no reason why variant
must behave the way you say it should.
First, `Foo` doesn't have the "*freedom* to remove their default
constructor if they wish." By shipping `Foo` with a default constructor,
the author of that class gave its users the freedom to rely on the presence
of said constructor. We could just as much have been writing `Foo f` as
`variant<Foo, Bar> v`. Both of them are equally legal, and both of them are
equally broken if `Foo` stops being default constructible.
As far as I'm concerned, it should be well understood and readily apparent
what the state of the variant is after initialization. If I see `variant<T,
U> v;`, I should be able to know and *rely on* what state it is in, just as
if I had not default initialized it. I shouldn't have to look up T's
constructor to know if it's actually a `U`. With N4542's design, it is
apparent: if that line compiles at all, then it's a `T`. If it doesn't
compiler, then what state it's in doesn't matter.
Even designs that set it to empty on default construction at least set it
to something *consistently*...
Oh, and one more thing. The committee has spent untold quantities of time
nailing down the basic design of variant. They are almost certainly not
going to undo hard-won compromises on contentious issues like what the
default constructor does.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2223_1133062970.1446351156441
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, October 31, 2015 at 4:45:30 PM UTC-4, Dan Car=
ter wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"=
#FFFFFF">It is a *variant* after all, if you default construct it then you&=
#39;re
making a statement that your code can handle it being initialized to
*any* default constructible, this gives the author of Foo the
*freedom* to remove their default constructor if they wish. The
nature of working with variants means that you're willing to accept
a different kind of contract than working with basic types.</div></bloc=
kquote><div><br>No, that's <i>your</i> contract, not the contract. I se=
e no reason why variant must behave the way you say it should.<br><br>First=
, `Foo` doesn't have the "*freedom* to remove their default constr=
uctor if they wish." By shipping `Foo` with a default constructor, the=
author of that class gave its users the freedom to rely on the presence of=
said constructor. We could just as much have been writing `Foo f` as `vari=
ant<Foo, Bar> v`. Both of them are equally legal, and both of them ar=
e equally broken if `Foo` stops being default constructible.<br><br>As far =
as I'm concerned, it should be well understood and readily apparent=20
what the state of the variant is after initialization. If I see=20
`variant<T, U> v;`, I should be able to know and <i>rely on</i>=20
what state it is in, just as if I had not default initialized it. I shouldn=
't have to look up T's constructor to know
if it's actually a `U`. With N4542's design, it is apparent: if th=
at=20
line compiles at all, then it's a `T`. If it doesn't compiler, then=
what
state it's in doesn't matter.<br><br>Even designs that set it to e=
mpty on default construction at least set it to something <i>consistently</=
i>...<br><br>Oh,
and one more thing. The committee has spent untold quantities of time=20
nailing down the basic design of variant. They are almost certainly not=20
going to undo hard-won compromises on contentious issues like what the=20
default constructor does.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2223_1133062970.1446351156441--
------=_Part_2222_431846508.1446351156441--
.