Topic: Variant
Author: DeadMG <wolfeinstein@gmail.com>
Date: Wed, 24 Apr 2013 09:02:35 -0700 (PDT)
Raw View
------=_Part_1086_19395474.1366819355312
Content-Type: text/plain; charset=ISO-8859-1
Are there any existing std::variant proposals? If not, we need to get
cracking on one.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_1086_19395474.1366819355312
Content-Type: text/html; charset=ISO-8859-1
Are there any existing std::variant proposals? If not, we need to get cracking on one.
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
<br />
<br />
------=_Part_1086_19395474.1366819355312--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 24 Apr 2013 19:15:33 +0300
Raw View
--089e0149c50087603a04db1d9cb3
Content-Type: text/plain; charset=ISO-8859-1
On 24 April 2013 19:02, DeadMG <wolfeinstein@gmail.com> wrote:
> Are there any existing std::variant proposals? If not, we need to get
> cracking on one.
>
>
>
Axel Naumann is going to write one. I intend to help him with it. The
realistic target is C++17,
the door on C++14 is closed.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
--089e0149c50087603a04db1d9cb3
Content-Type: text/html; charset=ISO-8859-1
<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On 24 April 2013 19:02, DeadMG <span dir="ltr"><<a href="mailto:wolfeinstein@gmail.com" target="_blank">wolfeinstein@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Are there any existing std::variant proposals? If not, we need to get cracking on one.
<span class="HOEnZb"><font color="#888888"><p></p>
<br></font></span></blockquote><div><br></div><div>Axel Naumann is going to write one. I intend to help him with it. The realistic target is C++17,<br></div><div>the door on C++14 is closed. <br></div></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
<br />
<br />
--089e0149c50087603a04db1d9cb3--
.
Author: Fernando Cacciola <fernando.cacciola@gmail.com>
Date: Wed, 24 Apr 2013 13:17:28 -0300
Raw View
--089e0118279cc6f78f04db1da50e
Content-Type: text/plain; charset=ISO-8859-1
On Wed, Apr 24, 2013 at 1:15 PM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:
>
>
>
> On 24 April 2013 19:02, DeadMG <wolfeinstein@gmail.com> wrote:
>
>> Are there any existing std::variant proposals? If not, we need to get
>> cracking on one.
>>
>>
>>
> Axel Naumann is going to write one. I intend to help him with it. The
> realistic target is C++17,
> the door on C++14 is closed.
>
> Fantastic news.!
Best
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
--089e0118279cc6f78f04db1da50e
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Apr 24, 2013 at 1:15 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:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><div class=3D"gmail_ext=
ra"><br><br><div class=3D"gmail_quote"><div class=3D"im">On 24 April 2013 1=
9:02, DeadMG <span dir=3D"ltr"><<a href=3D"mailto:wolfeinstein@gmail.com=
" target=3D"_blank">wolfeinstein@gmail.com</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">Are there any existing std::variant proposal=
s? If not, we need to get cracking on one.
<span><font color=3D"#888888"><p></p>
<br></font></span></blockquote><div><br></div></div><div>Axel Naumann is go=
ing to write one. I intend to help him with it. The realistic target is C++=
17,<br></div><div>the door on C++14 is closed. <br></div></div><br></div>
</div></blockquote><div>Fantastic news.!<br><br></div><div>Best<br></div><d=
iv><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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--089e0118279cc6f78f04db1da50e--
.
Author: =?UTF-8?Q?Andrzej_Krzemie=C5=84ski?= <akrzemi1@gmail.com>
Date: Wed, 24 Apr 2013 23:18:31 -0700 (PDT)
Raw View
------=_Part_494_15318437.1366870711907
Content-Type: text/plain; charset=ISO-8859-1
> Axel Naumann is going to write one. I intend to help him with it. The
> realistic target is C++17,
> the door on C++14 is closed.
>
Perhaps it is too early, but I can't help bringing this up already. It
looks to me that std::variant will require some compiler magic support in
order to provide the Never-Empty gurantee<http://www.boost.org/doc/libs/1_53_0/doc/html/variant/design.html#variant.design.never-empty>.
It is essential part of variant, but difficult to achieve. Boost.Variant
provides it at the expense of heap memory allocation in copy-assignment. I
guess the expectation for std::variant would be that no such heap
allocation takes place.
Regards,
&rzej
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_494_15318437.1366870711907
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><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>Axel Naumann is going to write one. I intend to=
help him with it. The realistic target is C++17,<br></div><div>the door on=
C++14 is closed. <br></div></div></div></div></blockquote><div><br>Perhaps=
it is too early, but I can't help bringing this up already. It looks to me=
that std::variant will require some compiler magic support in order to pro=
vide the <a href=3D"http://www.boost.org/doc/libs/1_53_0/doc/html/variant/d=
esign.html#variant.design.never-empty">Never-Empty gurantee</a>. It is esse=
ntial part of variant, but difficult to achieve. Boost.Variant provides it =
at the expense of heap memory allocation in copy-assignment. I guess the ex=
pectation for std::variant would be that no such heap allocation takes plac=
e.<br><br>Regards,<br>&rzej<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_494_15318437.1366870711907--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 25 Apr 2013 00:13:30 -0700 (PDT)
Raw View
------=_Part_449_10270804.1366874010194
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
On Wednesday, April 24, 2013 11:18:31 PM UTC-7, Andrzej Krzemie=F1ski wrote=
:
>
> Axel Naumann is going to write one. I intend to help him with it. The=20
>> realistic target is C++17,
>> the door on C++14 is closed.=20
>>
>
> Perhaps it is too early, but I can't help bringing this up already. It=20
> looks to me that std::variant will require some compiler magic support in=
=20
> order to provide the Never-Empty gurantee<http://www.boost.org/doc/libs/1=
_53_0/doc/html/variant/design.html#variant.design.never-empty>.=20
> It is essential part of variant, but difficult to achieve. Boost.Variant=
=20
> provides it at the expense of heap memory allocation in copy-assignment. =
I=20
> guess the expectation for std::variant would be that no such heap=20
> allocation takes place.
>
Boost.Variant provides the Never-Empty Guarantee without heap allocation, *
provided* that one of your types has a nothrow default constructor. In=20
which case, in the event of a copy failure, the variant will be assigned=20
one of those values.
I don't see the need to impose direct compiler support, just to provide a=
=20
no-heap guarantee for variants that can't otherwise get 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/?hl=3Den.
------=_Part_449_10270804.1366874010194
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
On Wednesday, April 24, 2013 11:18:31 PM UTC-7, Andrzej Krzemie=F1ski wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><blockquote class=3D"gmail_qu=
ote" 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>Axel Nauma=
nn is going to write one. I intend to help him with it. The realistic targe=
t is C++17,<br></div><div>the door on C++14 is closed. <br></div></div></di=
v></div></blockquote><div><br>Perhaps it is too early, but I can't help bri=
nging this up already. It looks to me that std::variant will require some c=
ompiler magic support in order to provide the <a href=3D"http://www.boost.o=
rg/doc/libs/1_53_0/doc/html/variant/design.html#variant.design.never-empty"=
target=3D"_blank">Never-Empty gurantee</a>. It is essential part of varian=
t, but difficult to achieve. Boost.Variant provides it at the expense of he=
ap memory allocation in copy-assignment. I guess the expectation for std::v=
ariant would be that no such heap allocation takes place.<br></div></blockq=
uote><div><br>Boost.Variant provides the Never-Empty Guarantee without heap=
allocation, <i>provided</i> that one of your types has a nothrow default c=
onstructor. In which case, in the event of a copy failure, the variant will=
be assigned one of those values.<br><br>I don't see the need to impose dir=
ect compiler support, just to provide a no-heap guarantee for variants that=
can't otherwise get 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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_449_10270804.1366874010194--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Apr 2013 09:22:22 -0500
Raw View
--047d7bd6c2e4fce49e04db30274d
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On 25 April 2013 01:18, Andrzej Krzemie=C5=84ski <akrzemi1@gmail.com> wrote=
:
>
> Perhaps it is too early, but I can't help bringing this up already. It
> looks to me that std::variant will require some compiler magic support in
> order to provide the Never-Empty gurantee<http://www.boost.org/doc/libs/1=
_53_0/doc/html/variant/design.html#variant.design.never-empty>
> .
>
What magic support would that be? I'm not seeing it (but it's still early
in the morning :-)).
--=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/?hl=3Den.
--047d7bd6c2e4fce49e04db30274d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On 25 April 2013 01:18, Andrzej Krzemie=C5=84ski <span dir=3D"ltr"><<a h=
ref=3D"mailto:akrzemi1@gmail.com" target=3D"_blank">akrzemi1@gmail.com</a>&=
gt;</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:1=
ex">
<br><div>Perhaps it is too early, but I can't help bringing this up alr=
eady. It looks to me that std::variant will require some compiler magic sup=
port in order to provide the <a href=3D"http://www.boost.org/doc/libs/1_53_=
0/doc/html/variant/design.html#variant.design.never-empty" target=3D"_blank=
">Never-Empty gurantee</a>.</div>
</blockquote><div><br>What magic support would that be?=C2=A0 I'm not s=
eeing it (but it's still early in the morning :-)).<br></div></div>-- <=
br>=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nev=
in@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0=
(847) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--047d7bd6c2e4fce49e04db30274d--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Apr 2013 09:37:09 -0500
Raw View
--e89a8f64748ff26e3904db305cae
Content-Type: text/plain; charset=ISO-8859-1
On 25 April 2013 02:13, Nicol Bolas <jmckesson@gmail.com> wrote:
>
> Boost.Variant provides the Never-Empty Guarantee without heap allocation,
> *provided* that one of your types has a nothrow default constructor. In
> which case, in the event of a copy failure, the variant will be assigned
> one of those values.
>
Sure, and we wouldn't preclude that optimization. However, if you want
that for a type that has a non-throwing default constructor marked
noexcept(false) (such as, for instance, a typical implementation of
std::vector), you will need magic compiler support.
> I don't see the need to impose direct compiler support, just to provide a
> no-heap guarantee for variants that can't otherwise get one.
>
Note: a heap allocation is not the only way to get this guarantee. One
could have a variant that has room for two copies of the largest object
type, and an implementation may want to make a tradeoff between doing this
and doing a heap allocation, depending on the size.
--
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/?hl=en.
--e89a8f64748ff26e3904db305cae
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 25 April 2013 02:13, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto=
:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> =
wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br><div>Boost.Variant provides the Never-Empty Guarantee without heap allo=
cation, <i>provided</i> that one of your types has a nothrow default constr=
uctor. In which case, in the event of a copy failure, the variant will be a=
ssigned one of those values.<br>
</div></blockquote><div><br>Sure, and we wouldn't preclude that optimiz=
ation.=A0 However, if you want that for a type that has a non-throwing defa=
ult constructor marked noexcept(false) (such as, for instance, a typical im=
plementation of std::vector), you will need magic compiler support.<br>
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div>I don't see the need to im=
pose direct compiler support, just to provide a no-heap guarantee for varia=
nts that can't otherwise get one.<br>
</div></blockquote></div><br clear=3D"all">Note:=A0 a heap allocation is no=
t the only way to get this guarantee.=A0 One could have a variant that has =
room for two copies of the largest object type, and an implementation may w=
ant to make a tradeoff between doing this and doing a heap allocation, depe=
nding on the size.<br>
-- <br>=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto:nevin=
@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=A0 (847=
) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--e89a8f64748ff26e3904db305cae--
.
Author: =?UTF-8?Q?Andrzej_Krzemie=C5=84ski?= <akrzemi1@gmail.com>
Date: Thu, 25 Apr 2013 08:25:19 -0700 (PDT)
Raw View
------=_Part_1071_5191718.1366903519496
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
W dniu czwartek, 25 kwietnia 2013 16:22:22 UTC+2 u=BFytkownik Nevin ":-)"=
=20
Liber napisa=B3:
>
> On 25 April 2013 01:18, Andrzej Krzemie=F1ski <akrz...@gmail.com<javascri=
pt:>
> > wrote:
>
>>
>> Perhaps it is too early, but I can't help bringing this up already. It=
=20
>> looks to me that std::variant will require some compiler magic support i=
n=20
>> order to provide the Never-Empty gurantee<http://www.boost.org/doc/libs/=
1_53_0/doc/html/variant/design.html#variant.design.never-empty>
>> .
>>
>
> What magic support would that be? I'm not seeing it (but it's still earl=
y=20
> in the morning :-)).
>
The original implementation in Boost used tricks to implement it without=20
the necessity of free store or double storage. It used memcpy to move the=
=20
stack-allocated part of the object around. It is described in short in the=
=20
docs=20
http://www.boost.org/doc/libs/1_53_0/doc/html/variant/design.html#variant.d=
esign.never-empty.memcpy-solution.:=20
"move the bits for an existing object into a buffer so we can tentatively=
=20
construct a new object in that memory, and later move the old bits back=20
temporarily to destroy the old object" While it did work on certain=20
compilers, it was exploiting a UB.=20
But since it did work on some compilers, this makes me believe that it is=
=20
implementable at least on certain compilers (UB in the standard may be a=20
well defined behaviour on a particular platform). Every vendor could=20
exploit their own tricks inside the implementation.
Sorry if my reply is vague. I only read about this implementation in Boost=
=20
archives, and never explored it myself.
Regards,
&rzej
--=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/?hl=3Den.
------=_Part_1071_5191718.1366903519496
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
<br><br>W dniu czwartek, 25 kwietnia 2013 16:22:22 UTC+2 u=BFytkownik Nevin=
":-)" Liber napisa=B3:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 25 A=
pril 2013 01:18, Andrzej Krzemie=F1ski <span dir=3D"ltr"><<a href=3D"jav=
ascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"DovpLfnW1eQJ">akrz...@=
gmail.com</a>></span> wrote:<br><div class=3D"gmail_quote"><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex">
<br><div>Perhaps it is too early, but I can't help bringing this up already=
.. It looks to me that std::variant will require some compiler magic support=
in order to provide the <a href=3D"http://www.boost.org/doc/libs/1_53_0/do=
c/html/variant/design.html#variant.design.never-empty" target=3D"_blank">Ne=
ver-Empty gurantee</a>.</div>
</blockquote><div><br>What magic support would that be? I'm not seein=
g it (but it's still early in the morning :-)).<br></div></div></blockquote=
><div><br>The original implementation in Boost used tricks to implement it =
without the necessity of free store or double storage. It used memcpy to mo=
ve the stack-allocated part of the object around. It is described in short =
in the docs <a href=3D"http://www.boost.org/doc/libs/1_53_0/doc/html/varian=
t/design.html#variant.design.never-empty.memcpy-solution">http://www.boost.=
org/doc/libs/1_53_0/doc/html/variant/design.html#variant.design.never-empty=
..memcpy-solution</a>.: "move the bits for an existing object
into a buffer so we can tentatively construct a new object in
that memory, and later move the old bits back temporarily to
destroy the old object" While it did work on certain compilers,=
it was exploiting a UB. <br><br>But since it did work on some compilers, t=
his makes me believe that it is implementable at least on certain compilers=
(UB in the standard may be a well defined behaviour on a particular platfo=
rm). Every vendor could exploit their own tricks inside the implementation.=
<br><br>Sorry if my reply is vague. I only read about this implementation i=
n Boost archives, and never explored it myself.<br><br>Regards,<br>&rze=
j<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_1071_5191718.1366903519496--
.
Author: Fernando Cacciola <fernando.cacciola@gmail.com>
Date: Thu, 25 Apr 2013 12:36:36 -0300
Raw View
--047d7b344168709f7f04db3131cd
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thu, Apr 25, 2013 at 12:25 PM, Andrzej Krzemie=C5=84ski <akrzemi1@gmail.=
com>wrote:
> But since it did work on some compilers, this makes me believe that it is
> implementable at least on certain compilers (UB in the standard may be a
> well defined behaviour on a particular platform). Every vendor could
> exploit their own tricks inside the implementation.
>
>
I'm almost positive that I seem to recall that, when this was being added
to Boost, we regarded the trick as unspecified instead of UB
At the very least, I can't off the top of my head think of a reason for
this trick (copy to a different storage then restore it) be anything but
unspecified.
And even if it is currently UB, it might be reasonable to change that,
similarly to what we did for aligned_storage (which before being added to
the std, all actual implementations exploited UB)
Best
--=20
Fernando Cacciola
SciSoft Consulting, Founder
http://www.scisoft-consulting.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/?hl=3Den.
--047d7b344168709f7f04db3131cd
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, Apr 25, 2013 at 12:25 PM, Andrzej Krzemie=C5=84ski <span dir=3D"ltr">&l=
t;<a href=3D"mailto:akrzemi1@gmail.com" target=3D"_blank">akrzemi1@gmail.co=
m</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div>But since it did work on some compilers=
, this makes me believe that it is implementable at least on certain compil=
ers (UB in the standard may be a well defined behaviour on a particular pla=
tform). Every vendor could exploit their own tricks inside the implementati=
on.<br>
<br></div></blockquote><div>=C2=A0<br></div><div>I'm almost positive th=
at I seem to recall that, when this was being added to Boost, we regarded t=
he trick as unspecified instead of UB<br><br></div><div>At the very least, =
I can't off the top of my head think of a reason for this trick (copy t=
o a different storage then restore it) be anything but unspecified.<br>
<br>And even if it is currently UB, it might be reasonable to change that, =
similarly to what we did for aligned_storage (which before being added to t=
he std, all actual implementations exploited UB)<br><br></div><div>Best<br>
</div></div><br>-- <br>Fernando Cacciola<br>SciSoft Consulting, Founder<br>=
<a href=3D"http://www.scisoft-consulting.com">http://www.scisoft-consulting=
..com</a>
</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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--047d7b344168709f7f04db3131cd--
.
Author: Jonathan Wakely <cxx@kayari.org>
Date: Thu, 25 Apr 2013 09:57:59 -0700 (PDT)
Raw View
------=_Part_545_17286470.1366909079997
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, April 25, 2013 4:36:36 PM UTC+1, Fernando Cacciola wrote:
>
> On Thu, Apr 25, 2013 at 12:25 PM, Andrzej Krzemie=C5=84ski <akrz...@gmail=
..com<javascript:>
> > wrote:
>
>> But since it did work on some compilers, this makes me believe that it i=
s=20
>> implementable at least on certain compilers (UB in the standard may be a=
=20
>> well defined behaviour on a particular platform). Every vendor could=20
>> exploit their own tricks inside the implementation.
>>
>> =20
> I'm almost positive that I seem to recall that, when this was being added=
=20
> to Boost, we regarded the trick as unspecified instead of UB
>
[basic.types]/2 says it works for trivially copyable types, which implies=
=20
it doesn't otherwise, or it wouldn't need saying.
=20
> At the very least, I can't off the top of my head think of a reason for=
=20
> this trick (copy to a different storage then restore it) be anything but=
=20
> unspecified.
>
>
If an object has a non-trivial destructor you cannot reuse its storage=20
without running the destructor.
What if the object to be replaced had started a new thread which sets a=20
timer and calls a member function on the object if it hasn't been destroyed=
=20
yet. Since you haven't run its destructor (just moved its bytes to new=20
storage) the other thread will do the callback, but might find garbage=20
where it expects to find the object.
=20
> And even if it is currently UB, it might be reasonable to change that,=20
> similarly to what we did for aligned_storage (which before being added to=
=20
> the std, all actual implementations exploited UB)
>
Why was it UB?
--=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/?hl=3Den.
------=_Part_545_17286470.1366909079997
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Thursday, April 25, 2013 4:36:36 PM UTC+1, Fernando Cacciola wro=
te:<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, Apr 25, 2013 at 12:25 PM, Andrzej Krzemie=C5=
=84ski <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"lGubHydTGv8J">akrz...@gmail.com</a>></span> wrote:<=
br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div>But since it did work on some compilers=
, this makes me believe that it is implementable at least on certain compil=
ers (UB in the standard may be a well defined behaviour on a particular pla=
tform). Every vendor could exploit their own tricks inside the implementati=
on.<br>
<br></div></blockquote><div> <br></div><div>I'm almost positive that I=
seem to recall that, when this was being added to Boost, we regarded the t=
rick as unspecified instead of UB<br></div></div></div></div></blockquote><=
div><br>[basic.types]/2 says it works for trivially copyable types, which i=
mplies it doesn't otherwise, or it wouldn't need saying.<br><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 dir=3D"ltr"><div><div cl=
ass=3D"gmail_quote"><div></div><div>At the very least, I can't off the top =
of my head think of a reason for this trick (copy to a different storage th=
en restore it) be anything but unspecified.<br>
<br></div></div></div></div></blockquote><div><br>If an object has a non-tr=
ivial destructor you cannot reuse its storage without running the destructo=
r.<br><br>What if the object to be replaced had started a new thread which =
sets a timer and calls a member function on the object if it hasn't been de=
stroyed yet. Since you haven't run its destructor (just moved its bytes to =
new storage) the other thread will do the callback, but might find garbage =
where it expects to find the object.<br><br><br><br> </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>And even if it is currently UB, it might be reasonable to chan=
ge that, similarly to what we did for aligned_storage (which before being a=
dded to the std, all actual implementations exploited UB)<br></div></div></=
div></div></blockquote><div><br>Why was it UB?<br><br><br></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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_545_17286470.1366909079997--
.
Author: DeadMG <wolfeinstein@gmail.com>
Date: Thu, 25 Apr 2013 13:13:51 -0700 (PDT)
Raw View
------=_Part_145_7572530.1366920831382
Content-Type: text/plain; charset=ISO-8859-1
I can't help but feel that this won't be necessary for a C++11 Variant.
Surely, you could implement the copy assignment operator in terms of copy
and swap, like normal. Since swap can now be guaranteed noexcept with move
semantics, it seems to me like this should be a fine implementation
strategy for strongly exception safe no double storage no heap allocation
copy assignment.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_145_7572530.1366920831382
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
I can't help but feel that this won't be necessary for a C++11 Variant. Sur=
ely, you could implement the copy assignment operator in terms of copy and =
swap, like normal. Since swap can now be guaranteed noexcept with move sema=
ntics, it seems to me like this should be a fine implementation strategy fo=
r strongly exception safe no double storage no heap allocation copy assignm=
ent.
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_145_7572530.1366920831382--
.
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Thu, 25 Apr 2013 22:18:19 +0200
Raw View
2013/4/25 DeadMG <wolfeinstein@gmail.com>:
> I can't help but feel that this won't be necessary for a C++11 Variant.
> Surely, you could implement the copy assignment operator in terms of copy
> and swap, like normal. Since swap can now be guaranteed noexcept with move
> semantics, it seems to me like this should be a fine implementation strategy
> for strongly exception safe no double storage no heap allocation copy
> assignment.
Why should swap guarantee noexcept? Not every type has move operations
(it will copy instead), not every move operation is noexcept (The
library supports throwing move operations but gives up the strong
exception safety).
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Apr 2013 15:27:49 -0500
Raw View
--20cf30050e94f50fb604db3542fa
Content-Type: text/plain; charset=ISO-8859-1
On 25 April 2013 15:13, DeadMG <wolfeinstein@gmail.com> wrote:
> Surely, you could implement the copy assignment operator in terms of copy
> and swap, like normal.
Could you? There aren't any "internals" to swap (it's value based, not
pointer based), so wouldn't this just be a pessimization?
> Since swap can now be guaranteed noexcept with move semantics,
Huh? Where does this come from? Unless the move constructor/move
assignment are marked noexcept, this isn't true.
> it seems to me like this should be a fine implementation strategy for
> strongly exception safe no double storage no heap allocation copy
> assignment.
I don't see how you can avoid it if you want never-empty for arbitrary
types.
--
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/?hl=en.
--20cf30050e94f50fb604db3542fa
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 25 April 2013 15:13, DeadMG <span dir=3D"ltr"><<a href=3D"mailto:wolf=
einstein@gmail.com" target=3D"_blank">wolfeinstein@gmail.com</a>></span>=
wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Surely, you could implement the copy assignment operator in terms of copy a=
nd swap, like normal.</blockquote><div><br></div><div>Could you? =A0There a=
ren't any "internals" to swap (it's value based, not poin=
ter based), so wouldn't this just be a pessimization?</div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"> Since swap can now be guarant=
eed noexcept with move semantics, </blockquote><div><br></div><div>Huh? =A0=
Where does this come from? =A0Unless the move constructor/move assignment a=
re marked noexcept, this isn't true.</div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex">it seems to me like this shoul=
d be a fine implementation strategy for strongly exception safe no double s=
torage no heap allocation copy assignment.</blockquote>
<div><br></div><div>I don't see how you can avoid it if you want never-=
empty for arbitrary types.</div><div>--=A0</div></div>=A0Nevin ":-)&qu=
ot; Liber=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D=
"_blank">nevin@eviloverlord.com</a>>=A0 (847) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--20cf30050e94f50fb604db3542fa--
.
Author: DeadMG <wolfeinstein@gmail.com>
Date: Thu, 25 Apr 2013 13:28:42 -0700 (PDT)
Raw View
------=_Part_758_3946507.1366921722208
Content-Type: text/plain; charset=ISO-8859-1
Frankly, I think that requiring nothrow move would be a superior option. It
considerably simplifies the implementation, improves performance, and does
not have the requirement of needing a nothrow default constructible type to
put in the variant in case of failure. In my opinion, losing the strong
exception safety guarantee is something we should only do if we have
absolutely no other choice. In this case, we do have a 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/?hl=en.
------=_Part_758_3946507.1366921722208
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Frankly, I think that requiring nothrow move would be a superior option. It=
considerably simplifies the implementation, improves performance, and does=
not have the requirement of needing a nothrow default constructible type t=
o put in the variant in case of failure. In my opinion, losing the strong e=
xception safety guarantee is something we should only do if we have absolut=
ely no other choice. In this case, we do have a choice.
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_758_3946507.1366921722208--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Apr 2013 15:40:12 -0500
Raw View
--e89a8f6471cb3d275304db356f68
Content-Type: text/plain; charset=ISO-8859-1
On 25 April 2013 15:28, DeadMG <wolfeinstein@gmail.com> wrote:
> Frankly, I think that requiring nothrow move would be a superior option.
> It considerably simplifies the implementation, improves performance, and
> does not have the requirement of needing a nothrow default constructible
> type to put in the variant in case of failure.
>
You've just swapped one unreasonable (IMO) requirement on the type for
another. You couldn't, for instance, store most of the standard containers
in your variant. I would vote strongly against this.
In my opinion, losing the strong exception safety guarantee is something we
> should only do if we have absolutely no other choice. In this case, we do
> have a choice.
>
Requiring no-throw move constructors for various standard library
components has been tried before. It didn't work.
--
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/?hl=en.
--e89a8f6471cb3d275304db356f68
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div class=3D"gmail_quote">On 25 April 2013 15:28, DeadMG <span dir=3D"ltr"=
><<a href=3D"mailto:wolfeinstein@gmail.com" target=3D"_blank">wolfeinste=
in@gmail.com</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 id=3D":2ho">Frankly, I think that requiring nothrow move would be a su=
perior option. It considerably simplifies the implementation, improves perf=
ormance, and does not have the requirement of needing a nothrow default con=
structible type to put in the variant in case of failure.</div>
</blockquote><div><br></div><div>You've just swapped one unreasonable (=
IMO) requirement on the type for another. =A0You couldn't, for instance=
, store most of the standard containers in your variant. =A0I would vote st=
rongly against this.</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 id=3D":2ho"> In my opini=
on, losing the strong exception safety guarantee is something we should onl=
y do if we have absolutely no other choice. In this case, we do have a choi=
ce.</div>
</blockquote><div><br></div><div>=A0Requiring no-throw move constructors fo=
r various standard library components has been tried before. =A0It didn'=
;t work.</div></div>-- <br>=A0Nevin ":-)" Liber=A0 <mailto:<a =
href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord=
..com</a>>=A0 (847) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--e89a8f6471cb3d275304db356f68--
.
Author: Jeffrey Yasskin <jyasskin@google.com>
Date: Thu, 25 Apr 2013 13:46:13 -0700
Raw View
On Thu, Apr 25, 2013 at 7:37 AM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 25 April 2013 02:13, Nicol Bolas <jmckesson@gmail.com> wrote:
>>
>>
>> Boost.Variant provides the Never-Empty Guarantee without heap allocation,
>> provided that one of your types has a nothrow default constructor. In which
>> case, in the event of a copy failure, the variant will be assigned one of
>> those values.
>
>
> Sure, and we wouldn't preclude that optimization. However, if you want that
> for a type that has a non-throwing default constructor marked
> noexcept(false) (such as, for instance, a typical implementation of
> std::vector), you will need magic compiler support.
>
>>
>> I don't see the need to impose direct compiler support, just to provide a
>> no-heap guarantee for variants that can't otherwise get one.
>
>
> Note: a heap allocation is not the only way to get this guarantee. One
> could have a variant that has room for two copies of the largest object
> type, and an implementation may want to make a tradeoff between doing this
> and doing a heap allocation, depending on the size.
The implementation can distinguish a couple cases then:
a) At least one member of the variant has a noexcept(true) default constructor.
b) At most one member of the variant has a noexcept(false) move constructor.
c) The variant is either twice the size or allocates on some assignments.
Right? (b) is new with C++11, and the proposal should definitely
include it. Maybe we can get the allocator crowd not to insist on
allocators by telling them to fit in (a) or (b) if they want to
control allocation. I don't have a good feeling for whether
std::variant should forbid (c) entirely, or allow it with
allocation-or-double-memory.
To forbid (c), we'd probably have to give the standard containers
noexcept move constructors. ... Are they missing the noexcept today
because of allocators?
Jeffrey
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
.
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Thu, 25 Apr 2013 22:55:54 +0200
Raw View
2013/4/25 Jeffrey Yasskin <jyasskin@google.com>:
> On Thu, Apr 25, 2013 at 7:37 AM, Nevin Liber <nevin@eviloverlord.com> wrote:
>> On 25 April 2013 02:13, Nicol Bolas <jmckesson@gmail.com> wrote:
> To forbid (c), we'd probably have to give the standard containers
> noexcept move constructors. ... Are they missing the noexcept today
> because of allocators?
No, I don't think so. We require that the move construction of
allocators is no-throw. I believe the reason here is the same as we
have for not having guaranteed no-throw container default
constructors, because implementations might need to allocate memory
for internal purposes that could fail.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
.
Author: DeadMG <wolfeinstein@gmail.com>
Date: Thu, 25 Apr 2013 14:04:04 -0700 (PDT)
Raw View
------=_Part_196_13067631.1366923844370
Content-Type: text/plain; charset=ISO-8859-1
Then the real problem here is the lack of support for noexcept allocators.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_196_13067631.1366923844370
Content-Type: text/html; charset=ISO-8859-1
Then the real problem here is the lack of support for noexcept allocators.
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
<br />
<br />
------=_Part_196_13067631.1366923844370--
.
Author: Fernando Cacciola <fernando.cacciola@gmail.com>
Date: Thu, 25 Apr 2013 18:09:45 -0300
Raw View
--089e01494226ed3bb304db35d8ad
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thu, Apr 25, 2013 at 1:57 PM, Jonathan Wakely <cxx@kayari.org> wrote:
>
>
> On Thursday, April 25, 2013 4:36:36 PM UTC+1, Fernando Cacciola wrote:
>
>> On Thu, Apr 25, 2013 at 12:25 PM, Andrzej Krzemie=C5=84ski <akrz...@gmai=
l.com>wrote:
>>
>>> But since it did work on some compilers, this makes me believe that it
>>> is implementable at least on certain compilers (UB in the standard may =
be a
>>> well defined behaviour on a particular platform). Every vendor could
>>> exploit their own tricks inside the implementation.
>>>
>>>
>> I'm almost positive that I seem to recall that, when this was being adde=
d
>> to Boost, we regarded the trick as unspecified instead of UB
>>
>
> [basic.types]/2 says it works for trivially copyable types, which implies
> it doesn't otherwise, or it wouldn't need saying.
>
> Good point.
>
>
>> At the very least, I can't off the top of my head think of a reason for
>> this trick (copy to a different storage then restore it) be anything but
>> unspecified.
>>
>>
> If an object has a non-trivial destructor you cannot reuse its storage
> without running the destructor.
>
> Right, I would have replied than in this case you are giving it the
storage back, but...
What if the object to be replaced had started a new thread which sets a
> timer and calls a member function on the object if it hasn't been destroy=
ed
> yet. Since you haven't run its destructor (just moved its bytes to new
> storage) the other thread will do the callback, but might find garbage
> where it expects to find the object.
>
> This is quite valid, even if odd and unlikely, so that settles it.
>
>
>> And even if it is currently UB, it might be reasonable to change that,
>> similarly to what we did for aligned_storage (which before being added t=
o
>> the std, all actual implementations exploited UB)
>>
>
> Why was it UB?
>
> I've been trying to remember but I can't. And there is alignment_of plus
type_with_alignment in the bag, so I might be confusing them.
Best
--=20
Fernando Cacciola
SciSoft Consulting, Founder
http://www.scisoft-consulting.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/?hl=3Den.
--089e01494226ed3bb304db35d8ad
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, Apr 25, 2013 at 1:57 PM, Jonathan Wakely <span dir=3D"ltr"><<a href=
=3D"mailto:cxx@kayari.org" target=3D"_blank">cxx@kayari.org</a>></span> =
wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><br><br>On Thursday, April 25, 2013 4:36:36 =
PM UTC+1, Fernando Cacciola wrote:<div class=3D"im"><blockquote class=3D"gm=
ail_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">On Thu, Apr 25, 2013 at 12=
:25 PM, Andrzej Krzemie=C5=84ski <span dir=3D"ltr"><<a>akrz...@gmail.com=
</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div>But since it did work on some compilers=
, this makes me believe that it is implementable at least on certain compil=
ers (UB in the standard may be a well defined behaviour on a particular pla=
tform). Every vendor could exploit their own tricks inside the implementati=
on.<br>
<br></div></blockquote><div>=C2=A0<br></div><div>I'm almost positive th=
at I seem to recall that, when this was being added to Boost, we regarded t=
he trick as unspecified instead of UB<br></div></div></div></div></blockquo=
te>
</div><div><br>[basic.types]/2 says it works for trivially copyable types, =
which implies it doesn't otherwise, or it wouldn't need saying.<br>=
<br></div></blockquote><div>Good point.<br>=C2=A0<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>=C2=A0</div><div class=3D"im"><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>At the ve=
ry least, I can't off the top of my head think of a reason for this tri=
ck (copy to a different storage then restore it) be anything but unspecifie=
d.<br>
<br></div></div></div></div></blockquote></div><div><br>If an object has a =
non-trivial destructor you cannot reuse its storage without running the des=
tructor.<br><br></div></blockquote><div>Right, I would have replied than in=
this case you are giving it the storage back, but...<br>
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div>What if the object to be repl=
aced had started a new thread which sets a timer and calls a member functio=
n on the object if it hasn't been destroyed yet. Since you haven't =
run its destructor (just moved its bytes to new storage) the other thread w=
ill do the callback, but might find garbage where it expects to find the ob=
ject.<br>
<br></div></blockquote><div>This is quite valid, even if odd and unlikely, =
so that settles it.<br><br></div><blockquote class=3D"gmail_quote" style=3D=
"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><br>=
=C2=A0</div>
<div class=3D"im"><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"><div>And even if it is currently UB, it mig=
ht be reasonable to change that, similarly to what we did for aligned_stora=
ge (which before being added to the std, all actual implementations exploit=
ed UB)<br>
</div></div></div></div></blockquote></div><div><br>Why was it UB?<br><br><=
/div></blockquote><div>I've been trying to remember but I can't. An=
d there is alignment_of plus type_with_alignment in the bag, so I might be =
confusing them.<br>
</div></div><br></div><div class=3D"gmail_extra">Best<br clear=3D"all"></di=
v><div class=3D"gmail_extra"><br>-- <br>Fernando Cacciola<br>SciSoft Consul=
ting, Founder<br><a href=3D"http://www.scisoft-consulting.com">http://www.s=
cisoft-consulting.com</a>
</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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--089e01494226ed3bb304db35d8ad--
.
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Thu, 25 Apr 2013 23:10:33 +0200
Raw View
2013/4/25 DeadMG <wolfeinstein@gmail.com>:
> Then the real problem here is the lack of support for noexcept allocators.
I assume you mean kind-of-nothrow_t allocate overload in allocators?
This should not be the actual problem, since an implementation could
easily realize the same thing by *attempting* to call Alloc::allocate
within a try/catch block. Essentially the default operator new
overload with std::nothrow_t argument behaves in the same way: It
tries to call the potentially throwing operator new and returns null,
if that throws an exception. The actual problem is that some
implementations *need* this storage and could not be created if that
memory would not exist.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
.
Author: DeadMG <wolfeinstein@gmail.com>
Date: Thu, 25 Apr 2013 14:12:24 -0700 (PDT)
Raw View
------=_Part_1054_23504864.1366924344089
Content-Type: text/plain; charset=ISO-8859-1
No, I mean "If allocation fails, std::terminate()".
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_1054_23504864.1366924344089
Content-Type: text/html; charset=ISO-8859-1
No, I mean "If allocation fails, std::terminate()".
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
<br />
<br />
------=_Part_1054_23504864.1366924344089--
.
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Thu, 25 Apr 2013 23:20:50 +0200
Raw View
2013/4/25 DeadMG <wolfeinstein@gmail.com>:
> No, I mean "If allocation fails, std::terminate()".
A drastic solution IMO. I would prefer that implementations would
instead provide the nothrow-guarantee for default-construction of
potentially zero-capacity containers.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
.
Author: DeadMG <wolfeinstein@gmail.com>
Date: Thu, 25 Apr 2013 14:26:59 -0700 (PDT)
Raw View
------=_Part_1083_11853004.1366925219911
Content-Type: text/plain; charset=ISO-8859-1
I feel that it's the best solution, since the situation that many
applications are in is that if they exhaust memory, then this effectively
will only occur due to a memory leak. An exception is of little use.
Let me put it another way. In my program, then there is no way I am going
to exhaust my 2GB virtual memory limit. But you're saying that I have to
pay the price of no strong exception guarantee and having to screw around
with default constructible types, because *some other program* would prefer
to have an exception on memory allocation failure. This is fundamentally
against the C++ philosophy IYAM, but more importantly, plain unnecessary-
we have a perfectly good tool to solve this problem and there's no reason
not to use it if possible. Let those programs who want memory allocation
failures to be exceptions cope with the problem of exception safety when
memory allocation might throw.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_1083_11853004.1366925219911
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
I feel that it's the best solution, since the situation that many applicati=
ons are in is that if they exhaust memory, then this effectively will only =
occur due to a memory leak. An exception is of little use.<div><br></div><d=
iv>Let me put it another way. In my program, then there is no way I am goin=
g to exhaust my 2GB virtual memory limit. But you're saying that I have to =
pay the price of no strong exception guarantee and having to screw around w=
ith default constructible types, because *some other program* would prefer =
to have an exception on memory allocation failure. This is fundamentally ag=
ainst the C++ philosophy IYAM, but more importantly, plain unnecessary- we =
have a perfectly good tool to solve this problem and there's no reason not =
to use it if possible. Let those programs who want memory allocation failur=
es to be exceptions cope with the problem of exception safety when memory a=
llocation might throw.</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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_1083_11853004.1366925219911--
.
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Thu, 25 Apr 2013 23:34:45 +0200
Raw View
2013/4/25 DeadMG <wolfeinstein@gmail.com>:
> I feel that it's the best solution, since the situation that many
> applications are in is that if they exhaust memory, then this effectively
> will only occur due to a memory leak. An exception is of little use.
>
> Let me put it another way. In my program, then there is no way I am going to
> exhaust my 2GB virtual memory limit. But you're saying that I have to pay
> the price of no strong exception guarantee and having to screw around with
> default constructible types, because *some other program* would prefer to
> have an exception on memory allocation failure. This is fundamentally
> against the C++ philosophy IYAM, but more importantly, plain unnecessary- we
> have a perfectly good tool to solve this problem and there's no reason not
> to use it if possible. Let those programs who want memory allocation
> failures to be exceptions cope with the problem of exception safety when
> memory allocation might throw.
What you are describing here sounds to me like the moral equivalent of
an enforced new-handler that calls std::terminate. If you prefer it
that way, install such a beast, but this is an optional decision and
not what everyone likes to have.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
.
Author: DeadMG <wolfeinstein@gmail.com>
Date: Thu, 25 Apr 2013 14:36:23 -0700 (PDT)
Raw View
------=_Part_1100_19736225.1366925783390
Content-Type: text/plain; charset=ISO-8859-1
I'm not saying it should be enforced. I'm saying that *if* I install an
allocator (not a new-handler since that cannot influence exception
guarantees) which behaves this way, then the Standard should specify the
noexcepts to take advantage of 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/?hl=en.
------=_Part_1100_19736225.1366925783390
Content-Type: text/html; charset=ISO-8859-1
I'm not saying it should be enforced. I'm saying that *if* I install an allocator (not a new-handler since that cannot influence exception guarantees) which behaves this way, then the Standard should specify the noexcepts to take advantage of this.
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
<br />
<br />
------=_Part_1100_19736225.1366925783390--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Apr 2013 16:36:50 -0500
Raw View
--20cf30050e94ca273f04db3639a3
Content-Type: text/plain; charset=ISO-8859-1
On 25 April 2013 15:46, Jeffrey Yasskin <jyasskin@google.com> wrote:
> The implementation can distinguish a couple cases then:
>
> a) At least one member of the variant has a noexcept(true) default
> constructor.
> b) At most one member of the variant has a noexcept(false) move
> constructor.
> c) The variant is either twice the size or allocates on some assignments.
>
You can also do some optimizations if you have a nonexcept copy constructor
when you are doing copy assignment.
> I don't have a good feeling for whether
std::variant should forbid (c) entirely, or allow it with
> allocation-or-double-memory.
>
That is, of course, the crux of the never-empty vs. at-most-one guarantee.
:-)
>
> To forbid (c), we'd probably have to give the standard containers
> noexcept move constructors.
That is probably a non-starter.
--
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/?hl=en.
--20cf30050e94ca273f04db3639a3
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 25 April 2013 15:46, Jeffrey Yasskin <span dir=3D"ltr"><<a href=3D"ma=
ilto:jyasskin@google.com" target=3D"_blank">jyasskin@google.com</a>></sp=
an> 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 class=3D"HOEnZb"><div class=3D"h5">The implementation can distinguish =
a couple cases then:</div></div>
<br>
a) At least one member of the variant has a noexcept(true) default construc=
tor.<br>
b) At most one member of the variant has a noexcept(false) move constructor=
..<br>
c) The variant is either twice the size or allocates on some assignments.<b=
r></blockquote><div><br></div><div>You can also do some optimizations if yo=
u have a nonexcept copy constructor when you are doing copy assignment.=A0<=
/div>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex">=A0I don't have a good fee=
ling for whether</blockquote><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
std::variant should forbid (c) entirely, or allow it with<br>
allocation-or-double-memory.<br></blockquote><div><br></div><div><br></div>=
<div>That is, of course, the crux of the never-empty vs. at-most-one guaran=
tee. :-)</div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
To forbid (c), we'd probably have to give the standard containers<br>
noexcept move constructors. </blockquote><div><br></div><div>That is probab=
ly a non-starter.</div></div>-- <br>=A0Nevin ":-)" Liber=A0 <m=
ailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@evi=
loverlord.com</a>>=A0 (847) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--20cf30050e94ca273f04db3639a3--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Apr 2013 16:42:45 -0500
Raw View
--089e0149c752ea155104db364e49
Content-Type: text/plain; charset=ISO-8859-1
On 25 April 2013 16:36, DeadMG <wolfeinstein@gmail.com> wrote:
> I'm not saying it should be enforced. I'm saying that *if* I install an
> allocator (not a new-handler since that cannot influence exception
> guarantees) which behaves this way, then the Standard should specify the
> noexcepts to take advantage of this.
Then write a proposal (or at least start a new thread, since this has
nothing to do with the variant proposal).
--
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/?hl=en.
--089e0149c752ea155104db364e49
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 25 April 2013 16:36, DeadMG <span dir=3D"ltr"><<a href=3D"mailto:wolf=
einstein@gmail.com" target=3D"_blank">wolfeinstein@gmail.com</a>></span>=
wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I'm not saying it should be enforced. I'm saying that *if* I instal=
l an allocator (not a new-handler since that cannot influence exception gua=
rantees) which behaves this way, then the Standard should specify the noexc=
epts to take advantage of this.</blockquote>
<div><br></div><div>Then write a proposal (or at least start a new thread, =
since this has nothing to do with the variant proposal).</div><div>--=A0</d=
iv></div>=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto:nev=
in@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=A0 (8=
47) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--089e0149c752ea155104db364e49--
.
Author: DeadMG <wolfeinstein@gmail.com>
Date: Thu, 25 Apr 2013 14:44:04 -0700 (PDT)
Raw View
------=_Part_1015_10571654.1366926244263
Content-Type: text/plain; charset=ISO-8859-1
Yes, I have totally spammed the wrong thread. My apologies.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_1015_10571654.1366926244263
Content-Type: text/html; charset=ISO-8859-1
Yes, I have totally spammed the wrong thread. My apologies.
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
<br />
<br />
------=_Part_1015_10571654.1366926244263--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Apr 2013 17:00:16 -0500
Raw View
--047d7bb043ae8dccc104db368d89
Content-Type: text/plain; charset=ISO-8859-1
On 25 April 2013 16:36, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 25 April 2013 15:46, Jeffrey Yasskin <jyasskin@google.com> wrote:
>
>> The implementation can distinguish a couple cases then:
>>
>> a) At least one member of the variant has a noexcept(true) default
>> constructor.
>> b) At most one member of the variant has a noexcept(false) move
>> constructor.
>> c) The variant is either twice the size or allocates on some assignments.
>>
>
> You can also do some optimizations if you have a nonexcept copy
> constructor when you are doing copy assignment.
>
Here is what I am thinking:
Move assignment of distinct types:
If we have a noexcept move constructor or at least one noexcept default
constructor:
Destroy old object
Move construct new object
Otherwise
Move construct new object into alternate space
Destroy old object
Copy assignment of distinct types:
If we have a noexcept copy constructor or at least one noexcept default
constructor:
Destroy old object
Copy construct new object
Else if we have a noexcept(false) copy constructor, no noexcept default
constructors, and a noexcept move constructor:
Copy construct new object on the stack
Destroy old object
Move construct new object from the stack into the variant
Otherwise either do what Boost.Variant does OR:
Copy construct new object into alternate space
Destroy old object
I *think* that covers all the cases.
--
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/?hl=en.
--047d7bb043ae8dccc104db368d89
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 25 April 2013 16:36, Nevin Liber <span dir=3D"ltr"><<a href=3D"mailto=
:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.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 class=3D"im">On 25 April 2013 15:46, Jeffrey Yasskin <span dir=3D"ltr"=
><<a href=3D"mailto:jyasskin@google.com" target=3D"_blank">jyasskin@goog=
le.com</a>></span> wrote:<br></div><div class=3D"gmail_quote"><div class=
=3D"im">
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
<div><div>The implementation can distinguish a couple cases then:</div></di=
v>
<br>
a) At least one member of the variant has a noexcept(true) default construc=
tor.<br>
b) At most one member of the variant has a noexcept(false) move constructor=
..<br>
c) The variant is either twice the size or allocates on some assignments.<b=
r></blockquote><div><br></div></div><div>You can also do some optimizations=
if you have a nonexcept copy constructor when you are doing copy assignmen=
t.=A0</div>
</div></blockquote><div><br></div><div>Here is what I am thinking:</div><di=
v><br></div><div>Move assignment of distinct types:</div><div>=A0 =A0 If we=
have a noexcept move constructor or at least one noexcept default construc=
tor:</div>
<div>=A0 =A0 =A0 =A0 Destroy old object</div><div>=A0 =A0 =A0 =A0 Move cons=
truct new object</div><div>=A0 =A0 Otherwise</div><div>=A0 =A0 =A0 =A0 Move=
construct new object into alternate space</div><div>=A0 =A0 =A0 =A0 Destro=
y old object</div><div><br></div>
<div>Copy assignment of distinct types:</div><div>=A0 =A0 If we have a noex=
cept copy constructor or at least one noexcept default constructor:</div><d=
iv>=A0 =A0 =A0 =A0 Destroy old object</div><div>=A0 =A0 =A0 =A0 Copy constr=
uct new object</div>
<div>=A0 =A0 Else if we have a noexcept(false) copy constructor, no noexcep=
t default constructors, and a noexcept move constructor:</div><div>=A0 =A0 =
=A0 =A0 Copy construct new object on the stack</div><div>=A0 =A0 =A0 =A0 De=
stroy old object</div>
<div>=A0 =A0 =A0 =A0 Move construct new object from the stack into the vari=
ant</div><div>=A0 =A0 Otherwise either do what Boost.Variant does OR:</div>=
<div>=A0 =A0 =A0 =A0 Copy construct new object into alternate space</div><d=
iv>=A0 =A0 =A0 =A0 Destroy old object</div>
<div><br></div><div>I *think* that covers all the cases.</div><div>--=A0</d=
iv></div>=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto:nev=
in@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=A0 (8=
47) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--047d7bb043ae8dccc104db368d89--
.
Author: Alex B <devalexb@gmail.com>
Date: Mon, 29 Apr 2013 20:26:56 -0700 (PDT)
Raw View
------=_Part_5856_21050858.1367292416929
Content-Type: text/plain; charset=ISO-8859-1
Before trying to solve the never-empty guarantee problem, I think we should
examine the design of the variant class.
The design of boost::variant has the following particularity: "By default,
a variant default-constructs its first bounded type"
I never felt comfortable with that part of the design of boost::variant. It
always felt odd to me that the order of the bounded types matter. In my
opinion, a default constructed variant should not have one of its types
selected by default. In my personal implementation of a variant class,
there is what I call a "null" or "disengaged" or "no type" state. If we
think of a variant as being an index representing the selected type along
with an aligned storage large enough to hold any of the types of the
variant, there would be no extra cost of adding a null state. It could
simply be represented by a special index (let's say -1).
template <class... Types>
class variant
{
int selected_type; // value is an index among Types... or -1 if no
selected type
std::aligned_storage<MaxLen, MaxAlign> data;
...
There could be a *nullvar* value that would represent a variant with no
type selected (similar to *nullopt* that is part of the std::optional
proposal). For this and a few other things, the variant class would benefit
from having a design inspired in part by std::optional.
Why am I bringing this? Because if there is a null state, then the "never
empty" problem becomes much simpler. In fact, the problem could then be
called "never empty when not nullvar". The copy assignment of distinct
types could simply be:
- Destroy old object
- Set selected type as *nullvar* (could be omitted if copy constructor is
noexcept)
- Copy construct new object
- Set selected type as new type
If the copy constructor throws, the variant remains in a nullvar state,
which *is* a valid state.
So, do you think of any problem of having this nullvar state? Maybe there
was a reason for not including one in boost::variant but I can't see one
apart from being a design 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/?hl=en.
------=_Part_5856_21050858.1367292416929
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;">Before trying to solve the never-empty guarantee problem, I think w=
e
should examine the design of the variant class.<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;"><o:p> </o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;">The design of boost::variant has the following particularity: "</sp=
an><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">By default=
,
a </span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: '=
Courier New'; color: black; border: 1pt none windowtext; padding: 0cm;">var=
iant</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Aria=
l, sans-serif; color: black; border: 1pt none windowtext; padding: 0cm;">&n=
bsp;default-constructs
its first bounded type"</span><span lang=3D"EN-CA" style=3D"font-size: 10pt=
; font-family: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;"><o:p> </o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">I never fe=
lt
comfortable with that part of the design of boost::variant. It always felt =
odd
to me that the order of the bounded types matter. In my opinion, a default
constructed variant should not have one of its types selected by default. I=
n my
personal implementation of a variant class, there is what I call a
"null" or "disengaged" or "no type" state. If we
think of a variant as being an index representing the selected type along w=
ith
an aligned storage large enough to hold any of the types of the variant, th=
ere
would be no extra cost of adding a null state. It could simply be represent=
ed
by a special index (let's say -1).</span><span lang=3D"EN-CA" style=3D"font=
-size: 10pt; font-family: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;"><o:p> </o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin: 0cm 0cm 0.0001pt 35.4pt; line-heigh=
t: normal; background-position: initial initial; background-repeat: initial=
initial;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Aria=
l, sans-serif; color: black; border: 1pt none windowtext; padding: 0cm;">te=
mplate <class...
Types></span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family:=
Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin: 0cm 0cm 0.0001pt 35.4pt; line-heigh=
t: normal; background-position: initial initial; background-repeat: initial=
initial;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Aria=
l, sans-serif; color: black; border: 1pt none windowtext; padding: 0cm;">cl=
ass variant</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-famil=
y: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin: 0cm 0cm 0.0001pt 35.4pt; line-heigh=
t: normal; background-position: initial initial; background-repeat: initial=
initial;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Aria=
l, sans-serif; color: black; border: 1pt none windowtext; padding: 0cm;">{<=
/span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sa=
ns-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin: 0cm 0cm 0.0001pt 35.4pt; line-heigh=
t: normal; background-position: initial initial; background-repeat: initial=
initial;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Aria=
l, sans-serif; color: black; border: 1pt none windowtext; padding: 0cm;">&n=
bsp; int
selected_type; // value is an index among Types... or -1 if no selected typ=
e</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, =
sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin: 0cm 0cm 0.0001pt 35.4pt; line-heigh=
t: normal; background-position: initial initial; background-repeat: initial=
initial;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Aria=
l, sans-serif; color: black; border: 1pt none windowtext; padding: 0cm;">&n=
bsp; std::aligned_storage<MaxLen,
MaxAlign> data;</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; fon=
t-family: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin: 0cm 0cm 0.0001pt 35.4pt; line-heigh=
t: normal; background-position: initial initial; background-repeat: initial=
initial;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Aria=
l, sans-serif; color: black; border: 1pt none windowtext; padding: 0cm;">&n=
bsp; ...</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-fa=
mily: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;"><o:p> </o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">There coul=
d be
a <i>nullvar</i> value that would represent a variant with no typ=
e
selected (similar to <i>nullopt</i> that is part of the std::opti=
onal
proposal). For this and a few other things, the variant class would benefit
from having a design inspired in part by std::optional.</span><span lang=3D=
"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-serif;"><o:p></o=
:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;"><o:p> </o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">Why am I
bringing this? Because if there is a null state, then the "never
empty" problem becomes much simpler. In fact, the problem could then be
called "never empty when not nullvar". The copy assignment of
distinct types could simply be:</span><span lang=3D"EN-CA" style=3D"font-si=
ze: 10pt; font-family: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">- Destroy =
old
object</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Ar=
ial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">- Set sele=
cted
type as <i>nullvar</i> (could be omitted if copy constructor is
noexcept)</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family:=
Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">- Copy
construct new object</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; f=
ont-family: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif; color: black; border: 1pt none windowtext; padding: 0cm;">- Set sele=
cted
type as new type</span><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-=
family: Arial, sans-serif;"><o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;"><o:p> </o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;">If the copy constructor throws, the variant remains in a nullvar st=
ate,
which <i>is</i> a valid state.<o:p></o:p></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom: 0.0001pt; line-height: norma=
l; background-position: initial initial; background-repeat: initial initial=
;"><span lang=3D"EN-CA" style=3D"font-size: 10pt; font-family: Arial, sans-=
serif;"><o:p> </o:p></span></p>
<span lang=3D"EN-CA" style=3D"font-size: 10pt; line-height: 107%; font-fami=
ly: Arial, sans-serif; background-position: initial initial; background-rep=
eat: initial initial;">So,
do you think of any problem of having this nullvar state? Maybe there was a
reason for not including one in boost::variant but I can't see one apart fr=
om
being a design choice.</span><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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_5856_21050858.1367292416929--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 29 Apr 2013 21:42:22 -0700 (PDT)
Raw View
------=_Part_1123_31499325.1367296942898
Content-Type: text/plain; charset=ISO-8859-1
On Monday, April 29, 2013 8:26:56 PM UTC-7, Alex B wrote:
>
> Before trying to solve the never-empty guarantee problem, I think we
> should examine the design of the variant class.
>
>
>
> The design of boost::variant has the following particularity: "By
> default, a variant default-constructs its first bounded type"
>
>
>
> I never felt comfortable with that part of the design of boost::variant.
> It always felt odd to me that the order of the bounded types matter. In my
> opinion, a default constructed variant should not have one of its types
> selected by default. In my personal implementation of a variant class,
> there is what I call a "null" or "disengaged" or "no type" state. If we
> think of a variant as being an index representing the selected type along
> with an aligned storage large enough to hold any of the types of the
> variant, there would be no extra cost of adding a null state. It could
> simply be represented by a special index (let's say -1).
>
>
>
> template <class... Types>
>
> class variant
>
> {
>
> int selected_type; // value is an index among Types... or -1 if no
> selected type
>
> std::aligned_storage<MaxLen, MaxAlign> data;
>
> ...
>
>
>
> There could be a *nullvar* value that would represent a variant with no
> type selected (similar to *nullopt* that is part of the std::optional
> proposal). For this and a few other things, the variant class would benefit
> from having a design inspired in part by std::optional.
>
>
>
> Why am I bringing this? Because if there is a null state, then the "never
> empty" problem becomes much simpler.
>
No it doesn't. OK, it *does*, but only because you're using wordplay to
redefine the problem away.
You can not have a "never empty" guarantee if the variant *can be empty*.
You're basically deciding that variants will have an empty state, and
therefore the user will have to deal with the possibility of a variant
being in the empty state. But we're not going to actually *call* it
"empty"; we'll call it "nullvar".
I fail to see how "nullvar" is in any way different from being "empty". You
still need to define what it means to use a visitor on a "nullvar" variant.
Does it throw an exception? Does it simply fail to call any visitation
function? Does the user get to have a particular operator() overload that
is called on the "nullvar" state? If the latter is true, does *every*visitor class now have to have this overload?
In fact, the problem could then be called "never empty when not nullvar".
> The copy assignment of distinct types could simply be:
>
> - Destroy old object
>
> - Set selected type as *nullvar* (could be omitted if copy constructor is
> noexcept)
>
> - Copy construct new object
>
> - Set selected type as new type
>
>
>
> If the copy constructor throws, the variant remains in a nullvar state,
> which *is* a valid state.
>
>
> So, do you think of any problem of having this nullvar state? Maybe there
> was a reason for not including one in boost::variant but I can't see one
> apart from being a design choice.
>
The reason not to do this is the same reason to not have a variant that can
be empty at all: every user will have to account for the possibility of
using an empty variant, even if they do not want to.
With the *actual* "never empty" guarantee, you can still have an empty
variant. Indeed, you can have almost exactly the same "nullvar" semantics
you propose. Just make the first element in the variant `boost::blank`. A
default-constructed variant will be of type `blank`. A variant that fails
copy construction will be of type `blank`. Boost::variant guarantees this.
This also neatly answers all of those questions I asked earlier about
visitation. Since it's an explicit element in the list, you must account
for that possibility in your visitors. Which is *good.*
In the Boost design, a user who doesn't want the "never empty" guarantee
doesn't have to pay for it (the presence of `blank` prevents the more
expensive copy operation). And a user who *does* want the "never empty"
guarantee, and doesn't want to deal with a "nullvar" state in all of their
visitors, will simply not use `blank`.
Everyone wins with the Boost design. So why should we use an implicit
"empty" state when those who want to have an empty state can use an
explicit one?
Pay only for what you 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/?hl=en.
------=_Part_1123_31499325.1367296942898
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Monday, April 29, 2013 8:26:56 PM UTC-7, Alex B wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><p class=3D"MsoNormal" style=3D"margin-bottom:0=
..0001pt;line-height:normal;background-repeat:initial initial"><span style=
=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D"EN-CA">Before tryi=
ng to solve the never-empty guarantee problem, I think we
should examine the design of the variant class.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">The design of boost::variant has the foll=
owing particularity: "</span><span style=3D"font-size:10pt;font-family:Aria=
l,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=3D"EN=
-CA">By default,
a </span><span style=3D"font-size:10pt;font-family:'Courier New';color=
:black;border:1pt none windowtext;padding:0cm" lang=3D"EN-CA">variant</span=
><span style=3D"font-size:10pt;font-family:Arial,sans-serif;color:black;bor=
der:1pt none windowtext;padding:0cm" lang=3D"EN-CA"> default-construct=
s
its first bounded type"</span><span style=3D"font-size:10pt;font-family:Ari=
al,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">I never felt
comfortable with that part of the design of boost::variant. It always felt =
odd
to me that the order of the bounded types matter. In my opinion, a default
constructed variant should not have one of its types selected by default. I=
n my
personal implementation of a variant class, there is what I call a
"null" or "disengaged" or "no type" state. If we
think of a variant as being an index representing the selected type along w=
ith
an aligned storage large enough to hold any of the types of the variant, th=
ere
would be no extra cost of adding a null state. It could simply be represent=
ed
by a special index (let's say -1).</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">template <class...
Types></span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">class variant</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">{</span><span style=3D"font-size:10pt;font-family:Arial,s=
ans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> int
selected_type; // value is an index among Types... or -1 if no selected typ=
e</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D=
"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> std::aligned_storage<MaxLen,
MaxAlign> data;</span><span style=3D"font-size:10pt;font-family:Arial,sa=
ns-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> ...</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">There could be
a <i>nullvar</i> value that would represent a variant with no typ=
e
selected (similar to <i>nullopt</i> that is part of the std::opti=
onal
proposal). For this and a few other things, the variant class would benefit
from having a design inspired in part by std::optional.</span><span style=
=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">Why am I
bringing this? Because if there is a null state, then the "never
empty" problem becomes much simpler.</span></p></blockquote><div><br>No it =
doesn't. OK, it <i>does</i>, but only because you're using wordplay to rede=
fine the problem away.<br><br>You can not have a "never empty" guarantee if=
the variant <i>can be empty</i>. You're basically deciding that variants w=
ill have an empty state, and therefore the user will have to deal with the =
possibility of a variant being in the empty state. But we're not going to a=
ctually <i>call</i> it "empty"; we'll call it "nullvar".<br><br>I fail to s=
ee how "nullvar" is in any way different from being "empty". You still need=
to define what it means to use a visitor on a "nullvar" variant. Does it t=
hrow an exception? Does it simply fail to call any visitation function? Doe=
s the user get to have a particular operator() overload that is called on t=
he "nullvar" state? If the latter is true, does <i>every</i> visitor class =
now have to have this overload?<br><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-=
height:normal;background-repeat:initial initial"><span style=3D"font-size:1=
0pt;font-family:Arial,sans-serif;color:black;border:1pt none windowtext;pad=
ding:0cm" lang=3D"EN-CA">In fact, the problem could then be
called "never empty when not nullvar". The copy assignment of
distinct types could simply be:</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Destroy old
object</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" la=
ng=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as <i>nullvar</i> (could be omitted if copy constructor is
noexcept)</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Copy
construct new object</span><span style=3D"font-size:10pt;font-family:Arial,=
sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as new type</span><span style=3D"font-size:10pt;font-family:Arial,sans=
-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">If the copy constructor throws, the varia=
nt remains in a nullvar state,
which <i>is</i> a valid state.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<span style=3D"font-size:10pt;line-height:107%;font-family:Arial,sans-serif=
;background-repeat:initial initial" lang=3D"EN-CA">So,
do you think of any problem of having this nullvar state? Maybe there was a
reason for not including one in boost::variant but I can't see one apart fr=
om
being a design choice.</span><br></blockquote><div><br>The reason not to do=
this is the same reason to not have a variant that can be empty at all: ev=
ery user will have to account for the possibility of using an empty variant=
, even if they do not want to.<br><br>With the <i>actual</i> "never empty" =
guarantee, you can still have an empty variant. Indeed, you can have almost=
exactly the same "nullvar" semantics you propose. Just make the first elem=
ent in the variant `boost::blank`. A default-constructed variant will be of=
type `blank`. A variant that fails copy construction will be of type `blan=
k`. Boost::variant guarantees this.<br><br>This also neatly answers all of =
those questions I asked earlier about visitation. Since it's an explicit el=
ement in the list, you must account for that possibility in your visitors. =
Which is <i>good.</i><br><br>In the Boost design, a user who doesn't want t=
he "never empty" guarantee doesn't have to pay for it (the presence of `bla=
nk` prevents the more expensive copy operation). And a user who <i>does</i>=
want the "never empty" guarantee, and doesn't want to deal with a "nullvar=
" state in all of their visitors, will simply not use `blank`.<br><br>Every=
one wins with the Boost design. So why should we use an implicit "empty" st=
ate when those who want to have an empty state can use an explicit one?<br>=
<br>Pay only for what you use.<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_1123_31499325.1367296942898--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 30 Apr 2013 02:47:35 -0500
Raw View
--20cf300fb23d5ab06504db8f39b3
Content-Type: text/plain; charset=ISO-8859-1
On 29 April 2013 23:42, Nicol Bolas <jmckesson@gmail.com> wrote:
> No it doesn't. OK, it *does*, but only because you're using wordplay to
> redefine the problem away.
>
Yes, Alex basically describes at-most-one semantics.
> In the Boost design, a user who doesn't want the "never empty" guarantee
> doesn't have to pay for it (the presence of `blank` prevents the more
> expensive copy operation). And a user who *does* want the "never empty"
> guarantee, and doesn't want to deal with a "nullvar" state in all of their
> visitors, will simply not use `blank`.
>
> Everyone wins with the Boost design.
>
*Experts* win in the Boost design. It is not obvious to non-experts that
variant<vector<char>, string> will have some copy/move operations that are
significantly slower than expected (given that the *only* constructor
required to be marked noexcept is the string move constructor). And,
unlike Boost.Variant, we cannot specialize the std type_traits, so there is
no choice but to use std::nullopt (or equivalent), which is intrusive in
that the user's visitor *must* take it into account. Even if we invented
our own type traits just for variant, you still could only specialize them
for non-Standard user defined types, which doesn't apply in the case above.
In addition, the Boost solution makes the tradeoff of speed over keeping
things in the heap (ie, makes yet another copy), so you still don't get
full control over what happens. And no one has yet addressed the allocator
issue, which I'm pretty sure we'll have to if it can allocate memory and we
want the proposal to succeed.
Seriously, the number one question I've been asked about variant at my last
two jobs is am I sure that a particular instantiation of variant avoids
this performance penalty.
> So why should we use an implicit "empty" state when those who want to have
> an empty state can use an explicit one?
>
To not penalize non-experts for using it. Like I said, in order to not
dictate implementation, I can't see the exception safety guarantee being
any more than "on an exception being thrown, the object is left as an
unspecified instance of one of the types", and in practice, I don't find
such an unknown state as being useful, but I'm certainly willing to be
persuaded by others that it is.
--
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/?hl=en.
--20cf300fb23d5ab06504db8f39b3
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 29 April 2013 23:42, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto=
:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> =
wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class=3D"im">No it doesn't. OK, it <i>does</i>, but only because y=
ou're using wordplay to redefine the problem away.</div></blockquote><d=
iv><br></div><div>Yes, Alex basically describes at-most-one semantics.</div=
>
<div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div>In the Boost design, a us=
er who doesn't want the "never empty" guarantee doesn't h=
ave to pay for it (the presence of `blank` prevents the more expensive copy=
operation). And a user who <i>does</i> want the "never empty" gu=
arantee, and doesn't want to deal with a "nullvar" state in a=
ll of their visitors, will simply not use `blank`.</div>
<div><br>Everyone wins with the Boost design. </div></blockquote><div><br><=
/div><div>*Experts* win in the Boost design. =A0It is not obvious to non-ex=
perts that variant<vector<char>, string> will have some copy/mo=
ve operations that are significantly slower than expected (given that the *=
only* constructor required to be marked noexcept is the string move constru=
ctor). =A0And, unlike Boost.Variant, we cannot specialize the std type_trai=
ts, so there is no choice but to use std::nullopt (or equivalent), which is=
intrusive in that the user's visitor *must* take it into account. =A0E=
ven if we invented our own type traits just for variant, you still could on=
ly specialize them for non-Standard user defined types, which doesn't a=
pply in the case above. =A0In addition, the Boost solution makes the tradeo=
ff of speed over keeping things in the heap (ie, makes yet another copy), s=
o you still don't get full control over what happens. =A0And no one has=
yet addressed the allocator issue, which I'm pretty sure we'll hav=
e to if it can allocate memory and we want the proposal to succeed.</div>
<div><br></div><div>Seriously, the number one question I've been asked =
about variant at my last two jobs is am I sure that a particular instantiat=
ion of variant avoids this performance penalty.</div><div>=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>So why should we use an implicit "empty" state when those wh=
o want to have an empty state can use an explicit one?<br></div></blockquot=
e><div><br></div><div>To not penalize non-experts for using it. =A0Like I s=
aid, in order to not dictate implementation, I can't see the exception =
safety guarantee being any more than "on an exception being thrown, th=
e object is left as an unspecified instance of one of the types", and =
in practice, I don't find such an unknown state as being useful, but I&=
#39;m certainly willing to be persuaded by others that it is.</div>
</div>-- <br>=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto=
:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=
=A0 (847) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
--20cf300fb23d5ab06504db8f39b3--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 30 Apr 2013 02:31:24 -0700 (PDT)
Raw View
------=_Part_4780_27209987.1367314284282
Content-Type: text/plain; charset=ISO-8859-1
On Tuesday, April 30, 2013 12:47:35 AM UTC-7, Nevin ":-)" Liber wrote:
>
> On 29 April 2013 23:42, Nicol Bolas <jmck...@gmail.com <javascript:>>wrote:
>
>> No it doesn't. OK, it *does*, but only because you're using wordplay to
>> redefine the problem away.
>>
>
> Yes, Alex basically describes at-most-one semantics.
>
>
>> In the Boost design, a user who doesn't want the "never empty" guarantee
>> doesn't have to pay for it (the presence of `blank` prevents the more
>> expensive copy operation). And a user who *does* want the "never empty"
>> guarantee, and doesn't want to deal with a "nullvar" state in all of their
>> visitors, will simply not use `blank`.
>>
>> Everyone wins with the Boost design.
>>
>
> *Experts* win in the Boost design. It is not obvious to non-experts that
> variant<vector<char>, string> will have some copy/move operations that are
> significantly slower than expected (given that the *only* constructor
> required to be marked noexcept is the string move constructor). And,
> unlike Boost.Variant, we cannot specialize the std type_traits, so there is
> no choice but to use std::nullopt (or equivalent), which is intrusive in
> that the user's visitor *must* take it into account. Even if we invented
> our own type traits just for variant, you still could only specialize them
> for non-Standard user defined types, which doesn't apply in the case above.
> In addition, the Boost solution makes the tradeoff of speed over keeping
> things in the heap (ie, makes yet another copy), so you still don't get
> full control over what happens. And no one has yet addressed the allocator
> issue, which I'm pretty sure we'll have to if it can allocate memory and we
> want the proposal to succeed.
>
> Seriously, the number one question I've been asked about variant at my
> last two jobs is am I sure that a particular instantiation of variant
> avoids this performance penalty.
>
OK, so how do we do it in a non-expert friendly way that doesn't penalize *
experts*? If you force the variant to have an empty state (and thus force
users to do something with a possibly empty state), then there's no way to
have a variant that *doesn't* have an empty state. Which means people have
to be forced into checking conditions that they don't need to (the state of
being empty is something every visitor should have to account for).
So why should we use an implicit "empty" state when those who want to have
>> an empty state can use an explicit one?
>>
>
> To not penalize non-experts for using it. Like I said, in order to not
> dictate implementation, I can't see the exception safety guarantee being
> any more than "on an exception being thrown, the object is left as an
> unspecified instance of one of the types", and in practice, I don't find
> such an unknown state as being useful, but I'm certainly willing to be
> persuaded by others that it is.
>
I don't understand why it is that we can't specify what state it will be
in. What freedom are you allowing implementations if you do this? You're
saying a variant must contain an instance of a type. So you still want to
enforce the never-empty guarantee, and therefore the copying penalty that
comes along with it. But you don't want the back-door that Boost put into
their class that allows you to avoid that penalty.
So what exactly is it that you want: a variant that will always have an
empty state? Or a variant that can never have an empty state? I prefer
giving the programmer the choice of an empty variant: a variant that can
either be empty or not empty, as the user sees fit by adding a class to the
variant's parameter list.
That's what's nice about the Boost version: if you want a *known* state
after a copy exception, you can get that. So you can define your variant
such that it never is in "such an unknown state". You just have to pay a
cost for it by defining a specific member of the variant.
Why do you want to penalize experts (taking away their choices) *without*doing anything to make the class non-expert friendly?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_4780_27209987.1367314284282
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Tuesday, April 30, 2013 12:47:35 AM UTC-7, Nevin ":-)" Liber wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">On 29 April 2013 23:42, Nicol Bolas=
<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfusc=
ated-mailto=3D"pWRC5VSZnU8J">jmck...@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>No it doesn't. OK, it <i>does</i>, but only because you're using wordp=
lay to redefine the problem away.</div></blockquote><div><br></div><div>Yes=
, Alex basically describes at-most-one semantics.</div>
<div> </div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div>In the Boost design, a=
user who doesn't want the "never empty" guarantee doesn't have to pay for =
it (the presence of `blank` prevents the more expensive copy operation). An=
d a user who <i>does</i> want the "never empty" guarantee, and doesn't want=
to deal with a "nullvar" state in all of their visitors, will simply not u=
se `blank`.</div>
<div><br>Everyone wins with the Boost design. </div></blockquote><div><br><=
/div><div>*Experts* win in the Boost design. It is not obvious to non=
-experts that variant<vector<char>, string> will have some copy=
/move operations that are significantly slower than expected (given that th=
e *only* constructor required to be marked noexcept is the string move cons=
tructor). And, unlike Boost.Variant, we cannot specialize the std typ=
e_traits, so there is no choice but to use std::nullopt (or equivalent), wh=
ich is intrusive in that the user's visitor *must* take it into account. &n=
bsp;Even if we invented our own type traits just for variant, you still cou=
ld only specialize them for non-Standard user defined types, which doesn't =
apply in the case above. In addition, the Boost solution makes the tr=
adeoff of speed over keeping things in the heap (ie, makes yet another copy=
), so you still don't get full control over what happens. And no one =
has yet addressed the allocator issue, which I'm pretty sure we'll have to =
if it can allocate memory and we want the proposal to succeed.</div>
<div><br></div><div>Seriously, the number one question I've been asked abou=
t variant at my last two jobs is am I sure that a particular instantiation =
of variant avoids this performance penalty.<br></div></div></blockquote><di=
v><br>OK, so how do we do it in a non-expert friendly way that doesn't pena=
lize <i>experts</i>? If you force the variant to have an empty state (and t=
hus force users to do something with a possibly empty state), then there's =
no way to have a variant that <i>doesn't</i> have an empty state. Which mea=
ns people have to be forced into checking conditions that they don't need t=
o (the state of being empty is something every visitor should have to accou=
nt for).<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 cla=
ss=3D"gmail_quote"><div></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>So why should we use an implicit "empty" state when those who want to =
have an empty state can use an explicit one?<br></div></blockquote><div><br=
></div><div>To not penalize non-experts for using it. Like I said, in=
order to not dictate implementation, I can't see the exception safety guar=
antee being any more than "on an exception being thrown, the object is left=
as an unspecified instance of one of the types", and in practice, I don't =
find such an unknown state as being useful, but I'm certainly willing to be=
persuaded by others that it is.</div></div></blockquote><div><br>I don't u=
nderstand why it is that we can't specify what state it will be in. What fr=
eedom are you allowing implementations if you do this? You're saying a vari=
ant must contain an instance of a type. So you still want to enforce the ne=
ver-empty guarantee, and therefore the copying penalty that comes along wit=
h it. But you don't want the back-door that Boost put into their class that=
allows you to avoid that penalty.<br><br>So what exactly is it that you wa=
nt: a variant that will always have an=20
empty state? Or a variant that can never have an empty state? I prefer=20
giving the programmer the choice of an empty variant: a variant that can
either be empty or not empty, as the user sees fit by adding a class to
the variant's parameter list.<br><br>That's what's nice about the Boost ve=
rsion: if you want a <i>known</i> state after a copy exception, you can get=
that. So you can define your variant such that it never is in "such an unk=
nown state". You just have to pay a cost for it by defining a specific memb=
er of the variant.<br><br>Why do you want to penalize experts (taking away =
their choices) <i>without</i> doing anything to make the class non-expert f=
riendly?<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_4780_27209987.1367314284282--
.
Author: Alex B <devalexb@gmail.com>
Date: Wed, 1 May 2013 04:43:13 -0700 (PDT)
Raw View
------=_Part_5436_11279661.1367408593566
Content-Type: text/plain; charset=ISO-8859-1
>
> You still need to define what it means to use a visitor on a "nullvar"
> variant.
>
Fair enough.
Does it throw an exception? Does it simply fail to call any visitation
> function? Does the user get to have a particular operator() overload that
> is called on the "nullvar" state? If the latter is true, does *every* visitor
> class now have to have this overload?
How about throwing if the variant is in a nullvar state and the visitor
doesn't provide a nullvar overload? That way, if you are sure that your
variant is not nullvar, don't provide a nullvar overload. Otherwise, 2
choices: provide an overload or surround your call to apply visitor by a
try-catch.
As I understand it, the problem that you are raising is that you don't want
to penalize the user by forcing him to implement an overload taking a
nullvar_t in every of his visitors. As I said, I would not force him to do
so (but it would be an option).
I would push it even further. I would not force visitors to provide
overloads for all of the types. If visitor::operator() cannot be called for
the current type of the variant, then just throw. Let's say that your
variant contains 10 types. You *know* that in a specific context, the
variant type should be one of only 3 of these types. So why not allow the
implementer of the visitor to only provide overloads for the 3 types that
he expect? Just throw if the provided overloads cannot accept the current
type of the variant (including nullvar_t).
Pay only for what you use.
I couldn't agree more.
Notice that I am not going into the details of how it should be implemented
but rather on the intent and high level design of the class that will
influence how the user will use it. For instance, I am not sure yet how the
class will be able to determine if the visitor is providing a specific
overload (maybe it will require some compiler support or maybe that
sentence should be rephrased -- what I care for now is the intent).
Final note about the "expert"/"non-expert" argument.
I can't seem to see how it would benefit "experts" to have the variant copy
constructed to the original type (from/to alternate space) if a copy/move
assignment fails. If the assignment fails, I might not need to use the
variant anymore. So that copy that was made to/from alternate space would
just be a waste. I personally think that an expert will want control over
this; copying back to the original type seems an arbitrary choice to me.
But we don't have to agree on this if you agree on what I first suggest...
On Tuesday, April 30, 2013 12:42:22 AM UTC-4, Nicol Bolas wrote:
>
> On Monday, April 29, 2013 8:26:56 PM UTC-7, Alex B wrote:
>>
>> Before trying to solve the never-empty guarantee problem, I think we
>> should examine the design of the variant class.
>>
>>
>>
>> The design of boost::variant has the following particularity: "By
>> default, a variant default-constructs its first bounded type"
>>
>>
>>
>> I never felt comfortable with that part of the design of boost::variant.
>> It always felt odd to me that the order of the bounded types matter. In my
>> opinion, a default constructed variant should not have one of its types
>> selected by default. In my personal implementation of a variant class,
>> there is what I call a "null" or "disengaged" or "no type" state. If we
>> think of a variant as being an index representing the selected type along
>> with an aligned storage large enough to hold any of the types of the
>> variant, there would be no extra cost of adding a null state. It could
>> simply be represented by a special index (let's say -1).
>>
>>
>>
>> template <class... Types>
>>
>> class variant
>>
>> {
>>
>> int selected_type; // value is an index among Types... or -1 if no
>> selected type
>>
>> std::aligned_storage<MaxLen, MaxAlign> data;
>>
>> ...
>>
>>
>>
>> There could be a *nullvar* value that would represent a variant with no
>> type selected (similar to *nullopt* that is part of the std::optional
>> proposal). For this and a few other things, the variant class would benefit
>> from having a design inspired in part by std::optional.
>>
>>
>>
>> Why am I bringing this? Because if there is a null state, then the "never
>> empty" problem becomes much simpler.
>>
>
> No it doesn't. OK, it *does*, but only because you're using wordplay to
> redefine the problem away.
>
> You can not have a "never empty" guarantee if the variant *can be empty*.
> You're basically deciding that variants will have an empty state, and
> therefore the user will have to deal with the possibility of a variant
> being in the empty state. But we're not going to actually *call* it
> "empty"; we'll call it "nullvar".
>
> I fail to see how "nullvar" is in any way different from being "empty".
> You still need to define what it means to use a visitor on a "nullvar"
> variant. Does it throw an exception? Does it simply fail to call any
> visitation function? Does the user get to have a particular operator()
> overload that is called on the "nullvar" state? If the latter is true, does
> *every* visitor class now have to have this overload?
>
> In fact, the problem could then be called "never empty when not nullvar".
>> The copy assignment of distinct types could simply be:
>>
>> - Destroy old object
>>
>> - Set selected type as *nullvar* (could be omitted if copy constructor
>> is noexcept)
>>
>> - Copy construct new object
>>
>> - Set selected type as new type
>>
>>
>>
>> If the copy constructor throws, the variant remains in a nullvar state,
>> which *is* a valid state.
>>
>>
>> So, do you think of any problem of having this nullvar state? Maybe there
>> was a reason for not including one in boost::variant but I can't see one
>> apart from being a design choice.
>>
>
> The reason not to do this is the same reason to not have a variant that
> can be empty at all: every user will have to account for the possibility of
> using an empty variant, even if they do not want to.
>
> With the *actual* "never empty" guarantee, you can still have an empty
> variant. Indeed, you can have almost exactly the same "nullvar" semantics
> you propose. Just make the first element in the variant `boost::blank`. A
> default-constructed variant will be of type `blank`. A variant that fails
> copy construction will be of type `blank`. Boost::variant guarantees this.
>
> This also neatly answers all of those questions I asked earlier about
> visitation. Since it's an explicit element in the list, you must account
> for that possibility in your visitors. Which is *good.*
>
> In the Boost design, a user who doesn't want the "never empty" guarantee
> doesn't have to pay for it (the presence of `blank` prevents the more
> expensive copy operation). And a user who *does* want the "never empty"
> guarantee, and doesn't want to deal with a "nullvar" state in all of their
> visitors, will simply not use `blank`.
>
> Everyone wins with the Boost design. So why should we use an implicit
> "empty" state when those who want to have an empty state can use an
> explicit one?
>
> Pay only for what you use.
>
On Tuesday, April 30, 2013 12:42:22 AM UTC-4, Nicol Bolas wrote:
>
> On Monday, April 29, 2013 8:26:56 PM UTC-7, Alex B wrote:
>>
>> Before trying to solve the never-empty guarantee problem, I think we
>> should examine the design of the variant class.
>>
>>
>>
>> The design of boost::variant has the following particularity: "By
>> default, a variant default-constructs its first bounded type"
>>
>>
>>
>> I never felt comfortable with that part of the design of boost::variant.
>> It always felt odd to me that the order of the bounded types matter. In my
>> opinion, a default constructed variant should not have one of its types
>> selected by default. In my personal implementation of a variant class,
>> there is what I call a "null" or "disengaged" or "no type" state. If we
>> think of a variant as being an index representing the selected type along
>> with an aligned storage large enough to hold any of the types of the
>> variant, there would be no extra cost of adding a null state. It could
>> simply be represented by a special index (let's say -1).
>>
>>
>>
>> template <class... Types>
>>
>> class variant
>>
>> {
>>
>> int selected_type; // value is an index among Types... or -1 if no
>> selected type
>>
>> std::aligned_storage<MaxLen, MaxAlign> data;
>>
>> ...
>>
>>
>>
>> There could be a *nullvar* value that would represent a variant with no
>> type selected (similar to *nullopt* that is part of the std::optional
>> proposal). For this and a few other things, the variant class would benefit
>> from having a design inspired in part by std::optional.
>>
>>
>>
>> Why am I bringing this? Because if there is a null state, then the "never
>> empty" problem becomes much simpler.
>>
>
> No it doesn't. OK, it *does*, but only because you're using wordplay to
> redefine the problem away.
>
> You can not have a "never empty" guarantee if the variant *can be empty*.
> You're basically deciding that variants will have an empty state, and
> therefore the user will have to deal with the possibility of a variant
> being in the empty state. But we're not going to actually *call* it
> "empty"; we'll call it "nullvar".
>
> I fail to see how "nullvar" is in any way different from being "empty".
> You still need to define what it means to use a visitor on a "nullvar"
> variant. Does it throw an exception? Does it simply fail to call any
> visitation function? Does the user get to have a particular operator()
> overload that is called on the "nullvar" state? If the latter is true, does
> *every* visitor class now have to have this overload?
>
> In fact, the problem could then be called "never empty when not nullvar".
>> The copy assignment of distinct types could simply be:
>>
>> - Destroy old object
>>
>> - Set selected type as *nullvar* (could be omitted if copy constructor
>> is noexcept)
>>
>> - Copy construct new object
>>
>> - Set selected type as new type
>>
>>
>>
>> If the copy constructor throws, the variant remains in a nullvar state,
>> which *is* a valid state.
>>
>>
>> So, do you think of any problem of having this nullvar state? Maybe there
>> was a reason for not including one in boost::variant but I can't see one
>> apart from being a design choice.
>>
>
> The reason not to do this is the same reason to not have a variant that
> can be empty at all: every user will have to account for the possibility of
> using an empty variant, even if they do not want to.
>
> With the *actual* "never empty" guarantee, you can still have an empty
> variant. Indeed, you can have almost exactly the same "nullvar" semantics
> you propose. Just make the first element in the variant `boost::blank`. A
> default-constructed variant will be of type `blank`. A variant that fails
> copy construction will be of type `blank`. Boost::variant guarantees this.
>
> This also neatly answers all of those questions I asked earlier about
> visitation. Since it's an explicit element in the list, you must account
> for that possibility in your visitors. Which is *good.*
>
> In the Boost design, a user who doesn't want the "never empty" guarantee
> doesn't have to pay for it (the presence of `blank` prevents the more
> expensive copy operation). And a user who *does* want the "never empty"
> guarantee, and doesn't want to deal with a "nullvar" state in all of their
> visitors, will simply not use `blank`.
>
> Everyone wins with the Boost design. So why should we use an implicit
> "empty" state when those who want to have an empty state can use an
> explicit one?
>
> Pay only for what you use.
>
On Tuesday, April 30, 2013 12:42:22 AM UTC-4, Nicol Bolas wrote:
>
> On Monday, April 29, 2013 8:26:56 PM UTC-7, Alex B wrote:
>>
>> Before trying to solve the never-empty guarantee problem, I think we
>> should examine the design of the variant class.
>>
>>
>>
>> The design of boost::variant has the following particularity: "By
>> default, a variant default-constructs its first bounded type"
>>
>>
>>
>> I never felt comfortable with that part of the design of boost::variant.
>> It always felt odd to me that the order of the bounded types matter. In my
>> opinion, a default constructed variant should not have one of its types
>> selected by default. In my personal implementation of a variant class,
>> there is what I call a "null" or "disengaged" or "no type" state. If we
>> think of a variant as being an index representing the selected type along
>> with an aligned storage large enough to hold any of the types of the
>> variant, there would be no extra cost of adding a null state. It could
>> simply be represented by a special index (let's say -1).
>>
>>
>>
>> template <class... Types>
>>
>> class variant
>>
>> {
>>
>> int selected_type; // value is an index among Types... or -1 if no
>> selected type
>>
>> std::aligned_storage<MaxLen, MaxAlign> data;
>>
>> ...
>>
>>
>>
>> There could be a *nullvar* value that would represent a variant with no
>> type selected (similar to *nullopt* that is part of the std::optional
>> proposal). For this and a few other things, the variant class would benefit
>> from having a design inspired in part by std::optional.
>>
>>
>>
>> Why am I bringing this? Because if there is a null state, then the "never
>> empty" problem becomes much simpler.
>>
>
> No it doesn't. OK, it *does*, but only because you're using wordplay to
> redefine the problem away.
>
> You can not have a "never empty" guarantee if the variant *can be empty*.
> You're basically deciding that variants will have an empty state, and
> therefore the user will have to deal with the possibility of a variant
> being in the empty state. But we're not going to actually *call* it
> "empty"; we'll call it "nullvar".
>
> I fail to see how "nullvar" is in any way different from being "empty".
> You still need to define what it means to use a visitor on a "nullvar"
> variant. Does it throw an exception? Does it simply fail to call any
> visitation function? Does the user get to have a particular operator()
> overload that is called on the "nullvar" state? If the latter is true, does
> *every* visitor class now have to have this overload?
>
> In fact, the problem could then be called "never empty when not nullvar".
>> The copy assignment of distinct types could simply be:
>>
>> - Destroy old object
>>
>> - Set selected type as *nullvar* (could be omitted if copy constructor
>> is noexcept)
>>
>> - Copy construct new object
>>
>> - Set selected type as new type
>>
>>
>>
>> If the copy constructor throws, the variant remains in a nullvar state,
>> which *is* a valid state.
>>
>>
>> So, do you think of any problem of having this nullvar state? Maybe there
>> was a reason for not including one in boost::variant but I can't see one
>> apart from being a design choice.
>>
>
> The reason not to do this is the same reason to not have a variant that
> can be empty at all: every user will have to account for the possibility of
> using an empty variant, even if they do not want to.
>
> With the *actual* "never empty" guarantee, you can still have an empty
> variant. Indeed, you can have almost exactly the same "nullvar" semantics
> you propose. Just make the first element in the variant `boost::blank`. A
> default-constructed variant will be of type `blank`. A variant that fails
> copy construction will be of type `blank`. Boost::variant guarantees this.
>
> This also neatly answers all of those questions I asked earlier about
> visitation. Since it's an explicit element in the list, you must account
> for that possibility in your visitors. Which is *good.*
>
> In the Boost design, a user who doesn't want the "never empty" guarantee
> doesn't have to pay for it (the presence of `blank` prevents the more
> expensive copy operation). And a user who *does* want the "never empty"
> guarantee, and doesn't want to deal with a "nullvar" state in all of their
> visitors, will simply not use `blank`.
>
> Everyone wins with the Boost design. So why should we use an implicit
> "empty" state when those who want to have an empty state can use an
> explicit one?
>
> Pay only for what you 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/?hl=en.
------=_Part_5436_11279661.1367408593566
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div>You still need to define =
what it means to use a visitor on a "nullvar" variant.<br></div></blockquot=
e><div><br></div><div>Fair enough.</div><div><br></div><div><blockquote cla=
ss=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; paddin=
g-left: 1ex;">Does it throw an exception? Does it simply fail to call any v=
isitation function? Does the user get to have a particular operator() overl=
oad that is called on the "nullvar" state? If the latter is true, does =
;<i>every</i> visitor class now have to have this overload?</blockquot=
e><div><br></div><div>How about throwing if the variant is in a nullvar sta=
te and the visitor doesn't provide a nullvar overload? That way, if you are=
sure that your variant is not nullvar, don't provide a nullvar overload. O=
therwise, 2 choices: provide an overload or surround your call to=
apply visitor by a try-catch.</div></div><div><br></div><div>As I understa=
nd it, the problem that you are raising is that you don't want to penalize =
the user by forcing him to implement an overload taking a nullvar_t in ever=
y of his visitors. As I said, I would not force him to do so (but it would =
be an option).</div><div><br></div><div>I would push it even further. I wou=
ld not force visitors to provide overloads for all of the types. If visitor=
::operator() cannot be called for the current type of the variant, then jus=
t throw. Let's say that your variant contains 10 types. You *know* that in =
a specific context, the variant type should be one of only 3 of these types=
.. So why not allow the implementer of the visitor to only provide overloads=
for the 3 types that he expect? Just throw if the provided overloads canno=
t accept the current type of the variant (including nullvar_t).</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-l=
eft-style: solid; padding-left: 1ex;">Pay only for what you use.</blockquot=
e><div><br></div><div>I couldn't agree more.</div><div><br></div><div>Notic=
e that I am not going into the details of how it should be implemented but =
rather on the intent and high level design of the class that will influence=
how the user will use it. For instance, I am not sure yet how the class wi=
ll be able to determine if the visitor is providing a specific overload (ma=
ybe it will require some compiler support or maybe that sentence should be =
rephrased -- what I care for now is the intent).</div><div><br></div><div>F=
inal note about the "expert"/"non-expert" argument.</div><div><br></div><di=
v>I can't seem to see how it would benefit "experts" to have the variant co=
py constructed to the original type (from/to alternate space) if a copy/mov=
e assignment fails. If the assignment fails, I might not need to use the va=
riant anymore. So that copy that was made to/from alternate space would jus=
t be a waste. I personally think that an expert will want control=
over this; copying back to the original type seems an arbitrary choice to =
me. But we don't have to agree on this if you agree on what I first suggest=
....</div><div><br></div><br>On Tuesday, April 30, 2013 12:42:22 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;">On Monday, Ap=
ril 29, 2013 8:26:56 PM UTC-7, Alex B wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height=
:normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fo=
nt-family:Arial,sans-serif" lang=3D"EN-CA">Before trying to solve the never=
-empty guarantee problem, I think we
should examine the design of the variant class.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">The design of boost::variant has the foll=
owing particularity: "</span><span style=3D"font-size:10pt;font-family:Aria=
l,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=3D"EN=
-CA">By default,
a </span><span style=3D"font-size:10pt;font-family:'Courier New';color=
:black;border:1pt none windowtext;padding:0cm" lang=3D"EN-CA">variant</span=
><span style=3D"font-size:10pt;font-family:Arial,sans-serif;color:black;bor=
der:1pt none windowtext;padding:0cm" lang=3D"EN-CA"> default-construct=
s
its first bounded type"</span><span style=3D"font-size:10pt;font-family:Ari=
al,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">I never felt
comfortable with that part of the design of boost::variant. It always felt =
odd
to me that the order of the bounded types matter. In my opinion, a default
constructed variant should not have one of its types selected by default. I=
n my
personal implementation of a variant class, there is what I call a
"null" or "disengaged" or "no type" state. If we
think of a variant as being an index representing the selected type along w=
ith
an aligned storage large enough to hold any of the types of the variant, th=
ere
would be no extra cost of adding a null state. It could simply be represent=
ed
by a special index (let's say -1).</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">template <class...
Types></span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">class variant</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">{</span><span style=3D"font-size:10pt;font-family:Arial,s=
ans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> int
selected_type; // value is an index among Types... or -1 if no selected typ=
e</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D=
"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> std::aligned_storage<MaxLen,
MaxAlign> data;</span><span style=3D"font-size:10pt;font-family:Arial,sa=
ns-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> ...</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">There could be
a <i>nullvar</i> value that would represent a variant with no typ=
e
selected (similar to <i>nullopt</i> that is part of the std::opti=
onal
proposal). For this and a few other things, the variant class would benefit
from having a design inspired in part by std::optional.</span><span style=
=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">Why am I
bringing this? Because if there is a null state, then the "never
empty" problem becomes much simpler.</span></p></blockquote><div><br>No it =
doesn't. OK, it <i>does</i>, but only because you're using wordplay to rede=
fine the problem away.<br><br>You can not have a "never empty" guarantee if=
the variant <i>can be empty</i>. You're basically deciding that variants w=
ill have an empty state, and therefore the user will have to deal with the =
possibility of a variant being in the empty state. But we're not going to a=
ctually <i>call</i> it "empty"; we'll call it "nullvar".<br><br>I fail to s=
ee how "nullvar" is in any way different from being "empty". You still need=
to define what it means to use a visitor on a "nullvar" variant. Does it t=
hrow an exception? Does it simply fail to call any visitation function? Doe=
s the user get to have a particular operator() overload that is called on t=
he "nullvar" state? If the latter is true, does <i>every</i> visitor class =
now have to have this overload?<br><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-heigh=
t:normal;background-repeat:initial initial"><span style=3D"font-size:10pt;f=
ont-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:=
0cm" lang=3D"EN-CA">In fact, the problem could then be
called "never empty when not nullvar". The copy assignment of
distinct types could simply be:</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Destroy old
object</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" la=
ng=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as <i>nullvar</i> (could be omitted if copy constructor is
noexcept)</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Copy
construct new object</span><span style=3D"font-size:10pt;font-family:Arial,=
sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as new type</span><span style=3D"font-size:10pt;font-family:Arial,sans=
-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">If the copy constructor throws, the varia=
nt remains in a nullvar state,
which <i>is</i> a valid state.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<span style=3D"font-size:10pt;line-height:107%;font-family:Arial,sans-serif=
;background-repeat:initial initial" lang=3D"EN-CA">So,
do you think of any problem of having this nullvar state? Maybe there was a
reason for not including one in boost::variant but I can't see one apart fr=
om
being a design choice.</span><br></blockquote><div><br>The reason not to do=
this is the same reason to not have a variant that can be empty at all: ev=
ery user will have to account for the possibility of using an empty variant=
, even if they do not want to.<br><br>With the <i>actual</i> "never empty" =
guarantee, you can still have an empty variant. Indeed, you can have almost=
exactly the same "nullvar" semantics you propose. Just make the first elem=
ent in the variant `boost::blank`. A default-constructed variant will be of=
type `blank`. A variant that fails copy construction will be of type `blan=
k`. Boost::variant guarantees this.<br><br>This also neatly answers all of =
those questions I asked earlier about visitation. Since it's an explicit el=
ement in the list, you must account for that possibility in your visitors. =
Which is <i>good.</i><br><br>In the Boost design, a user who doesn't want t=
he "never empty" guarantee doesn't have to pay for it (the presence of `bla=
nk` prevents the more expensive copy operation). And a user who <i>does</i>=
want the "never empty" guarantee, and doesn't want to deal with a "nullvar=
" state in all of their visitors, will simply not use `blank`.<br><br>Every=
one wins with the Boost design. So why should we use an implicit "empty" st=
ate when those who want to have an empty state can use an explicit one?<br>=
<br>Pay only for what you use.<br></div></blockquote><br>On Tuesday, April =
30, 2013 12:42:22 AM UTC-4, Nicol Bolas wrote:<blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;">On Monday, April 29, 2013 8:26:56 PM UTC-7, Alex B wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex"><p class=3D"MsoNormal" style=3D"margi=
n-bottom:0.0001pt;line-height:normal;background-repeat:initial initial"><sp=
an style=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D"EN-CA">Bef=
ore trying to solve the never-empty guarantee problem, I think we
should examine the design of the variant class.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">The design of boost::variant has the foll=
owing particularity: "</span><span style=3D"font-size:10pt;font-family:Aria=
l,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=3D"EN=
-CA">By default,
a </span><span style=3D"font-size:10pt;font-family:'Courier New';color=
:black;border:1pt none windowtext;padding:0cm" lang=3D"EN-CA">variant</span=
><span style=3D"font-size:10pt;font-family:Arial,sans-serif;color:black;bor=
der:1pt none windowtext;padding:0cm" lang=3D"EN-CA"> default-construct=
s
its first bounded type"</span><span style=3D"font-size:10pt;font-family:Ari=
al,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">I never felt
comfortable with that part of the design of boost::variant. It always felt =
odd
to me that the order of the bounded types matter. In my opinion, a default
constructed variant should not have one of its types selected by default. I=
n my
personal implementation of a variant class, there is what I call a
"null" or "disengaged" or "no type" state. If we
think of a variant as being an index representing the selected type along w=
ith
an aligned storage large enough to hold any of the types of the variant, th=
ere
would be no extra cost of adding a null state. It could simply be represent=
ed
by a special index (let's say -1).</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">template <class...
Types></span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">class variant</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">{</span><span style=3D"font-size:10pt;font-family:Arial,s=
ans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> int
selected_type; // value is an index among Types... or -1 if no selected typ=
e</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D=
"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> std::aligned_storage<MaxLen,
MaxAlign> data;</span><span style=3D"font-size:10pt;font-family:Arial,sa=
ns-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> ...</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">There could be
a <i>nullvar</i> value that would represent a variant with no typ=
e
selected (similar to <i>nullopt</i> that is part of the std::opti=
onal
proposal). For this and a few other things, the variant class would benefit
from having a design inspired in part by std::optional.</span><span style=
=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">Why am I
bringing this? Because if there is a null state, then the "never
empty" problem becomes much simpler.</span></p></blockquote><div><br>No it =
doesn't. OK, it <i>does</i>, but only because you're using wordplay to rede=
fine the problem away.<br><br>You can not have a "never empty" guarantee if=
the variant <i>can be empty</i>. You're basically deciding that variants w=
ill have an empty state, and therefore the user will have to deal with the =
possibility of a variant being in the empty state. But we're not going to a=
ctually <i>call</i> it "empty"; we'll call it "nullvar".<br><br>I fail to s=
ee how "nullvar" is in any way different from being "empty". You still need=
to define what it means to use a visitor on a "nullvar" variant. Does it t=
hrow an exception? Does it simply fail to call any visitation function? Doe=
s the user get to have a particular operator() overload that is called on t=
he "nullvar" state? If the latter is true, does <i>every</i> visitor class =
now have to have this overload?<br><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-heigh=
t:normal;background-repeat:initial initial"><span style=3D"font-size:10pt;f=
ont-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:=
0cm" lang=3D"EN-CA">In fact, the problem could then be
called "never empty when not nullvar". The copy assignment of
distinct types could simply be:</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Destroy old
object</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" la=
ng=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as <i>nullvar</i> (could be omitted if copy constructor is
noexcept)</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Copy
construct new object</span><span style=3D"font-size:10pt;font-family:Arial,=
sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as new type</span><span style=3D"font-size:10pt;font-family:Arial,sans=
-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">If the copy constructor throws, the varia=
nt remains in a nullvar state,
which <i>is</i> a valid state.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<span style=3D"font-size:10pt;line-height:107%;font-family:Arial,sans-serif=
;background-repeat:initial initial" lang=3D"EN-CA">So,
do you think of any problem of having this nullvar state? Maybe there was a
reason for not including one in boost::variant but I can't see one apart fr=
om
being a design choice.</span><br></blockquote><div><br>The reason not to do=
this is the same reason to not have a variant that can be empty at all: ev=
ery user will have to account for the possibility of using an empty variant=
, even if they do not want to.<br><br>With the <i>actual</i> "never empty" =
guarantee, you can still have an empty variant. Indeed, you can have almost=
exactly the same "nullvar" semantics you propose. Just make the first elem=
ent in the variant `boost::blank`. A default-constructed variant will be of=
type `blank`. A variant that fails copy construction will be of type `blan=
k`. Boost::variant guarantees this.<br><br>This also neatly answers all of =
those questions I asked earlier about visitation. Since it's an explicit el=
ement in the list, you must account for that possibility in your visitors. =
Which is <i>good.</i><br><br>In the Boost design, a user who doesn't want t=
he "never empty" guarantee doesn't have to pay for it (the presence of `bla=
nk` prevents the more expensive copy operation). And a user who <i>does</i>=
want the "never empty" guarantee, and doesn't want to deal with a "nullvar=
" state in all of their visitors, will simply not use `blank`.<br><br>Every=
one wins with the Boost design. So why should we use an implicit "empty" st=
ate when those who want to have an empty state can use an explicit one?<br>=
<br>Pay only for what you use.<br></div></blockquote><br>On Tuesday, April =
30, 2013 12:42:22 AM UTC-4, Nicol Bolas wrote:<blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;">On Monday, April 29, 2013 8:26:56 PM UTC-7, Alex B wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex"><p class=3D"MsoNormal" style=3D"margi=
n-bottom:0.0001pt;line-height:normal;background-repeat:initial initial"><sp=
an style=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D"EN-CA">Bef=
ore trying to solve the never-empty guarantee problem, I think we
should examine the design of the variant class.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">The design of boost::variant has the foll=
owing particularity: "</span><span style=3D"font-size:10pt;font-family:Aria=
l,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=3D"EN=
-CA">By default,
a </span><span style=3D"font-size:10pt;font-family:'Courier New';color=
:black;border:1pt none windowtext;padding:0cm" lang=3D"EN-CA">variant</span=
><span style=3D"font-size:10pt;font-family:Arial,sans-serif;color:black;bor=
der:1pt none windowtext;padding:0cm" lang=3D"EN-CA"> default-construct=
s
its first bounded type"</span><span style=3D"font-size:10pt;font-family:Ari=
al,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">I never felt
comfortable with that part of the design of boost::variant. It always felt =
odd
to me that the order of the bounded types matter. In my opinion, a default
constructed variant should not have one of its types selected by default. I=
n my
personal implementation of a variant class, there is what I call a
"null" or "disengaged" or "no type" state. If we
think of a variant as being an index representing the selected type along w=
ith
an aligned storage large enough to hold any of the types of the variant, th=
ere
would be no extra cost of adding a null state. It could simply be represent=
ed
by a special index (let's say -1).</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">template <class...
Types></span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">class variant</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA">{</span><span style=3D"font-size:10pt;font-family:Arial,s=
ans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> int
selected_type; // value is an index among Types... or -1 if no selected typ=
e</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D=
"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> std::aligned_storage<MaxLen,
MaxAlign> data;</span><span style=3D"font-size:10pt;font-family:Arial,sa=
ns-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin:0cm 0cm 0.0001pt 35.4pt;line-height:=
normal;background-repeat:initial initial"><span style=3D"font-size:10pt;fon=
t-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0c=
m" lang=3D"EN-CA"> ...</span><span style=3D"font-size:10pt;font=
-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">There could be
a <i>nullvar</i> value that would represent a variant with no typ=
e
selected (similar to <i>nullopt</i> that is part of the std::opti=
onal
proposal). For this and a few other things, the variant class would benefit
from having a design inspired in part by std::optional.</span><span style=
=3D"font-size:10pt;font-family:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">Why am I
bringing this? Because if there is a null state, then the "never
empty" problem becomes much simpler.</span></p></blockquote><div><br>No it =
doesn't. OK, it <i>does</i>, but only because you're using wordplay to rede=
fine the problem away.<br><br>You can not have a "never empty" guarantee if=
the variant <i>can be empty</i>. You're basically deciding that variants w=
ill have an empty state, and therefore the user will have to deal with the =
possibility of a variant being in the empty state. But we're not going to a=
ctually <i>call</i> it "empty"; we'll call it "nullvar".<br><br>I fail to s=
ee how "nullvar" is in any way different from being "empty". You still need=
to define what it means to use a visitor on a "nullvar" variant. Does it t=
hrow an exception? Does it simply fail to call any visitation function? Doe=
s the user get to have a particular operator() overload that is called on t=
he "nullvar" state? If the latter is true, does <i>every</i> visitor class =
now have to have this overload?<br><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-heigh=
t:normal;background-repeat:initial initial"><span style=3D"font-size:10pt;f=
ont-family:Arial,sans-serif;color:black;border:1pt none windowtext;padding:=
0cm" lang=3D"EN-CA">In fact, the problem could then be
called "never empty when not nullvar". The copy assignment of
distinct types could simply be:</span><span style=3D"font-size:10pt;font-fa=
mily:Arial,sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Destroy old
object</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif" la=
ng=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as <i>nullvar</i> (could be omitted if copy constructor is
noexcept)</span><span style=3D"font-size:10pt;font-family:Arial,sans-serif"=
lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Copy
construct new object</span><span style=3D"font-size:10pt;font-family:Arial,=
sans-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif;color:black;border:1pt none windowtext;padding:0cm" lang=
=3D"EN-CA">- Set selected
type as new type</span><span style=3D"font-size:10pt;font-family:Arial,sans=
-serif" lang=3D"EN-CA"></span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA">If the copy constructor throws, the varia=
nt remains in a nullvar state,
which <i>is</i> a valid state.</span></p>
<p class=3D"MsoNormal" style=3D"margin-bottom:0.0001pt;line-height:normal;b=
ackground-repeat:initial initial"><span style=3D"font-size:10pt;font-family=
:Arial,sans-serif" lang=3D"EN-CA"> </span></p>
<span style=3D"font-size:10pt;line-height:107%;font-family:Arial,sans-serif=
;background-repeat:initial initial" lang=3D"EN-CA">So,
do you think of any problem of having this nullvar state? Maybe there was a
reason for not including one in boost::variant but I can't see one apart fr=
om
being a design choice.</span><br></blockquote><div><br>The reason not to do=
this is the same reason to not have a variant that can be empty at all: ev=
ery user will have to account for the possibility of using an empty variant=
, even if they do not want to.<br><br>With the <i>actual</i> "never empty" =
guarantee, you can still have an empty variant. Indeed, you can have almost=
exactly the same "nullvar" semantics you propose. Just make the first elem=
ent in the variant `boost::blank`. A default-constructed variant will be of=
type `blank`. A variant that fails copy construction will be of type `blan=
k`. Boost::variant guarantees this.<br><br>This also neatly answers all of =
those questions I asked earlier about visitation. Since it's an explicit el=
ement in the list, you must account for that possibility in your visitors. =
Which is <i>good.</i><br><br>In the Boost design, a user who doesn't want t=
he "never empty" guarantee doesn't have to pay for it (the presence of `bla=
nk` prevents the more expensive copy operation). And a user who <i>does</i>=
want the "never empty" guarantee, and doesn't want to deal with a "nullvar=
" state in all of their visitors, will simply not use `blank`.<br><br>Every=
one wins with the Boost design. So why should we use an implicit "empty" st=
ate when those who want to have an empty state can use an explicit one?<br>=
<br>Pay only for what you use.<br></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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_5436_11279661.1367408593566--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 1 May 2013 07:20:59 -0700 (PDT)
Raw View
------=_Part_6161_32666915.1367418059125
Content-Type: text/plain; charset=ISO-8859-1
On Wednesday, May 1, 2013 4:43:13 AM UTC-7, Alex B wrote:
>
> Does it throw an exception? Does it simply fail to call any visitation
>> function? Does the user get to have a particular operator() overload that
>> is called on the "nullvar" state? If the latter is true, does *every* visitor
>> class now have to have this overload?
>
>
> How about throwing if the variant is in a nullvar state and the visitor
> doesn't provide a nullvar overload? That way, if you are sure that your
> variant is not nullvar, don't provide a nullvar overload. Otherwise, 2
> choices: provide an overload or surround your call to apply visitor by a
> try-catch.
>
> As I understand it, the problem that you are raising is that you don't
> want to penalize the user by forcing him to implement an overload taking a
> nullvar_t in every of his visitors. As I said, I would not force him to do
> so (but it would be an option).
>
> I would push it even further. I would not force visitors to provide
> overloads for all of the types. If visitor::operator() cannot be called for
> the current type of the variant, then just throw. Let's say that your
> variant contains 10 types. You *know* that in a specific context, the
> variant type should be one of only 3 of these types. So why not allow the
> implementer of the visitor to only provide overloads for the 3 types that
> he expect? Just throw if the provided overloads cannot accept the current
> type of the variant (including nullvar_t).
>
There's a good reason not to do that. One of the nice things about variants
are that if you add new elements, you get a *compiler* error in every piece
of code where you forgot handle the new element. Not a runtime error that
you may or may not ever hit, a compile-time error that you can't ignore.
Furthermore, if a user knows that it's only in one of three states, it's
very easy for them to handle the rest with a: `template<typename T>
operator()(const T&) {}` overload. They could even `throw` if they want to.
It also happens to make it clear that it's *not* a mistake for it to not
handle the other alternatives; you're *explicitly* saying that you're doing
nothing for them.
The Boost.Variant way, the user has choices: do they want the compiler
error or a runtime error? I'd rather those choices be apparent and within
the visitor class itself, rather than having different visitation functions
or whatever.
To allow a visitation function to throw based on the state of the variant
goes against a significant part of the point of using variants rather than
something else.
Indeed, this is why I would even say that, if you're going to allow
variants to be empty, you should therefore require all users to actually
handle the empty state. And that's why I prefer the never-empty guarantee;
that way, I get to decide if I want a variant to possibly be empty, and
therefore I get to decide whether I want to test for emptiness.
Remember: saying that you throw on an empty variant isn't really much
better. That means it is *possible* to get an empty variant. I would much
rather make it my choice whether it is possible for a variant to ever be
empty. I really don't like the idea of visitation functions that throw
exceptions internally.
Pay only for what you use.
>
>
> I couldn't agree more.
>
> Notice that I am not going into the details of how it should be
> implemented but rather on the intent and high level design of the class
> that will influence how the user will use it. For instance, I am not sure
> yet how the class will be able to determine if the visitor is providing a
> specific overload (maybe it will require some compiler support or maybe
> that sentence should be rephrased -- what I care for now is the intent).
>
But you can't separate implementation from intent. It's going to have to be
implemented at some point, in real systems. And, unless you intend to stick
`variant` in Chapter 17, it's not reasonable to define the requirements
such that an implementation would have to rely on compiler-specific
intrinsics. Most standard library stuff does not, and that's a *good thing*.
People ought to be able to drop in their own version of the standard
library and use it effectively, outside of a select few objects which are
intrinsic to C++.
A specification which cannot be implemented reasonably isn't terribly
useful. That's why the committee likes to standardize existing practice, or
at least *proven* practice from a proof-of-concept implementation.
Boost.Variant is already existing practice. If you're going to suggest
significant changes, you should prove those changes with an implementation
that works and is better in some respect.
Final note about the "expert"/"non-expert" argument.
>
> I can't seem to see how it would benefit "experts" to have the variant
> copy constructed to the original type (from/to alternate space) if a
> copy/move assignment fails. If the assignment fails, I might not need to
> use the variant anymore. So that copy that was made to/from alternate space
> would just be a waste.
>
Then again, they might need it. We don't throw away exception safety just
because someone might not use the object.
I personally think that an expert will want control over this; copying back
> to the original type seems an arbitrary choice to me. But we don't have to
> agree on this if you agree on what I first suggest...
>
But what you suggest breaks the never-empty 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/?hl=en.
------=_Part_6161_32666915.1367418059125
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 1, 2013 4:43:13 AM UTC-7, Alex B wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><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">Does it throw an exceptio=
n? Does it simply fail to call any visitation function? Does the user get t=
o have a particular operator() overload that is called on the "nullvar" sta=
te? If the latter is true, does <i>every</i> visitor class now ha=
ve to have this overload?</blockquote><div><br></div><div>How about throwin=
g if the variant is in a nullvar state and the visitor doesn't provide a nu=
llvar overload? That way, if you are sure that your variant is not nullvar,=
don't provide a nullvar overload. Otherwise, 2 choices: provide an overloa=
d or surround your call to apply visitor by a try-catch.</div></d=
iv><div><br></div><div>As I understand it, the problem that you are raising=
is that you don't want to penalize the user by forcing him to implement an=
overload taking a nullvar_t in every of his visitors. As I said, I would n=
ot force him to do so (but it would be an option).</div></blockquote><block=
quote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 2=
04, 204); padding-left: 1ex;" class=3D"gmail_quote"><div><br></div></blockq=
uote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div></div><div>I would p=
ush it even further. I would not force visitors to provide overloads for al=
l of the types. If visitor::operator() cannot be called for the current typ=
e of the variant, then just throw. Let's say that your variant contains 10 =
types. You *know* that in a specific context, the variant type should be on=
e of only 3 of these types. So why not allow the implementer of the visitor=
to only provide overloads for the 3 types that he expect? Just throw if th=
e provided overloads cannot accept the current type of the variant (includi=
ng nullvar_t).</div></blockquote><div><br>There's a good reason not to do t=
hat. One of the nice things about variants are that if you add new elements=
, you get a <i>compiler</i> error in every piece of code where you forgot h=
andle the new element. Not a runtime error that you may or may not ever hit=
, a compile-time error that you can't ignore.<br><br>Furthermore, if a user=
knows that it's only in one of three states, it's very easy for them to ha=
ndle the rest with a: `template<typename T> operator()(const T&) =
{}` overload. They could even `throw` if they want to. It also happens to m=
ake it clear that it's <i>not</i> a mistake for it to not handle the other =
alternatives; you're <i>explicitly</i> saying that you're doing nothing for=
them.<br><br>The Boost.Variant way, the user has choices: do they want the=
compiler error or a runtime error? I'd rather those choices be apparent an=
d within the visitor class itself, rather than having different visitation =
functions or whatever.<br><br>To allow a visitation function to throw based=
on the state of the variant goes against a significant part of the point o=
f using variants rather than something else.<br><br>Indeed, this is why I w=
ould even say that, if you're going to allow variants to be empty, you shou=
ld therefore require all users to actually handle the empty state. And that=
's why I prefer the never-empty guarantee; that way, I get to decide if I w=
ant a variant to possibly be empty, and therefore I get to decide whether I=
want to test for emptiness.<br><br>Remember: saying that you throw on an e=
mpty variant isn't really much better. That means it is <i>possible</i> to =
get an empty variant. I would much rather make it my choice whether it is p=
ossible for a variant to ever be empty. I really don't like the idea of vis=
itation functions that throw exceptions internally.<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></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">Pay only for=
what you use.</blockquote><div><br></div><div>I couldn't agree more.</div>=
<div><br></div><div>Notice that I am not going into the details of how it s=
hould be implemented but rather on the intent and high level design of the =
class that will influence how the user will use it. For instance, I am not =
sure yet how the class will be able to determine if the visitor is providin=
g a specific overload (maybe it will require some compiler support or maybe=
that sentence should be rephrased -- what I care for now is the intent).</=
div></blockquote><div><br>But you can't separate implementation from intent=
.. It's going to have to be implemented at some point, in real systems. And,=
unless you intend to stick `variant` in Chapter 17, it's not reasonable to=
define the requirements such that an implementation would have to rely on =
compiler-specific intrinsics. Most standard library stuff does not, and tha=
t's a <i>good thing</i>. People ought to be able to drop in their own versi=
on of the standard=20
library and use it effectively, outside of a select few objects which=20
are intrinsic to C++.<br><br>A specification which cannot be implemented re=
asonably isn't terribly useful. That's why the committee likes to standardi=
ze existing practice, or at least <i>proven</i> practice from a proof-of-co=
ncept implementation.<br><br>Boost.Variant is already existing practice. If=
you're going to suggest significant changes, you should prove those change=
s with an implementation that works and is better in some respect.<br><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>Final note about the=
"expert"/"non-expert" argument.</div><div><br></div><div>I can't seem to s=
ee how it would benefit "experts" to have the variant copy constructed to t=
he original type (from/to alternate space) if a copy/move assignment fails.=
If the assignment fails, I might not need to use the variant anymore. So t=
hat copy that was made to/from alternate space would just be a waste.</div>=
</blockquote><div><br>Then again, they might need it. We don't throw away e=
xception safety just because someone might not use the object.<br><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>I personally t=
hink that an expert will want control over this; copying back to the origin=
al type seems an arbitrary choice to me. But we don't have to agree on this=
if you agree on what I first suggest...<br></div></blockquote><div><br>But=
what you suggest breaks the never-empty 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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_6161_32666915.1367418059125--
.
Author: Alex B <devalexb@gmail.com>
Date: Wed, 1 May 2013 20:54:41 -0700 (PDT)
Raw View
------=_Part_29_18585113.1367466881323
Content-Type: text/plain; charset=ISO-8859-1
I see a lot to be discussed here (sorry for the long post).
> There's a good reason not to do that. One of the nice things about
> variants are that if you add new elements, you get a *compiler* error in
> every piece of code where you forgot handle the new element. Not a runtime
> error that you may or may not ever hit, a compile-time error that you can't
> ignore.
Ok.
Furthermore, if a user knows that it's only in one of three states, it's
> very easy for them to handle the rest with a: `template<typename T>
> operator()(const T&) {}` overload. They could even `throw` if they want to.
> It also happens to make it clear that it's *not* a mistake for it to not
> handle the other alternatives; you're *explicitly*saying that you're
> doing nothing for them.
There has to be a better way than having to redefine the same templated
overload all the time to handle the rest.
Let's forget about the nullvar/empty/blank state (for now).
Imagine that instead of the boost::static_visitor class (that visitors have
to derrive form), there would be a std::variant::visitor class (nested).
That class would take variadic template parameters that would represent all
the types from the variant that *need* to be supported by the visitor (and
those types need to be part of the variant). It will be easier to
illustrate this idea with some code (please don't take the design and names
chosen for granted; they are only provided to illustrate the intent):
template <class... Types>
class variant
{
// [...]
public:
template <class V, class... VTypes>
struct visitor
{
// Compile error if VTypes are not part of Types
// [...]
};
template <class V>
using complete_visitor = visitor<V, Types...>; // There might be a better
name for this
template <class V, class... VTypes>
void apply_visitor(const visitor<V, VTypes...>& v)
{
// Throw if the current type of the variant is not among VTypes
};
// [...]
};
using MyVariantType = variant<int, float, string, vector<int>, list<float>>;
struct MyCompleteVisitor : MyVariantType::complete_visitor
{
void operator()(int& i) const {}
void operator()(float& f) const {}
void operator()(string& s) const {}
void operator()(vector<int>& v) const {}
void operator()(list<float>& l) const {}
// If one of the types in MyVariantType changes or a new one is added,
// this visitor won't compile unless it is modified accordingly
};
struct MyVisitor : MyVariantType::visitor<float, string>
{
void operator()(float& f) const {} // Would not compile without this
overload
void operator()(string& s) const {} // Would not compile without this
overload
// Other overloads are not specified, so if the variant is of type int,
// vector<int> or list<float>, this visitor would throw when being applied
};
MyVariantType v{0}; // variant constructed as int
v.apply_visitor(MyCompleteVisitor{}); // does not throw
v.apply_visitor(MyVisitor{}); // throws
v = 0.0f;
v.apply_visitor(MyVisitor{}); // does not throw
So Boost users would get the same compile-time safety if they make their
visitors derive from std::variant<...>::complete_visitor instead of
boost::static_visitor.
For users who only care about some of the types, they would now have the
choice to only supply overloads for the types they care about.
Everybody wins.
Now how could we integrate nullvar in those visitors? That is another
question, but I'm sure it could be done. For example, just accept nullvar_t
as one of the types of variant::visitor to force the visitor to define an
overload taking a nullvar. Then we could have this defined in the variant
class:
template <class V>
using complete_visitor_with_nullvar = visitor<V, nullvar_t, Types...>; //
For sure we can find a better name for this...
But you can't separate implementation from intent. It's going to have to be
> implemented at some point, in real systems. And, unless you intend to stick
> `variant` in Chapter 17, it's not reasonable to define the requirements
> such that an implementation would have to rely on compiler-specific
> intrinsics. Most standard library stuff does not, and that's a *good thing
> *. People ought to be able to drop in their own version of the standard
> library and use it effectively, outside of a select few objects which are
> intrinsic to C++.
> A specification which cannot be implemented reasonably isn't terribly
> useful. That's why the committee likes to standardize existing practice, or
> at least *proven*practice from a proof-of-concept implementation.
> Boost.Variant is already existing practice. If you're going to suggest
> significant changes, you should prove those changes with an implementation
> that works and is better in some respect.
Do you really expect everyone here to bring an implementation to be able to
discuss?
Please remember that we are in a *discussion* forum. When I (and others)
throw out some ideas like this, I don't have a full proposal and all the
possible proofs in my hands right now and I think that is what should be
expected. If you only care about fully elaborated proposals and papers,
then you should skip this kind of thread. (but it would be sad because you
are bringing some valid concerns and clarifications about the ideas being
thrown)
Then again, they might need it.
How would I do it if I *don't* need it? Because the guarantee *has* a cost
and for performance I want to be able to avoid it. Ok, I could add
boost::blank as the first of my variant types. The thing is that it is not
possible to modify the variant declaration. Let's say there is a function
in a library taking a ref to a variant with specific types as a parameter
(but these types do not include boost::blank). Now I want to implement that
library function and inside of it I do a copy assignment from another
variant and I want to avoid the guarantee because I want it to be optimal.
It would not make sense to have to modify the library interface (adding
boost::blank as one of the types of the variant passed as a ref parameter)
just to accommodate the implementer.
We don't throw away exception safety just because someone might not use the
> object.
What do you mean exactly? Do you mean that you consider the nullvar state
to be unsafe? It would be a fully valid state (just like nullopt is a valid
state for optional).
But what you suggest breaks the never-empty guarantee.
Indeed, that's what I wish: to break that guarantee. For many reasons.
There might be some good reasons for this guarantee, but you cannot say
that it doesn't have its drawbacks. Personally (and many others), I find it
to be more trouble than anything so that's why we shouldn't take it for
granted.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_29_18585113.1367466881323
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>I see a lot to be discussed here (sorry for the long post).</div><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); borde=
r-left-style: solid; padding-left: 1ex;">There's a good reason not to do th=
at. One of the nice things about variants are that if you add new elements,=
you get a <i>compiler</i> error in every piece of code where you=
forgot handle the new element. Not a runtime error that you may or may not=
ever hit, a compile-time error that you can't ignore.</blockquote>Ok.<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;">Furthermore, if a user knows that it=
's only in one of three states, it's very easy for them to handle the rest =
with a: `template<typename T> operator()(const T&) {}` overload. =
They could even `throw` if they want to. It also happens to make it clear t=
hat it's <i>not</i> a mistake for it to not handle the other alte=
rnatives; you're <i>explicitly</i>saying that you're doing nothing for=
them.</blockquote><div>There has to be a better way than having to redefin=
e the same templated overload all the time to handle the rest.</div><div>Le=
t's forget about the nullvar/empty/blank state (for now).</div><div>Imagine=
that instead of the boost::static_visitor class (that visitors have to der=
rive form), there would be a std::variant::visitor class (nested). That cla=
ss would take variadic template parameters that would represent all the typ=
es from the variant that <b>need</b> to be supported by the visitor (a=
nd those types need to be part of the variant). It will be easier to illust=
rate this idea with some code (please don't take the design and names chose=
n for granted; they are only provided to illustrate the intent):<div><div><=
br></div><div style=3D"background-color: rgb(250, 250, 250); border: 1px so=
lid rgb(187, 187, 187); word-wrap: break-word;" class=3D"prettyprint"><code=
class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: =
#008;" class=3D"styled-by-prettify">template</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">class</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ty=
pes</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> variant<br></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: #800;" class=3D"styled-by-prettify">// [...]</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">public</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">template</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> V</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">...</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606=
;" class=3D"styled-by-prettify">VTypes</span><span style=3D"color: #660;" c=
lass=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">struct</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> visitor<br> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br> </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">// Compile error if VTypes are not part of Types</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><=
span style=3D"color: #800;" class=3D"styled-by-prettify">// [...]</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">template</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> V</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">using</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> complete_visitor </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> visitor</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">V</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: #606;" class=3D"styled-by-prettify">Types</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=
: #800;" class=3D"styled-by-prettify">// There might be a better name for t=
his</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br=
> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">tem=
plate</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> V</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">class</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">VTypes</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nb=
sp;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> apply_visito=
r</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"> visitor</span><span st=
yle=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">,</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"sty=
led-by-prettify">VTypes</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">...>&</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> v</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</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> <=
/span><span style=3D"color: #800;" class=3D"styled-by-prettify">// Throw if=
the current type of the variant is not among VTypes</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br> </span><span style=3D"color=
: #800;" 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"styled-by-prettify"><br><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">using</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">MyVariantType</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> va=
riant</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span 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: #008;" class=3D"styled-by-prettify">float</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">string</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> vector</span><span style=3D"color: #080;" class=3D"styled-by-prettify">=
<int></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> list</s=
pan><span style=3D"color: #080;" class=3D"styled-by-prettify"><float>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">MyCompleteVisitor</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #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">MyVariantType</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">complete_visitor<br></span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">void</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">int</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> i</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">operato=
r</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()(</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">float</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> f</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: #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: #000;" class=3D"styled-by-prettify=
"><br> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">operator</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">()(</span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">string</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> s</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: #008;" class=3D"st=
yled-by-prettify">const</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">void=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">()(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"=
color: #080;" class=3D"styled-by-prettify"><int></span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> v</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: #008;" class=3D"style=
d-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: #000;" class=3D"styled-by-prettify"><br>&nb=
sp;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">()(</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">list</span><span style=3D"color=
: #080;" class=3D"styled-by-prettify"><float></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> l</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">const</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>&nbs=
p;</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// If on=
e of the types in MyVariantType changes or a new one is added,</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">// this visitor won't c=
ompile unless it is modified accordingly</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"styl=
ed-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">MyV=
isitor</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </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: #606;" class=3D"styled-by-prettify">MyVariantType</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">visitor</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">float</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">string</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">></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"styled-by-prettify"><br> </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">()(</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">float</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> f</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">co=
nst</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #800;" class=3D"styled-by-prettify">// Would not compile without this=
overload</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">v=
oid</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 st=
yle=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> s</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-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: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">// Would not co=
mpile without this overload</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br><br> </span><span style=3D"color: #800;" class=3D=
"styled-by-prettify">// Other overloads are not specified, so if the varian=
t is of type int,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br> </span><span style=3D"color: #800;" class=3D"styled-by-pre=
ttify">// vector<int> or list<float>, this visitor would throw =
when being applied</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><b=
r></span><span style=3D"color: #606;" class=3D"styled-by-prettify">MyVarian=
tType</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> v</s=
pan><span style=3D"color: #660;" 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-by-prettify"> </span><span style=3D"color: #800;" cl=
ass=3D"styled-by-prettify">// variant constructed as int</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>v</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">apply_visitor</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">MyCompleteVisitor</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{});</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">// does not throw</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>v</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">apply_visitor</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">MyVisitor</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{});</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// throws<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>v </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #066;" class=3D"styled-by-prettify">0.0f</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>v</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">apply_visitor</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">MyVisitor</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: #800;" class=3D"styled-by-prettify">// does=
not throw</span></div></code></div><div><br></div></div><div>So Boost user=
s would get the same compile-time safety if they make their visitors derive=
from std::variant<...>::complete_visitor instead of boost::static_vi=
sitor.</div><div>For users who only care about some of the types, they woul=
d now have the choice to only supply overloads for the types they care abou=
t.</div><div>Everybody wins.</div><div><br></div><div>Now how could we inte=
grate nullvar in those visitors? That is another question, but I'm sure it =
could be done. For example, just accept nullvar_t as one of the types of va=
riant::visitor to force the visitor to define an overload taking a nullvar.=
Then we could have this defined in the variant class:</div><div><div style=
=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 1=
87); word-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">template</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">clas=
s</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> V</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"> complete_visitor_with_nullv=
ar </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> visitor</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">,</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> nullvar_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: #606;" class=3D"sty=
led-by-prettify">Types</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">...>;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>// For sure we can find a better name for this...</span></div></code></div=
></div><div><br></div><div><br></div><blockquote class=3D"gmail_quote" styl=
e=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;">But you c=
an't separate implementation from intent. It's going to have to be implemen=
ted at some point, in real systems. And, unless you intend to stick `varian=
t` in Chapter 17, it's not reasonable to define the requirements such that =
an implementation would have to rely on compiler-specific intrinsics. Most =
standard library stuff does not, and that's a <i>good thing</i>. Peopl=
e ought to be able to drop in their own version of the standard library and=
use it effectively, outside of a select few objects which are intrinsic to=
C++.<br>A specification which cannot be implemented reasonably isn't terri=
bly useful. That's why the committee likes to standardize existing practice=
, or at least <i>proven</i>practice from a proof-of-concept implementa=
tion.<br>Boost.Variant is already existing practice. If you're going to sug=
gest significant changes, you should prove those changes with an implementa=
tion that works and is better in some respect.</blockquote><div>Do you real=
ly expect everyone here to bring an implementation to be able to discuss?</=
div><div>Please remember that we are in a <b>discussion</b> forum. When I (=
and others) throw out some ideas like this, I don't have a full proposal an=
d all the possible proofs in my hands right now and I think that is what sh=
ould be expected. If you only care about fully elaborated proposals and pap=
ers, then you should skip this kind of thread. (but it would be sad because=
you are bringing some valid concerns and clarifications about the ideas be=
ing thrown)</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(2=
04, 204, 204); border-left-style: solid; padding-left: 1ex;">Then again, th=
ey might need it.</blockquote><div>How would I do it if I <i>don't</i> =
;need it? Because the guarantee <u style=3D"font-weight: bold;">h=
as</u> a cost and for performance I want to be able to avoid it. =
Ok, I could add boost::blank as the first of my variant types. The thing is=
that it is not possible to modify the variant declaration. Let's say there=
is a function in a library taking a ref to a variant with specific types a=
s a parameter (but these types do not include boost::blank). Now I want to =
implement that library function and inside of it I do a copy assignment fro=
m another variant and I want to avoid the guarantee because I want it to be=
optimal. It would not make sense to have to modify the library interface (=
adding boost::blank as one of the types of the variant passed as a ref para=
meter) just to accommodate the implementer.</div></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;">We don't throw away exception safety just=
because someone might not use the object.</blockquote><div>What do you mea=
n exactly? Do you mean that you consider the nullvar state to be unsafe? It=
would be a fully valid state (just like nullopt is a valid state for =
optional).</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(20=
4, 204, 204); border-left-style: solid; padding-left: 1ex;">But what you su=
ggest breaks the never-empty guarantee.</blockquote><div>Indeed, that's wha=
t I wish: to break that guarantee. For many reasons. There might be some go=
od reasons for this guarantee, but you cannot say that it doesn't have its =
drawbacks. Personally (and many others), I find it to be more trouble =
than anything so that's why we shouldn't take it for granted.</div><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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_29_18585113.1367466881323--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 1 May 2013 21:19:47 -0700 (PDT)
Raw View
------=_Part_6280_28841402.1367468387555
Content-Type: text/plain; charset=ISO-8859-1
On Wednesday, May 1, 2013 8:54:41 PM UTC-7, Alex B wrote:
>
> I see a lot to be discussed here (sorry for the long post).
>
>
>> There's a good reason not to do that. One of the nice things about
>> variants are that if you add new elements, you get a *compiler* error in
>> every piece of code where you forgot handle the new element. Not a runtime
>> error that you may or may not ever hit, a compile-time error that you can't
>> ignore.
>
> Ok.
>
> Furthermore, if a user knows that it's only in one of three states, it's
>> very easy for them to handle the rest with a: `template<typename T>
>> operator()(const T&) {}` overload. They could even `throw` if they want to.
>> It also happens to make it clear that it's *not* a mistake for it to not
>> handle the other alternatives; you're *explicitly*saying that you're
>> doing nothing for them.
>
> There has to be a better way than having to redefine the same templated
> overload all the time to handle the rest.
> Let's forget about the nullvar/empty/blank state (for now).
> Imagine that instead of the boost::static_visitor class (that visitors
> have to derrive form), there would be a std::variant::visitor class
> (nested). That class would take variadic template parameters that would
> represent all the types from the variant that *need* to be supported by
> the visitor (and those types need to be part of the variant). It will be
> easier to illustrate this idea with some code (please don't take the design
> and names chosen for granted; they are only provided to illustrate the
> intent):
>
> template <class... Types>
> class variant
> {
> // [...]
> public:
> template <class V, class... VTypes>
> struct visitor
> {
> // Compile error if VTypes are not part of Types
> // [...]
> };
>
> template <class V>
> using complete_visitor = visitor<V, Types...>; // There might be a
> better name for this
>
> template <class V, class... VTypes>
> void apply_visitor(const visitor<V, VTypes...>& v)
> {
> // Throw if the current type of the variant is not among VTypes
> };
>
> // [...]
> };
>
> using MyVariantType = variant<int, float, string, vector<int>, list<float>
> >;
> struct MyCompleteVisitor : MyVariantType::complete_visitor
> {
> void operator()(int& i) const {}
> void operator()(float& f) const {}
> void operator()(string& s) const {}
> void operator()(vector<int>& v) const {}
> void operator()(list<float>& l) const {}
>
> // If one of the types in MyVariantType changes or a new one is added,
> // this visitor won't compile unless it is modified accordingly
> };
> struct MyVisitor : MyVariantType::visitor<float, string>
> {
> void operator()(float& f) const {} // Would not compile without this
> overload
> void operator()(string& s) const {} // Would not compile without this
> overload
>
> // Other overloads are not specified, so if the variant is of type int,
> // vector<int> or list<float>, this visitor would throw when being
> applied
> };
>
> MyVariantType v{0}; // variant constructed as int
> v.apply_visitor(MyCompleteVisitor{}); // does not throw
> v.apply_visitor(MyVisitor{}); // throws
> v = 0.0f;
> v.apply_visitor(MyVisitor{}); // does not throw
>
> So Boost users would get the same compile-time safety if they make their
> visitors derive from std::variant<...>::complete_visitor instead of
> boost::static_visitor.
> For users who only care about some of the types, they would now have the
> choice to only supply overloads for the types they care about.
> Everybody wins.
>
Not really. The common case for a variant is to check all of the
possibilities. That is, the common case is that it is user error to miss
checking one of the elements. The way you're proposing means that I have to
expend a lot of effort in order to handle that common case.
Plus, it inextricably links the visitor to the variant that uses it. Is
that dependency *necessary*? Why does the visitation code need to have the
variant definition? It also means that it's much more difficult to use a
visitor with different variant types. Is there a reason that this should be
so difficult to handle?
This is a lot to give up just to avoid writing a quick template operator()
if you don't want to handle all of the cases.
Also, there *is* a simpler way than redefining the template operator(), if
you're really lazy:
template<typename Ret>struct no_error_visitor : public boost:static_visitor<
Ret>
{
template<typename T> Ret operator() (const T &) {return Ret();}
};
template<> struct no_error_visitor<void> : public boost::static_visitor<>
{
template<typename T> void operator() {const T&) {}
};
Derive all of your visitors from that. See? Problem solved. You can even
make a throwing one.
The default case should push errors as close to compile-time as possible.
If the user wants to say that they want runtime errors, or just to
transparently handle everything else, they have the tools to do that
easily. But by default, we should require the user to write proper,
fully-qualified visitors.
> Now how could we integrate nullvar in those visitors? That is another
> question, but I'm sure it could be done. For example, just accept nullvar_t
> as one of the types of variant::visitor to force the visitor to define an
> overload taking a nullvar. Then we could have this defined in the variant
> class:
> template <class V>
> using complete_visitor_with_nullvar = visitor<V, nullvar_t, Types...>; //
> For sure we can find a better name for this...
>
>
> But you can't separate implementation from intent. It's going to have to
>> be implemented at some point, in real systems. And, unless you intend to
>> stick `variant` in Chapter 17, it's not reasonable to define the
>> requirements such that an implementation would have to rely on
>> compiler-specific intrinsics. Most standard library stuff does not, and
>> that's a *good thing*. People ought to be able to drop in their own
>> version of the standard library and use it effectively, outside of a select
>> few objects which are intrinsic to C++.
>> A specification which cannot be implemented reasonably isn't terribly
>> useful. That's why the committee likes to standardize existing practice, or
>> at least *proven*practice from a proof-of-concept implementation.
>> Boost.Variant is already existing practice. If you're going to suggest
>> significant changes, you should prove those changes with an implementation
>> that works and is better in some respect.
>
> Do you really expect everyone here to bring an implementation to be able
> to discuss?
>
No, but if you're going to argue against the Boost version, it wouldn't
hurt. You're basically saying, "I want X and we'll figure out how to
implement it later." That's fine and all, but what good is wanting it if it
can't be done?
Please remember that we are in a *discussion* forum. When I (and others)
> throw out some ideas like this, I don't have a full proposal and all the
> possible proofs in my hands right now and I think that is what should be
> expected. If you only care about fully elaborated proposals and papers,
> then you should skip this kind of thread. (but it would be sad because you
> are bringing some valid concerns and clarifications about the ideas being
> thrown)
>
But what you suggest breaks the never-empty guarantee.
>
> Indeed, that's what I wish: to break that guarantee. For many reasons.
> There might be some good reasons for this guarantee, but you cannot say
> that it doesn't have its drawbacks. Personally (and many others), I find it
> to be more trouble than anything so that's why we shouldn't take it for
> granted.
>
That's great. The wonderful thing about the Boost version is that you can
avoid all of those drawbacks easily enough, just by putting an explicit
"empty" state into the variant. See? The copying won't allocate memory; if
a copy constructor throws, it will go to the blank state. Boost.Variant *
guarantees* this.
So explain why *everyone* should be forced to handle empty variants?
Boost.Variant gives you everything you ask for (except for the fact that
you have to actually handle the empty case. But I consider that a *good*thing over throwing exceptions). So... what's the problem?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_6280_28841402.1367468387555
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Wednesday, May 1, 2013 8:54:41 PM UTC-7, Alex B wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div>I see a lot to be discussed here (s=
orry for the long post).</div><div> </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">There's a g=
ood reason not to do that. One of the nice things about variants are that i=
f you add new elements, you get a <i>compiler</i> error in every =
piece of code where you forgot handle the new element. Not a runtime error =
that you may or may not ever hit, a compile-time error that you can't ignor=
e.</blockquote>Ok.<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,2=
04,204);border-left-style:solid;padding-left:1ex">Furthermore, if a user kn=
ows that it's only in one of three states, it's very easy for them to handl=
e the rest with a: `template<typename T> operator()(const T&) {}`=
overload. They could even `throw` if they want to. It also happens to make=
it clear that it's <i>not</i> a mistake for it to not handle the=
other alternatives; you're <i>explicitly</i>saying that you're doing =
nothing for them.</blockquote><div>There has to be a better way than having=
to redefine the same templated overload all the time to handle the rest.</=
div><div>Let's forget about the nullvar/empty/blank state (for now).</div><=
div>Imagine that instead of the boost::static_visitor class (that visitors =
have to derrive form), there would be a std::variant::visitor class (nested=
). That class would take variadic template parameters that would represent =
all the types from the variant that <b>need</b> to be supported by the=
visitor (and those types need to be part of the variant). It will be easie=
r to illustrate this idea with some code (please don't take the design and =
names chosen for granted; they are only provided to illustrate the intent):=
<div><div><br></div><div style=3D"background-color:rgb(250,250,250);border:=
1px solid rgb(187,187,187);word-wrap:break-word"><code><div><span style=3D"=
color:#008">template</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660"><</span><span style=3D"color:#008">class</span><span sty=
le=3D"color:#660">...</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Types</span><span style=3D"color:#660">></span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#008">class</span><span s=
tyle=3D"color:#000"> variant<br></span><span style=3D"color:#660">{</span><=
span style=3D"color:#000"><br> </span><span style=3D"color:#800">// [.=
...]</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
public</span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
<br> </span><span style=3D"color:#008">template</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660"><</span><span style=3D"col=
or:#008">class</span><span style=3D"color:#000"> V</span><span style=3D"col=
or:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">class</span><span style=3D"color:#660">...</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">VTypes</span><span style=3D"color:#=
660">></span><span style=3D"color:#000"><br> </span><span style=3D"=
color:#008">struct</span><span style=3D"color:#000"> visitor<br> </spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000"><br> <=
/span><span style=3D"color:#800">// Compile error if VTypes are not part of=
Types</span><span style=3D"color:#000"><br> </span><span style=3D"col=
or:#800">// [...]</span><span style=3D"color:#000"><br> </span><span s=
tyle=3D"color:#660">};</span><span style=3D"color:#000"><br><br> </spa=
n><span style=3D"color:#008">template</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660"><</span><span style=3D"color:#008">class<=
/span><span style=3D"color:#000"> V</span><span style=3D"color:#660">></=
span><span style=3D"color:#000"><br> </span><span style=3D"color:#008"=
>using</span><span style=3D"color:#000"> complete_visitor </span><span styl=
e=3D"color:#660">=3D</span><span style=3D"color:#000"> visitor</span><span =
style=3D"color:#660"><</span><span style=3D"color:#000">V</span><span st=
yle=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Types</span><span style=3D"color:#660">...>;</span><span=
style=3D"color:#000"> </span><span style=3D"color:#800">// There might be =
a better name for this</span><span style=3D"color:#000"><br><br> </spa=
n><span style=3D"color:#008">template</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660"><</span><span style=3D"color:#008">class<=
/span><span style=3D"color:#000"> V</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">class</span=
><span style=3D"color:#660">...</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#606">VTypes</span><span style=3D"color:#660">></span=
><span style=3D"color:#000"><br> </span><span style=3D"color:#008">voi=
d</span><span style=3D"color:#000"> apply_visitor</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#008">const</span><span style=3D"color=
:#000"> visitor</span><span style=3D"color:#660"><</span><span style=3D"=
color:#000">V</span><span style=3D"color:#660">,</span><span style=3D"color=
:#000"> </span><span style=3D"color:#606">VTypes</span><span style=3D"color=
:#660">...>&</span><span style=3D"color:#000"> v</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"><br> </span><span s=
tyle=3D"color:#660">{</span><span style=3D"color:#000"><br> </span><sp=
an style=3D"color:#800">// Throw if the current type of the variant is not =
among VTypes</span><span style=3D"color:#000"><br> </span><span style=
=3D"color:#660">};</span><span style=3D"color:#000"><br><br> </span><s=
pan style=3D"color:#800">// [...]</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">};</span><span style=3D"color:#000"><br><br><=
/span><span style=3D"color:#008">using</span><span style=3D"color:#000"> </=
span><span style=3D"color:#606">MyVariantType</span><span style=3D"color:#0=
00"> </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:=
#008">int</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">float</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">str=
ing</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> ve=
ctor</span><span style=3D"color:#080"><int></span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> list</span><span style=3D"color=
:#080"><float></span><span style=3D"color:#660">>;</span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#008">struct</span><span =
style=3D"color:#000"> </span><span style=3D"color:#606">MyCompleteVisitor</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">:</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">MyVariantType=
</span><span style=3D"color:#660">::</span><span style=3D"color:#000">compl=
ete_<wbr>visitor<br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br> </span><span style=3D"color:#008">void</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">operator</span><s=
pan style=3D"color:#660">()(</span><span style=3D"color:#008">int</span><sp=
an style=3D"color:#660">&</span><span style=3D"color:#000"> i</span><sp=
an style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">const</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">{}</span><span style=3D"color:#000"><br> </span><spa=
n style=3D"color:#008">void</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">operator</span><span style=3D"color:#660">()(</span><s=
pan style=3D"color:#008">float</span><span style=3D"color:#660">&</span=
><span style=3D"color:#000"> f</span><span style=3D"color:#660">)</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">const</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span st=
yle=3D"color:#000"><br> </span><span style=3D"color:#008">void</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">string</sp=
an><span style=3D"color:#660">&</span><span style=3D"color:#000"> s</sp=
an><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#008">const</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#660">{}</span><span style=3D"color:#000"><br> </spa=
n><span style=3D"color:#008">void</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">operator</span><span style=3D"color:#660">()(</s=
pan><span style=3D"color:#000">vector</span><span style=3D"color:#080"><=
int></span><span style=3D"color:#660">&</span><span style=3D"color:#=
000"> v</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 style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008">void</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">operator</span><span style=3D"color:#=
660">()(</span><span style=3D"color:#000">list</span><span style=3D"color:#=
080"><float></span><span style=3D"color:#660">&</span><span style=
=3D"color:#000"> l</span><span style=3D"color:#660">)</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">const</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"color=
:#000"><br><br> </span><span style=3D"color:#800">// If one of the typ=
es in MyVariantType changes or a new one is added,</span><span style=3D"col=
or:#000"><br> </span><span style=3D"color:#800">// this visitor won't =
compile unless it is modified accordingly</span><span style=3D"color:#000">=
<br></span><span style=3D"color:#660">};</span><span style=3D"color:#000"><=
br></span><span style=3D"color:#008">struct</span><span style=3D"color:#000=
"> </span><span style=3D"color:#606">MyVisitor</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
</span><span style=3D"color:#606">MyVariantType</span><span style=3D"color=
:#660">::</span><span style=3D"color:#000">visitor</span><span style=3D"col=
or:#660"><</span><span style=3D"color:#008">float</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:=
#008">string</span><span style=3D"color:#660">></span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"color=
:#000"><br> </span><span style=3D"color:#008">void</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">operator</span><span sty=
le=3D"color:#660">()(</span><span style=3D"color:#008">float</span><span st=
yle=3D"color:#660">&</span><span style=3D"color:#000"> f</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">const</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{}</span><span style=3D"color:#000"> </span><span style=3D"=
color:#800">// Would not compile without this overload</span><span style=3D=
"color:#000"><br> </span><span style=3D"color:#008">void</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#008">operator</span><span=
style=3D"color:#660">()(</span><span style=3D"color:#008">string</span><sp=
an style=3D"color:#660">&</span><span style=3D"color:#000"> s</span><sp=
an style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">const</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">{}</span><span style=3D"color:#000"> </span><span style=
=3D"color:#800">// Would not compile without this overload</span><span styl=
e=3D"color:#000"><br><br> </span><span style=3D"color:#800">// Other o=
verloads are not specified, so if the variant is of type int,</span><span s=
tyle=3D"color:#000"><br> </span><span style=3D"color:#800">// vector&l=
t;int> or list<float>, this visitor would throw when being applied=
</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">};<=
/span><span style=3D"color:#000"><br><br></span><span style=3D"color:#606">=
MyVariantType</span><span style=3D"color:#000"> v</span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#066">0</span><span style=3D"color:#66=
0">};</span><span style=3D"color:#000"> </span><span style=3D"color:#800">/=
/ variant constructed as int</span><span style=3D"color:#000"><br>v</span><=
span style=3D"color:#660">.</span><span style=3D"color:#000">apply_visitor<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#606">MyCompl=
eteVisi<wbr>tor</span><span style=3D"color:#660">{});</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">// does not throw</span><spa=
n style=3D"color:#000"><br>v</span><span style=3D"color:#660">.</span><span=
style=3D"color:#000">apply_visitor</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#606">MyVisitor</span><span style=3D"color:#660">{})=
;</span><span style=3D"color:#000"> </span><span style=3D"color:#800">// th=
rows</span><span style=3D"color:#000"><br>v </span><span style=3D"color:#66=
0">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#066">=
0.0f</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><b=
r>v</span><span style=3D"color:#660">.</span><span style=3D"color:#000">app=
ly_visitor</span><span style=3D"color:#660">(</span><span style=3D"color:#6=
06">MyVisitor</span><span style=3D"color:#660">{});</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#800">// does not throw</span></div>=
</code></div><div><br></div></div><div>So Boost users would get the same co=
mpile-time safety if they make their visitors derive from std::variant<.=
...>::complete_<wbr>visitor instead of boost::static_visitor.</div><div>F=
or users who only care about some of the types, they would now have the cho=
ice to only supply overloads for the types they care about.</div><div>Every=
body wins.</div></div></blockquote><div><br>Not really. The common case for=
a variant is to check all of the possibilities. That is, the common case i=
s that it is user error to miss checking one of the elements. The way you'r=
e proposing means that I have to expend a lot of effort in order to handle =
that common case.<br><br>Plus, it inextricably links the visitor to the var=
iant that uses it. Is that dependency <i>necessary</i>? Why does the visita=
tion code need to have the variant definition? It also means that it's much=
more difficult to use a visitor with different variant types. Is there a r=
eason that this should be so difficult to handle?<br><br>This is a lot to g=
ive up just to avoid writing a quick template operator() if you don't want =
to handle all of the cases.<br><br>Also, there <i>is</i> a simpler way than=
redefining the template operator(), if you're really lazy:<br><br><div cla=
ss=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-co=
lor: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap:=
break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">template</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Ret</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">></span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> no_error_visitor </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: #008;" class=3D"styled-by=
-prettify">public</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> boost</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">static=
_visitor</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&l=
t;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ret</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">></span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">template</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">typename</span><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"st=
yled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Ret</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">operato=
r</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> T </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ret</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">();}</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><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">template</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: #008;" cla=
ss=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> no_error_visitor</span><span style=3D"color: #080;=
" class=3D"styled-by-prettify"><void></span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </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: #008;" class=3D"styled-by-pret=
tify">public</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> boost</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">static_vis=
itor</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><&g=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><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">template</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"colo=
r: #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">void</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">operator</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">&)</span><span style=3D"colo=
r: #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"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span></div></code></div><br>Derive all of your visitors fro=
m that. See? Problem solved. You can even make a throwing one.<br><br>The d=
efault case should push errors as close to compile-time as possible. If the=
user wants to say that they want runtime errors, or just to transparently =
handle everything else, they have the tools to do that easily. But by defau=
lt, we should require the user to write proper, fully-qualified visitors.<b=
r><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=
v></div><div>Now how could we integrate nullvar in those visitors? That is =
another question, but I'm sure it could be done. For example, just accept n=
ullvar_t as one of the types of variant::visitor to force the visitor to de=
fine an overload taking a nullvar. Then we could have this defined in the v=
ariant class:</div><div><div style=3D"background-color:rgb(250,250,250);bor=
der:1px solid rgb(187,187,187);word-wrap:break-word"><code><div><span style=
=3D"color:#000"> </span><span style=3D"color:#008">template</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660"><</span><span =
style=3D"color:#008">class</span><span style=3D"color:#000"> V</span><span =
style=3D"color:#660">></span><span style=3D"color:#000"><br> </span=
><span style=3D"color:#008">using</span><span style=3D"color:#000"> complet=
e_visitor_with_nullvar </span><span style=3D"color:#660">=3D</span><span st=
yle=3D"color:#000"> visitor</span><span style=3D"color:#660"><</span><sp=
an style=3D"color:#000">V</span><span style=3D"color:#660">,</span><span st=
yle=3D"color:#000"> nullvar_t</span><span style=3D"color:#660">,</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Types</span><span=
style=3D"color:#660">...>;</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#800">// For sure we can find a better name for this...</=
span></div></code></div></div><div><br></div><div><br></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=
">But you can't separate implementation from intent. It's going to have to =
be implemented at some point, in real systems. And, unless you intend to st=
ick `variant` in Chapter 17, it's not reasonable to define the requirements=
such that an implementation would have to rely on compiler-specific intrin=
sics. Most standard library stuff does not, and that's a <i>good thing=
</i>. People ought to be able to drop in their own version of the standard =
library and use it effectively, outside of a select few objects which are i=
ntrinsic to C++.<br>A specification which cannot be implemented reasonably =
isn't terribly useful. That's why the committee likes to standardize existi=
ng practice, or at least <i>proven</i>practice from a proof-of-concept=
implementation.<br>Boost.Variant is already existing practice. If you're g=
oing to suggest significant changes, you should prove those changes with an=
implementation that works and is better in some respect.</blockquote><div>=
Do you really expect everyone here to bring an implementation to be able to=
discuss?</div></div></blockquote><div><br>No, but if you're going to argue=
against the Boost version, it wouldn't hurt. You're basically saying, "I w=
ant X and we'll figure out how to implement it later." That's fine and all,=
but what good is wanting it if it can't be done?<br><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div><div>Please remember that we are in a=
<b>discussion</b> forum. When I (and others) throw out some ideas like thi=
s, I don't have a full proposal and all the possible proofs in my hands rig=
ht now and I think that is what should be expected. If you only care about =
fully elaborated proposals and papers, then you should skip this kind of th=
read. (but it would be sad because you are bringing some valid concerns and=
clarifications about the ideas being thrown)</div></div></blockquote><br><=
br><br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><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">But wh=
at you suggest breaks the never-empty guarantee.</blockquote><div>Indeed, t=
hat's what I wish: to break that guarantee. For many reasons. There might b=
e some good reasons for this guarantee, but you cannot say that it doesn't =
have its drawbacks. Personally (and many others), I find it to be more=
trouble than anything so that's why we shouldn't take it for granted.</div=
></blockquote><div><br>That's great. The wonderful thing about the Boost ve=
rsion is that you can avoid all of those drawbacks easily enough, just by p=
utting an explicit "empty" state into the variant. See? The copying won't a=
llocate memory; if a copy constructor throws, it will go to the blank state=
.. Boost.Variant <i>guarantees</i> this.<br><br>So explain why <i>everyone</=
i> should be forced to handle empty variants? Boost.Variant gives you every=
thing you ask for (except for the fact that you have to actually handle the=
empty case. But I consider that a <i>good</i> thing over throwing exceptio=
ns). So... what's the problem?<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_6280_28841402.1367468387555--
.
Author: Alex B <devalexb@gmail.com>
Date: Thu, 2 May 2013 03:48:00 -0700 (PDT)
Raw View
------=_Part_179_5136679.1367491680297
Content-Type: text/plain; charset=ISO-8859-1
>
> Not really. The common case for a variant is to check all of the
> possibilities. That is, the common case is that it is user error to miss
> checking one of the elements. The way you're proposing means that I have to
> expend a lot of effort in order to handle that common case.
Yes. If you use variant::complete_visitor, you *have *the same
error-checking as boost::static_visitor. So if that's what you want, I
don't have any problem with it being *your* default.
Plus, it inextricably links the visitor to the variant that uses it. Is
> that dependency *necessary*? Why does the visitation code need to have
> the variant definition? It also means that it's much more difficult to use
> a visitor with different variant types. Is there a reason that this should
> be so difficult to handle?
I see what you mean. There might be a different way to do it that would
avoid it. I think it will work if I make the visitor class not a nested
class of variant (put it in namespace scope) and perform the check to
verify that the visitor types are all part of the variant types on the call
to apply_visitor (at compile-time). Let me think about it.
Also, there *is* a simpler way than redefining the template operator(), if
> you're really lazy:
> template<typename Ret>struct no_error_visitor : public boost:
> static_visitor<Ret>
> {
> template<typename T> Ret operator() (const T &) {return Ret();}
> };
> template<> struct no_error_visitor<void> : public boost::static_visitor<>
> {
> template<typename T> void operator() {const T&) {}
> };
> Derive all of your visitors from that. See? Problem solved. You can even
> make a throwing one.
The problem with doing this is that it won't perform any compile-time
checks; visitors will always compile because of the templated overload.
With the visitor class I'm proposing, you explicitely define what types
should be implemented by the visitor so that the compile-check could be
done. If I have a visitor<A, B> my code will not compile if I don't provide
overloads taking types A and B.
The default case should push errors as close to compile-time as possible.
> If the user wants to say that they want runtime errors, or just to
> transparently handle everything else, they have the tools to do that
> easily. But by default, we should require the user to write proper,
> fully-qualified visitors.
As I said, just use complete_visitor as your default and you will get all
those compile-time checks.
That's great. The wonderful thing about the Boost version is that you can
> avoid all of those drawbacks easily enough, just by putting an explicit
> "empty" state into the variant. See? The copying won't allocate memory; if
> a copy constructor throws, it will go to the blank state. Boost.Variant *
> guarantees* this.
> So explain why *everyone* should be forced to handle empty variants?
> Boost.Variant gives you everything you ask for (except for the fact that
> you have to actually handle the empty case. But I consider that a *good* thing
> over throwing exceptions). So... what's the problem?
The problem, I explained it in my previous post: most of the time it is *not
* possible to add an explicit empty state. Let me cite what I wrote:
I could add boost::blank as the first of my variant types. The thing is
> that it is not possible to modify the variant declaration. Let's say there
> is a function in a library taking a ref to a variant with specific types as
> a parameter (but these types do not include boost::blank). Now I want to
> implement that library function and inside of it I do a copy assignment
> from another variant and I want to avoid the guarantee because I want it to
> be optimal. It would not make sense to have to modify the library interface
> (adding boost::blank as one of the types of the variant passed as a ref
> parameter) just to accommodate the implementer.
To make it shorter, it doesn't make sens to me to change the types of my
variant (which could be used all over my code) just to be able, at a
specific place in code, to avoid the cost of the guarantee (if I don't need
it in that place in 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/?hl=en.
------=_Part_179_5136679.1367491680297
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<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;">Not really. The common case for a variant is t=
o check all of the possibilities. That is, the common case is that it is us=
er error to miss checking one of the elements. The way you're proposing mea=
ns that I have to expend a lot of effort in order to handle that common cas=
e.</blockquote><div><br></div><div>Yes. If you use variant::complete_visito=
r, you <b>have </b>the same error-checking as boost::static_visitor. So if =
that's what you want, I don't have any problem with it being <i>your</i>&nb=
sp;default.</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(2=
04, 204, 204); border-left-style: solid; padding-left: 1ex;">Plus, it inext=
ricably links the visitor to the variant that uses it. Is that dependency&n=
bsp;<i>necessary</i>? Why does the visitation code need to have the variant=
definition? It also means that it's much more difficult to use a visitor w=
ith different variant types. Is there a reason that this should be so diffi=
cult to handle?</blockquote><div><br></div><div>I see what you mean. There =
might be a different way to do it that would avoid it. I think it will work=
if I make the visitor class not a nested class of variant (put it in names=
pace scope) and perform the check to verify that the visitor types are all =
part of the variant types on the call to apply_visitor (at compile-time). L=
et me think about it.</div><div><br></div><blockquote class=3D"gmail_quote"=
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;">Also=
, there <i>is</i> a simpler way than redefining the template oper=
ator(), if you're really lazy:<br><code><span style=3D"color: rgb(0, 0, 136=
);">template</span><span style=3D"color: rgb(102, 102, 0);"><</span><spa=
n style=3D"color: rgb(0, 0, 136);">typename</span><span style=3D"color: rgb=
(0, 0, 0);"> </span><span style=3D"color: rgb(102, 0, 102);">Ret</span=
><span style=3D"color: rgb(102, 102, 0);">></span><span style=3D"color: =
rgb(0, 0, 136);">struct</span><span style=3D"color: rgb(0, 0, 0);"> no=
_error_visitor </span><span style=3D"color: rgb(102, 102, 0);">:</span=
><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rg=
b(0, 0, 136);">public</span><span style=3D"color: rgb(0, 0, 0);"> boos=
t</span><span style=3D"color: rgb(102, 102, 0);">:</span><span style=3D"col=
or: rgb(0, 0, 0);">static_visitor</span><span style=3D"color: rgb(102, 102,=
0);"><</span><span style=3D"color: rgb(102, 0, 102);">Ret</span><span s=
tyle=3D"color: rgb(102, 102, 0);">><br></span></code><code><span style=
=3D"color: rgb(102, 102, 0);">{<br></span></code><code><span style=3D"color=
: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(0, 0, 136);">=
template</span><span style=3D"color: rgb(102, 102, 0);"><</span><span st=
yle=3D"color: rgb(0, 0, 136);">typename</span><span style=3D"color: rgb(0, =
0, 0);"> T</span><span style=3D"color: rgb(102, 102, 0);">></span><=
span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(=
102, 0, 102);">Ret</span><span style=3D"color: rgb(0, 0, 0);"> </span>=
<span style=3D"color: rgb(0, 0, 136);">operator</span><span style=3D"color:=
rgb(102, 102, 0);">()</span><span style=3D"color: rgb(0, 0, 0);"> </s=
pan><span style=3D"color: rgb(102, 102, 0);">(</span><span style=3D"color: =
rgb(0, 0, 136);">const</span><span style=3D"color: rgb(0, 0, 0);"> T&n=
bsp;</span><span style=3D"color: rgb(102, 102, 0);">&)</span><span styl=
e=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102,=
0);">{</span><span style=3D"color: rgb(0, 0, 136);">return</span><span sty=
le=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 0, =
102);">Ret</span><span style=3D"color: rgb(102, 102, 0);">();}<br></span></=
code><code><span style=3D"color: rgb(102, 102, 0);">};</span></code><code><=
span style=3D"color: rgb(0, 0, 0);"><br></span></code><code><span style=3D"=
color: rgb(0, 0, 136);">template</span><span style=3D"color: rgb(102, 102, =
0);"><></span><span style=3D"color: rgb(0, 0, 0);"> </span><span=
style=3D"color: rgb(0, 0, 136);">struct</span><span style=3D"color: rgb(0,=
0, 0);"> no_error_visitor</span><span style=3D"color: rgb(0, 136, 0);=
"><void></span><span style=3D"color: rgb(0, 0, 0);"> </span><spa=
n style=3D"color: rgb(102, 102, 0);">:</span><span style=3D"color: rgb(0, 0=
, 0);"> </span><span style=3D"color: rgb(0, 0, 136);">public</span><sp=
an style=3D"color: rgb(0, 0, 0);"> boost</span><span style=3D"color: r=
gb(102, 102, 0);">::</span><span style=3D"color: rgb(0, 0, 0);">static_visi=
tor</span><span style=3D"color: rgb(102, 102, 0);"><><br></span></cod=
e><code><span style=3D"color: rgb(102, 102, 0);">{<br></span></code><code><=
span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color=
: rgb(0, 0, 136);">template</span><span style=3D"color: rgb(102, 102, 0);">=
<</span><span style=3D"color: rgb(0, 0, 136);">typename</span><span styl=
e=3D"color: rgb(0, 0, 0);"> T</span><span style=3D"color: rgb(102, 102=
, 0);">></span><span style=3D"color: rgb(0, 0, 0);"> </span><span s=
tyle=3D"color: rgb(0, 0, 136);">void</span><span style=3D"color: rgb(0, 0, =
0);"> </span><span style=3D"color: rgb(0, 0, 136);">operator</span><sp=
an style=3D"color: rgb(102, 102, 0);">()</span><span style=3D"color: rgb(0,=
0, 0);"> </span><span style=3D"color: rgb(102, 102, 0);">{</span><spa=
n style=3D"color: rgb(0, 0, 136);">const</span><span style=3D"color: rgb(0,=
0, 0);"> T</span><span style=3D"color: rgb(102, 102, 0);">&)</spa=
n><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: r=
gb(102, 102, 0);">{}<br></span></code><code><span style=3D"color: rgb(102, =
102, 0);">};</span></code><br>Derive all of your visitors from that. See? P=
roblem solved. You can even make a throwing one.</blockquote><div><br></div=
><div>The problem with doing this is that it won't perform any compile-time=
checks; visitors will always compile because of the templated overload. Wi=
th the visitor class I'm proposing, you explicitely define what types =
should be implemented by the visitor so that the compile-check could be don=
e. If I have a visitor<A, B> my code will not compile if I don't prov=
ide overloads taking types A and B.</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;">The default case should push errors as close to compile-time as=
possible. If the user wants to say that they want runtime errors, or just =
to transparently handle everything else, they have the tools to do that eas=
ily. But by default, we should require the user to write proper, fully-qual=
ified visitors.</blockquote><div><br></div><div>As I said, just use complet=
e_visitor as your default and you will get all those compile-time checks.</=
div><div><br></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)=
; border-left-style: solid; padding-left: 1ex;">That's great. The wonderful=
thing about the Boost version is that you can avoid all of those drawbacks=
easily enough, just by putting an explicit "empty" state into the variant.=
See? The copying won't allocate memory; if a copy constructor throws, it w=
ill go to the blank state. Boost.Variant <i>guarantees</i> this.<=
br>So explain why <i>everyone</i> should be forced to handle empt=
y variants? Boost.Variant gives you everything you ask for (except for the =
fact that you have to actually handle the empty case. But I consider that a=
<i>good</i> thing over throwing exceptions). So... what's the pr=
oblem?</blockquote><div><br></div><div>The problem, I explained it in my pr=
evious post: most of the time it is <b>not</b> possible to add an expl=
icit empty state. Let me cite what I wrote:</div><div><br></div><blockquote=
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; pa=
dding-left: 1ex;">I could add boost::blank as the first of my variant types=
.. The thing is that it is not possible to modify the variant declaration. L=
et's say there is a function in a library taking a ref to a variant with sp=
ecific types as a parameter (but these types do not include boost::blank). =
Now I want to implement that library function and inside of it I do a copy =
assignment from another variant and I want to avoid the guarantee because I=
want it to be optimal. It would not make sense to have to modify the libra=
ry interface (adding boost::blank as one of the types of the variant passed=
as a ref parameter) just to accommodate the implementer.</blockq=
uote><div><br></div><div>To make it shorter, it doesn't make sens to me to =
change the types of my variant (which could be used all over my code) just =
to be able, at a specific place in code, to avoid the cost of the guarantee=
(if I don't need it in that place in code).</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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_179_5136679.1367491680297--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 2 May 2013 04:28:16 -0700 (PDT)
Raw View
------=_Part_6683_12239871.1367494096852
Content-Type: text/plain; charset=ISO-8859-1
On Thursday, May 2, 2013 3:48:00 AM UTC-7, Alex B wrote:
>
> Not really. The common case for a variant is to check all of the
>> possibilities. That is, the common case is that it is user error to miss
>> checking one of the elements. The way you're proposing means that I have to
>> expend a lot of effort in order to handle that common case.
>
>
> Yes. If you use variant::complete_visitor, you *have *the same
> error-checking as boost::static_visitor. So if that's what you want, I
> don't have any problem with it being *your* default.
>
Because it should be *the* default, not "my" default. It is the correct way
to write a visitor. It fixes so many problems ahead of time. Forcing users
to make it clear what their visitors will handle solves so many issues.
My question is why you *don't* want it to be the default. You can still get
around it if you so desire, as previously outlined. But
nine-times-out-of-ten, if a visitor doesn't catch all of the variant
options, then the visitor is out of sync with the variant. That is almost
certainly a bug.
The default should be the scenario that is least likely to create *silently*buggy code.
Plus, it inextricably links the visitor to the variant that uses it. Is
>> that dependency *necessary*? Why does the visitation code need to have
>> the variant definition? It also means that it's much more difficult to use
>> a visitor with different variant types. Is there a reason that this should
>> be so difficult to handle?
>
>
> I see what you mean. There might be a different way to do it that would
> avoid it. I think it will work if I make the visitor class not a nested
> class of variant (put it in namespace scope) and perform the check to
> verify that the visitor types are all part of the variant types on the call
> to apply_visitor (at compile-time).
>
We already have that. It's called boost::apply_visitor. The question is
what to do when there's a possible type in the variant which the visitor
cannot satisfy. The Boost way lets you choose: you can use a simple
template overload to decide what to do. And if you don't (ie: write the
least amount of code), you can get a compiler error.
Also, there *is* a simpler way than redefining the template operator(), if
>> you're really lazy:
>> template<typename Ret>struct no_error_visitor : public boost:
>> static_visitor<Ret>
>> {
>> template<typename T> Ret operator() (const T &) {return Ret();}
>> };
>> template<> struct no_error_visitor<void> : public boost::static_visitor<>
>> {
>> template<typename T> void operator() {const T&) {}
>> };
>> Derive all of your visitors from that. See? Problem solved. You can even
>> make a throwing one.
>
>
> The problem with doing this is that it won't perform any compile-time
> checks; visitors will always compile because of the templated overload.
> With the visitor class I'm proposing, you explicitely define what types
> should be implemented by the visitor so that the compile-check could be
> done. If I have a visitor<A, B> my code will not compile if I don't provide
> overloads taking types A and B.
>
And if your Boost-based visitor doesn't implement operator() for A or B, it
won't compile either. Why do we want to force people to put the types in *
two* places instead of one? Isn't that a code smell of some sort, when a
design forces you to repeat the same information in two places?
That's great. The wonderful thing about the Boost version is that you can
>> avoid all of those drawbacks easily enough, just by putting an explicit
>> "empty" state into the variant. See? The copying won't allocate memory; if
>> a copy constructor throws, it will go to the blank state. Boost.Variant *
>> guarantees* this.
>> So explain why *everyone* should be forced to handle empty variants?
>> Boost.Variant gives you everything you ask for (except for the fact that
>> you have to actually handle the empty case. But I consider that a *good* thing
>> over throwing exceptions). So... what's the problem?
>
>
> The problem, I explained it in my previous post: most of the time it is *
> not* possible to add an explicit empty state. Let me cite what I wrote:
>
> I could add boost::blank as the first of my variant types. The thing is
>> that it is not possible to modify the variant declaration. Let's say there
>> is a function in a library taking a ref to a variant with specific types as
>> a parameter (but these types do not include boost::blank).
>
>
Stop.
If the person creating that variant (and therefore defining the type for
it) did not want that variant to have an empty state, then it does not have
an empty state. This means that the creator of that variant has *willingly
chosen* to accept the costs associated with not being empty. And, since you
are willingly using that variant, you *too* have willingly chosen to accept
those costs.
Just like if a library writer uses `std::string`, you can't use
`std::basic_string<char, ..., some_other_allocator_type>` without copying
the data. You must accept the limitations of the types that a library
presents you with.
Now I want to implement that library function and inside of it I do a copy
>> assignment from another variant and I want to avoid the guarantee because I
>> want it to be optimal. It would not make sense to have to modify the
>> library interface (adding boost::blank as one of the types of the variant
>> passed as a ref parameter) just to accommodate the implementer.
>
>
> To make it shorter, it doesn't make sens to me to change the types of my
> variant (which could be used all over my code) just to be able, at a
> specific place in code, to avoid the cost of the guarantee (if I don't need
> it in that place in code).
>
OK, let's look at the costs of the two approaches: Never-empty (with
user-defined emptiness) vs. Empty (with throwing if a visitor doesn't
explicitly handle the empty state). Here are the costs:
Empty with throw if empty isn't handled:
* Every visitor, or caller thereof, has a choice:
** Handle the empty state.
** Catch the exception thrown from failing to handle the empty state.
** Do neither and therefore have potentially broken code. Especially if
we're talking about a variant instance that was not produced locally. I
would consider this option a code smell that would fail code review.
Never-empty (per Boost.Variant's implementation):
* If none of the members of the variant are no-throw default-constructible,
copying the variant will invoke memory allocation *if and only if* the
current type held by the variant is not nothrow copy/move-constructible.
Both of these costs will be paid "all over my code". In the first case, you
will pay this cost every time you write a visitor or call a visitor that
doesn't test for empty. In the second case, you will pay it every time you
copy the object, but *only* if none of the members are no-throw
default-constructible (and then, only if that particular value is nothrow
copy/moveable).
In one case, the cost will be paid everywhere, no matter what. You will pay
either in added checks or difficult-to-test possible brokenness. They are
inescapable. In the other case, there is a way to use the object to avoid
the cost entirely.
I prefer the option where avoiding the cost is actually possible, rather
than the one that forces you to pay for it one way or another.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_6683_12239871.1367494096852
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Thursday, May 2, 2013 3:48:00 AM UTC-7, Alex B wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><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">Not really. The common case fo=
r a variant is to check all of the possibilities. That is, the common case =
is that it is user error to miss checking one of the elements. The way you'=
re proposing means that I have to expend a lot of effort in order to handle=
that common case.</blockquote><div><br></div><div>Yes. If you use variant:=
:complete_visitor, you <b>have </b>the same error-checking as boost::static=
_visitor. So if that's what you want, I don't have any problem with it bein=
g <i>your</i> default.</div></blockquote><div><br>Because it should be=
<b>the</b> default, not "my" default. It is the correct way to write a vis=
itor. It fixes so many problems ahead of time. Forcing users to make it cle=
ar what their visitors will handle solves so many issues.<br><br>My questio=
n is why you <i>don't</i> want it to be the default. You can still get arou=
nd it if you so desire, as previously outlined. But nine-times-out-of-ten, =
if a visitor doesn't catch all of the variant options, then the visitor is =
out of sync with the variant. That is almost certainly a bug.<br><br>The de=
fault should be the scenario that is least likely to create <i>silently</i>=
buggy code.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><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">Plus, it inextricably links the visitor to the variant that us=
es it. Is that dependency <i>necessary</i>? Why does the visitation co=
de need to have the variant definition? It also means that it's much more d=
ifficult to use a visitor with different variant types. Is there a reason t=
hat this should be so difficult to handle?</blockquote><div><br></div><div>=
I see what you mean. There might be a different way to do it that would avo=
id it. I think it will work if I make the visitor class not a nested class =
of variant (put it in namespace scope) and perform the check to verify that=
the visitor types are all part of the variant types on the call to apply_v=
isitor (at compile-time).</div></blockquote><div><br>We already have that. =
It's called boost::apply_visitor. The question is what to do when there's a=
possible type in the variant which the visitor cannot satisfy. The Boost w=
ay lets you choose: you can use a simple template overload to decide what t=
o do. And if you don't (ie: write the least amount of code), you can get a =
compiler error.</div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><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">Also, there <i>is</i> a simpler way than r=
edefining the template operator(), if you're really lazy:<br><code><span st=
yle=3D"color:rgb(0,0,136)">template</span><span style=3D"color:rgb(102,102,=
0)"><</span><span style=3D"color:rgb(0,0,136)">typename</span><span styl=
e=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Re=
t</span><span style=3D"color:rgb(102,102,0)">></span><span style=3D"colo=
r:rgb(0,0,136)">struct</span><span style=3D"color:rgb(0,0,0)"> <wbr>no=
_error_visitor </span><span style=3D"color:rgb(102,102,0)">:</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136=
)">public</span><span style=3D"color:rgb(0,0,0)"> <wbr>boost</span><sp=
an style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)">=
static_visitor</span><span style=3D"color:rgb(102,102,0)"><</span><span =
style=3D"color:rgb(102,0,102)">Ret</span><span style=3D"color:rgb(102,102,0=
)">><br></span></code><code><span style=3D"color:rgb(102,102,0)">{<br></=
span></code><code><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,0,136)">template</span><span style=3D"color:rgb(102,1=
02,0)"><</span><span style=3D"color:rgb(0,0,136)">typename</span><span s=
tyle=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rgb(102,102,0)=
">></span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(102,0,102)">Ret</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,0,136)">ope<wbr>rator</span><span style=3D"col=
or:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,13=
6)">const</span><span style=3D"color:rgb(0,0,0)"> T </span><span =
style=3D"color:rgb(102,102,0)">&)</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"=
color:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(102,0,102)">Re<wbr>t</span><span style=3D"colo=
r:rgb(102,102,0)">();}<br></span></code><code><span style=3D"color:rgb(102,=
102,0)">};</span></code><code><span style=3D"color:rgb(0,0,0)"><br></span><=
/code><code><span style=3D"color:rgb(0,0,136)">template</span><span style=
=3D"color:rgb(102,102,0)"><></span><span style=3D"color:rgb(0,0,0)">&=
nbsp;</span><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"=
color:rgb(0,0,0)"> no_error_<wbr>visitor</span><span style=3D"color:rg=
b(0,136,0)"><void></span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0=
,0)"> </span><span style=3D"color:rgb(0,0,136)">public</span><span sty=
le=3D"color:rgb(0,0,0)"> boost</span><span style=3D"color:rgb(102,102,=
0)">::</span><span style=3D"color:rgb(0,0,0)"><wbr>static_visitor</span><sp=
an style=3D"color:rgb(102,102,0)"><><br></span></code><code><span sty=
le=3D"color:rgb(102,102,0)">{<br></span></code><code><span style=3D"color:r=
gb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">template</=
span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:r=
gb(0,0,136)">typename</span><span style=3D"color:rgb(0,0,0)"> T</span>=
<span style=3D"color:rgb(102,102,0)">></span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,0,136)">void</span><span styl=
e=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">op<w=
br>erator</span><span style=3D"color:rgb(102,102,0)">()</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</=
span><span style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rg=
b(0,0,0)"> T</span><span style=3D"color:rgb(102,102,0)">&)</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,1=
02,0)">{}<br></span></code><code><span style=3D"color:rgb(102,102,0)">};</s=
pan></code><br>Derive all of your visitors from that. See? Problem solved. =
You can even make a throwing one.</blockquote><div><br></div><div>The probl=
em with doing this is that it won't perform any compile-time checks; visito=
rs will always compile because of the templated overload. With the visitor =
class I'm proposing, you explicitely define what types should be imple=
mented by the visitor so that the compile-check could be done. If I have a =
visitor<A, B> my code will not compile if I don't provide overloads t=
aking types A and B.</div></blockquote><div><br>And if your Boost-based vis=
itor doesn't implement operator() for A or B, it won't compile either. Why =
do we want to force people to put the types in <i>two</i> places instead of=
one? Isn't that a code smell of some sort, when a design forces you to rep=
eat the same information in two places?<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;"><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">That's great. The wonderful thing a=
bout the Boost version is that you can avoid all of those drawbacks easily =
enough, just by putting an explicit "empty" state into the variant. See? Th=
e copying won't allocate memory; if a copy constructor throws, it will go t=
o the blank state. Boost.Variant <i>guarantees</i> this.<br>So ex=
plain why <i>everyone</i> should be forced to handle empty varian=
ts? Boost.Variant gives you everything you ask for (except for the fact tha=
t you have to actually handle the empty case. But I consider that a <i=
>good</i> thing over throwing exceptions). So... what's the problem?</=
blockquote><div><br></div><div>The problem, I explained it in my previous p=
ost: most of the time it is <b>not</b> possible to add an explicit emp=
ty state. Let me cite what I wrote:</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 could add boost::blank as the first of my variant types. The thing is tha=
t it is not possible to modify the variant declaration. Let's say there is =
a function in a library taking a ref to a variant with specific types as a =
parameter (but these types do not include boost::blank).</blockquote></bloc=
kquote><div><br>Stop.<br><br>If the person creating that variant (and there=
fore defining the type for it) did not want that variant to have an empty s=
tate, then it does not have an empty state. This means that the creator of =
that variant has <i>willingly chosen</i> to accept the costs associated wit=
h not being empty. And, since you are willingly using that variant, you <i>=
too</i> have willingly chosen to accept those costs.<br><br>Just like if a =
library writer uses `std::string`, you can't use `std::basic_string<char=
, ..., some_other_allocator_type>` without copying the data. You must ac=
cept the limitations of the types that a library presents you with.<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;"><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"> Now I =
want to implement that library function and inside of it I do a copy assign=
ment from another variant and I want to avoid the guarantee because I want =
it to be optimal. It would not make sense to have to modify the library int=
erface (adding boost::blank as one of the types of the variant passed as a =
ref parameter) just to accommodate the implementer.</blockquote><=
div><br></div><div>To make it shorter, it doesn't make sens to me to change=
the types of my variant (which could be used all over my code) just to be =
able, at a specific place in code, to avoid the cost of the guarantee (if I=
don't need it in that place in code).</div></blockquote><div><br>OK, let's=
look at the costs of the two approaches: Never-empty (with user-defined em=
ptiness) vs. Empty (with throwing if a visitor doesn't explicitly handle th=
e empty state). Here are the costs:<br><br>Empty with throw if empty isn't =
handled:<br><br>* Every visitor, or caller thereof, has a choice:<br>** Han=
dle the empty state.<br>** Catch the exception thrown from failing to handl=
e the empty state.<br>** Do neither and therefore have potentially broken c=
ode. Especially if we're talking about a variant instance that was not prod=
uced locally. I would consider this option a code smell that would fail cod=
e review.<br><br>Never-empty (per Boost.Variant's implementation):<br><br>*=
If none of the members of the variant are no-throw default-constructible, =
copying the variant will invoke memory allocation <i>if and only if</i> the=
current type held by the variant is not nothrow copy/move-constructible.<b=
r><br>Both of these costs will be paid "all over my code". In the first cas=
e, you will pay this cost every time you write a visitor or call a visitor =
that doesn't test for empty. In the second case, you will pay it every time=
you copy the object, but <i>only</i> if none of the members are no-throw d=
efault-constructible (and then, only if that particular value is nothrow co=
py/moveable).<br><br>In one case, the cost will be paid everywhere, no matt=
er what. You will pay either in added checks or difficult-to-test possible =
brokenness. They are inescapable. In the other case, there is a way to use =
the object to avoid the cost entirely.<br><br>I prefer the option where avo=
iding the cost is actually possible, rather than the one that forces you to=
pay for it one way or another.<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_6683_12239871.1367494096852--
.