Topic: Why std::optional has checked and unchecked
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 16 Jan 2018 07:05:41 -0800 (PST)
Raw View
------=_Part_7319_556745548.1516115141787
Content-Type: multipart/alternative;
boundary="----=_Part_7320_1207459577.1516115141788"
------=_Part_7320_1207459577.1516115141788
Content-Type: text/plain; charset="UTF-8"
Because if you didn't want checking, you'd be using a `union`. Also, you're
not generally supposed to fetch values from a `variant`; you're supposed to
be visiting it and acting on it that way.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5dd620cd-a8ef-4354-a14c-6992421729ac%40isocpp.org.
------=_Part_7320_1207459577.1516115141788
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Because if you didn't want checking, you'd be=
using a `union`. Also, you're not generally supposed to fetch values f=
rom a `variant`; you're supposed to be visiting it and acting on it tha=
t way.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5dd620cd-a8ef-4354-a14c-6992421729ac%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5dd620cd-a8ef-4354-a14c-6992421729ac=
%40isocpp.org</a>.<br />
------=_Part_7320_1207459577.1516115141788--
------=_Part_7319_556745548.1516115141787--
.
Author: Richard Hodges <hodges.r@gmail.com>
Date: Tue, 16 Jan 2018 16:11:24 +0100
Raw View
--001a11484830e71b5e0562e6241f
Content-Type: text/plain; charset="UTF-8"
> Also, you're not generally supposed to fetch values from a `variant`, you're
supposed to be visiting it and acting on it that way.
I have wondered before whether optionals should also be visitable, since
logically, they could be thought of as a variant of T and nullopt_t
On 16 January 2018 at 16:05, Nicol Bolas <jmckesson@gmail.com> wrote:
> Because if you didn't want checking, you'd be using a `union`. Also,
> you're not generally supposed to fetch values from a `variant`; you're
> supposed to be visiting it and acting on it that way.
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/5dd620cd-a8ef-4354-
> a14c-6992421729ac%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5dd620cd-a8ef-4354-a14c-6992421729ac%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALvx3hYH7uwZtz5bMdAMwTCz5LG73iobfApidEX-Njvxmy1RyQ%40mail.gmail.com.
--001a11484830e71b5e0562e6241f
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">>=C2=A0<span style=3D"font-size:12.8px">Also, you'r=
e not generally supposed to fetch values from a `variant`,=C2=A0</span><spa=
n style=3D"font-size:12.8px">you're supposed to be visiting it and acti=
ng on it that way.</span><div><span style=3D"font-size:12.8px"><br></span><=
/div><div><span style=3D"font-size:12.8px">I have wondered before whether o=
ptionals should also be visitable, since logically, they could be thought o=
f as a variant of <font face=3D"monospace, monospace">T</font> and <font fa=
ce=3D"monospace, monospace">nullopt_t</font></span></div><div><div><span st=
yle=3D"font-size:12.8px"><br></span></div></div></div><div class=3D"gmail_e=
xtra"><br><div class=3D"gmail_quote">On 16 January 2018 at 16:05, Nicol Bol=
as <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_=
blank">jmckesson@gmail.com</a>></span> wrote:<br><blockquote class=3D"gm=
ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>Because if you didn't want checking, you&=
#39;d be using a `union`. Also, you're not generally supposed to fetch =
values from a `variant`; you're supposed to be visiting it and acting o=
n it that way.<br></div></div><span class=3D"">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5dd620cd-a8ef-4354-a14c-6992421729ac%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/5dd6=
20cd-a8ef-4354-<wbr>a14c-6992421729ac%40isocpp.org</a><wbr>.<br>
</blockquote></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CALvx3hYH7uwZtz5bMdAMwTCz5LG73iobfApi=
dEX-Njvxmy1RyQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALvx3hYH7uwZtz5b=
MdAMwTCz5LG73iobfApidEX-Njvxmy1RyQ%40mail.gmail.com</a>.<br />
--001a11484830e71b5e0562e6241f--
.
Author: Zhihao Yuan <zy@miator.net>
Date: Tue, 16 Jan 2018 10:38:43 -0500
Raw View
This is a multi-part message in MIME format.
--b1_d33892911b8c9e0e54482678d1fee4b8
Content-Type: text/plain; charset="UTF-8"
While it's not a bad idea (pattern matching in other
languages naturally support this use), in practise
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.html
may be easier to use.
--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
_______________________________________________
> -------- Original Message --------
> UTC Time: January 16, 2018 3:11 PM
> From: hodges.r@gmail.com
>
> I have wondered before whether optionals should also be visitable, since logically, they could be thought of as a variant of T and nullopt_t
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/HcludflA0pBlg8rnBwk_X3go-vy-MI-1YwE6cv8ky21WB85MQ17-d8of6blHVjgolBT2KaH74nXAWW_gI5XZJfcSUvUNNLo6M985ovjm7a8%3D%40miator.net.
--b1_d33892911b8c9e0e54482678d1fee4b8
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div>While it's not a bad idea (pattern matching in other<br></div><div>lan=
guages naturally support this use), in practise<br></div><div><br></div><di=
v> <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017=
/p0798r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p079=
8r0.html</a><br></div><div><br></div><div>may be easier to use.<br></div><d=
iv><br></div><div class=3D"protonmail_signature_block"><div class=3D"proton=
mail_signature_block-user"><div>--<br></div><div><span>Zhihao Yuan, ID lich=
ray<br>The best way to predict the future is to invent it.<br>_____________=
__________________________________</span></div></div><div class=3D"protonma=
il_signature_block-proton protonmail_signature_block-empty"><br></div></div=
><div><br></div><blockquote class=3D"protonmail_quote" type=3D"cite"><div>-=
------- Original Message --------<br></div><div>UTC Time: January 16, 2018 =
3:11 PM<br></div><div>From: hodges.r@gmail.com<br></div><div><br></div><div=
dir=3D"ltr"><div><span style=3D"font-size:12.8px" class=3D"size">I have wo=
ndered before whether optionals should also be visitable, since logically, =
they could be thought of as a variant of <span style=3D"font-family:monospa=
ce, monospace" class=3D"font">T</span> and <span style=3D"font-family:monos=
pace, monospace" class=3D"font">nullopt_t</span></span><br></div></div></bl=
ockquote><div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/HcludflA0pBlg8rnBwk_X3go-vy-MI-1YwE6c=
v8ky21WB85MQ17-d8of6blHVjgolBT2KaH74nXAWW_gI5XZJfcSUvUNNLo6M985ovjm7a8%3D%4=
0miator.net?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/HcludflA0pBlg8rnBwk_X3go-vy-MI-1YwE6c=
v8ky21WB85MQ17-d8of6blHVjgolBT2KaH74nXAWW_gI5XZJfcSUvUNNLo6M985ovjm7a8%3D%4=
0miator.net</a>.<br />
--b1_d33892911b8c9e0e54482678d1fee4b8--
.
Author: Oleksandr Pikozh <o.pikozh@gmail.com>
Date: Tue, 16 Jan 2018 17:52:31 +0200
Raw View
This is a multi-part message in MIME format.
--------------1C30913648BB3C2AB1A1F7E2
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
Well, an object is often used in different ways from different parts of=20
code: more carefree from relatively-rarely-called routines and more=20
optimized from relatively-often-called routines. Therefore it's good for=20
the same tool to support different modes; sometimes I want checking,=20
sometimes I don't (i.e. I want std::variant that keeps its `index`, but=20
sometimes to allow to do the `get`-like thing without internal checks);=20
as for me, that's the main goal of C++ =E2=80=94 to support higher-level=20
programming without losing the low-level control. Absence of unchecked=20
operations (comparable to std::optional::operator* and=20
std::vector::operator[]) makes std::variant (almost) useless for me: it=20
looks more psychologically-comfortable to use "enum state + union value"=20
from the beginning, than to integrate std::variant with feeling that it=20
implies checks that I can never get rid of(even in cases when inner type=20
is guaranteed by outer logic).
Besides that the same your argument can be applied for std::optional too=20
=E2=80=94 "if you didn't want checking, you'd be using a `T value` instead =
of=20
`std::optional<T> value`", right? (But no, we still have checkless=20
`std::optional::operator*` =E2=80=94 because there is no need to check agai=
n in=20
`if (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like cases, for example.)
"you're supposed to be visiting it and acting on it that way" =E2=80=94 am =
I=20
supposed to act _only_ in that way?
On 16.01.18 17:05, Nicol Bolas wrote:
> Because if you didn't want checking, you'd be using a `union`. Also,=20
> you're not generally supposed to fetch values from a `variant`; you're=20
> supposed to be visiting it and acting on it that way.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/3e553f4c-c2eb-3d80-4345-196d2a9e0647%40gmail.com=
..
--------------1C30913648BB3C2AB1A1F7E2
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
Well, an object is often used in different ways from different parts
of code: more <span id=3D"result_box" class=3D"short_text" lang=3D"en">=
<span
class=3D"">carefree from relatively-rarely-called routines and
more optimized from </span></span><span id=3D"result_box"
class=3D"short_text" lang=3D"en"><span class=3D""><span id=3D"result_=
box"
class=3D"short_text" lang=3D"en"><span class=3D"">relatively-ofte=
n-called
routines</span></span>. Therefore it's good for the same
tool to support different modes; sometimes I want checking,
sometimes I don't (i.e. I want std::variant that keeps its
`index`, but sometimes to allow to do the `get`-like thing
without internal checks); as for me, that's the main goal of C++
=E2=80=94 to support higher-level programming without losing the
low-level control. Absence of unchecked operations (comparable
to std::optional::operator* and std::vector::operator[]) makes
std::variant (almost) useless for me: it looks more
psychologically-comfortable to use "enum state + union value"
from the beginning, than to integrate std::variant with feeling
that it implies checks that I can never get rid of</span></span><sp=
an
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=3D""><=
span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=3D=
"">
(even in cases when inner type is guaranteed by outer
logic).</span></span></span></span>
<p><span id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=
=3D""><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=
=3D"">Besides
that the same your argument can be applied for std::optional
too =E2=80=94 "</span></span></span></span><span id=3D"result=
_box"
class=3D"short_text" lang=3D"en"><span class=3D""><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=
=3D"">if
you didn't want checking, you'd be using a `T value`
instead of `std::optional<T> value`</span></span></span=
></span><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=3D""=
><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=
=3D""><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span
class=3D""><span id=3D"result_box" class=3D"short_text"
lang=3D"en"><span class=3D"">"</span></span></span></sp=
an>,
right? (But no, we still have checkless
`std::optional::operator*` =E2=80=94 because there is no need=
to
check again in `if (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like c=
ases, for
example.)<br>
</span></span></span></span></p>
<p><span id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=
=3D""><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=
=3D"">"</span></span></span></span><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=3D""=
><span
id=3D"result_box" class=3D"short_text" lang=3D"en"><span class=
=3D"">you're
supposed to be visiting it and acting on it that way" =E2=80=
=94 am
I supposed to act _only_ in that way?<br>
</span></span></span></span></p>
On 16.01.18 17:05, Nicol Bolas wrote:<br>
<blockquote type=3D"cite"
cite=3D"mid:5dd620cd-a8ef-4354-a14c-6992421729ac@isocpp.org">
<div dir=3D"ltr">
<div>Because if you didn't want checking, you'd be using a
`union`. Also, you're not generally supposed to fetch values
from a `variant`; you're supposed to be visiting it and acting
on it that way.<br>
</div>
</div>
</blockquote>
<br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/3e553f4c-c2eb-3d80-4345-196d2a9e0647%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/3e553f4c-c2eb-3d80-4345-196d2a9e0647%=
40gmail.com</a>.<br />
--------------1C30913648BB3C2AB1A1F7E2--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 16 Jan 2018 08:35:10 -0800 (PST)
Raw View
------=_Part_7353_1150976193.1516120510274
Content-Type: multipart/alternative;
boundary="----=_Part_7354_878793721.1516120510275"
------=_Part_7354_878793721.1516120510275
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksandr Pikozh wrote:
>
> Well, an object is often used in different ways from different parts of=
=20
> code: more carefree from relatively-rarely-called routines and more=20
> optimized from relatively-often-called routines. Therefore it's good for=
=20
> the same tool to support different modes; sometimes I want checking,=20
> sometimes I don't (i.e. I want std::variant that keeps its `index`, but=
=20
> sometimes to allow to do the `get`-like thing without internal checks); a=
s=20
> for me, that's the main goal of C++ =E2=80=94 to support higher-level pro=
gramming=20
> without losing the low-level control. Absence of unchecked operations=20
> (comparable to std::optional::operator* and std::vector::operator[]) make=
s=20
> std::variant (almost) useless for me: it looks more=20
> psychologically-comfortable to use "enum state + union value" from the=20
> beginning, than to integrate std::variant with feeling that it implies=20
> checks that I can never get rid of (even in cases when inner type is=20
> guaranteed by outer logic).=20
>
> Besides that the same your argument can be applied for std::optional too =
=E2=80=94=20
> "if you didn't want checking, you'd be using a `T value` instead of=20
> `std::optional<T> value`", right? (But no, we still have checkless=20
> `std::optional::operator*` =E2=80=94 because there is no need to check ag=
ain in `if=20
> (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like cases, for example.)
>
> "you're supposed to be visiting it and acting on it that way" =E2=80=94 a=
m I=20
> supposed to act _only_ in that way?
>
I generally consider the use of `get` on a variant* at all* to be a=20
code-smell. A function which takes a variant is a function that is expected=
=20
to be able to operate correctly on* all* of the possible values in the=20
variant. And the most effective way to achieve that is to use visitation=20
when you want to access the member. By using `get`, you're saying that the=
=20
code in question simply can't handle the other possible states of the=20
variant. That's the wrong way to use a variant.
Visitation fixes so many problems. It makes it statically impossible for=20
you to forget to handle a state. It makes your code more readable (to a=20
degree), since you can use the variant value like it were a regular value.=
=20
It discourages lots of conditions. And so forth.
That's not to say that `get` is bad. It's simply not a tool that should be=
=20
in such frequent use that not having an unchecked version is a legitimate=
=20
problem.
Consider your example of "when inner type is guaranteed by outer logic".=20
How did this "outer logic" provide this guarantee? Did it create the=20
`variant` with that state? If so... why did it bundle it in a `variant`,=20
when it clearly only provides an object of a specific type? Did the "outer=
=20
logic" already do the test? If so, why did it not unpack the object=20
directly when it did that test, and just pass the object of the right type?=
If=20
the "inner" logic can only handle a specific state, why is it being given=
=20
an object that can assume states it cannot handle? That is, rather than:
if(var.index() =3D=3D required_index)
{
auto &value =3D get<required_index>(var);
}
You do this:
if(auto ptr =3D get_if<required_index>(&var); ptr)
{
//use `ptr`
}
The fundamental difference between `optional` and `variant` is that the=20
former only ever has 2 states. The behavior for the unengaged state will=20
almost always be "do nothing", while the behavior for the engaged state=20
will be "do something". Your code strongly suggests that you're trying to=
=20
treat a `variant` like an `optional`. And we have a way to do that: get a=
=20
pointer to the member.
Also, I'm curious as to your application where a single conditional check=
=20
is sufficient to make the type "(almost) useless for me". Seriously, is=20
that trivial performance *really* sufficient to go write your own variant=
=20
type or to use something less feature-rich?
You're also missing another problem with checked vs. unchecked operations:=
=20
consistency.
In the C++ standard library, the way you tell whether an operation is=20
checked or unchecked is that the unchecked operation uses an* operator*.=20
`vector::operator[]`, `optional::operator*`, and so on are operators. If=20
you use a named function, then it is a checked operation. `vector::at`,=20
`optional::value`, and so forth.
You can't really have an operator-form of the `variant` `get` function.=20
After all, you need to provide a template index/type, and you can't pass=20
something like that as a function parameter to an operator. After all,=20
operators cannot take explicit template parameters without calling them by=
=20
spelling out the operator (`variant::operator[]<std::string>(0)`).
Well... you* can* work around this, but it would require wrapping it up in=
=20
a constexpr type, and then having a template extract the type from the=20
parameter. So you'd have to do something like this:
var[type_container<Type>{}];
var[3_const_index];
And allow template argument deduction of `operator[]` to extract the=20
typename or index to access.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/7c323bd5-b9c7-4be4-971d-f617c6341665%40isocpp.or=
g.
------=_Part_7354_878793721.1516120510275
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksan=
dr Pikozh wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
Well, an object is often used in different ways from different parts
of code: more <span lang=3D"en"><span>carefree from relatively-rarely-c=
alled routines and
more optimized from </span></span><span lang=3D"en"><span><span lan=
g=3D"en"><span>relatively-often-called
routines</span></span>. Therefore it's good for the same
tool to support different modes; sometimes I want checking,
sometimes I don't (i.e. I want std::variant that keeps its
`index`, but sometimes to allow to do the `get`-like thing
without internal checks); as for me, that's the main goal of C+=
+
=E2=80=94 to support higher-level programming without losing the
low-level control. Absence of unchecked operations (comparable
to std::optional::operator* and std::vector::operator[]) makes
std::variant (almost) useless for me: it looks more
psychologically-comfortable to use "enum state + union value&q=
uot;
from the beginning, than to integrate std::variant with feeling
that it implies checks that I can never get rid of</span></span><sp=
an lang=3D"en"><span><span lang=3D"en"><span>
(even in cases when inner type is guaranteed by outer
logic).</span></span></span></span>
<p><span lang=3D"en"><span><span lang=3D"en"><span>Besides
that the same your argument can be applied for std::optional
too =E2=80=94 "</span></span></span></span><span lang=3D=
"en"><span><span lang=3D"en"><span>if
you didn't want checking, you'd be using a `T value`
instead of `std::optional<T> value`</span></span></span=
></span><span lang=3D"en"><span><span lang=3D"en"><span><span lang=3D"en"><=
span><span lang=3D"en"><span>"</span></span></span></span>,
right? (But no, we still have checkless
`std::optional::operator*` =E2=80=94 because there is no need=
to
check again in `if (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like c=
ases, for
example.)<br>
</span></span></span></span></p>
<p><span lang=3D"en"><span><span lang=3D"en"><span>"</span></span>=
</span></span><span lang=3D"en"><span><span lang=3D"en"><span>you're
supposed to be visiting it and acting on it that way" =
=E2=80=94 am
I supposed to act _only_ in that way?<br></span></span></span=
></span></p></div></blockquote><div><br></div><div>I generally consider the=
use of `get` on a variant<i> at all</i> to be a code-smell. A function whi=
ch takes a variant is a function that is expected to be able to operate cor=
rectly on<i> all</i> of the possible values in the variant. And the most ef=
fective way to achieve that is to use visitation when you want to access th=
e member. By using `get`, you're saying that the code in question simpl=
y can't handle the other possible states of the variant. That's the=
wrong way to use a variant.</div><div><br></div><div>Visitation fixes so m=
any problems. It makes it statically impossible for you to forget to handle=
a state. It makes your code more readable (to a degree), since you can use=
the variant value like it were a regular value. It discourages lots of con=
ditions. And so forth.</div><div><br></div><div>That's not to say that =
`get` is bad. It's simply not a tool that should be in such frequent us=
e that not having an unchecked version is a legitimate problem.</div><div><=
br></div><div>Consider your example of "<span style=3D"display: inline=
!important; float: none; background-color: transparent; color: rgb(34, 34,=
34); font-family: "Arial","Helvetica",sans-serif; font=
-size: 13px; font-style: normal; font-variant: normal; font-weight: 400; le=
tter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; =
text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; whi=
te-space: normal; word-spacing: 0px;">when inner type is guaranteed by oute=
r
logic". How did this "outer logic" provide this =
guarantee? Did it create the `variant` with that state? If so... why did it=
bundle it in a `variant`, when it clearly only provides an object of a spe=
cific type? Did the "outer logic" already do the test? If so, why=
did it not unpack the object directly when it did that test, and just pass=
the object of the right type? <span style=3D"background-color: transparent=
; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-b=
ottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; bor=
der-image-slice: 100%; border-image-source: none; border-image-width: 1; bo=
rder-left-color: rgb(34, 34, 34); border-left-style: none; border-left-widt=
h: 0px; border-right-color: rgb(34, 34, 34); border-right-style: none; bord=
er-right-width: 0px; border-top-color: rgb(34, 34, 34); border-top-style: n=
one; border-top-width: 0px; color: rgb(34, 34, 34); display: inline; float:=
none; font-family: &quot;Arial&quot;,&quot;Helvetica&quot;=
,sans-serif; font-size: 13px; font-style: normal; font-variant: normal; fon=
t-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px=
; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; padd=
ing-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text=
-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-str=
oke-width: 0px; white-space: normal; word-spacing: 0px;">If the "inner=
" logic can only handle a specific state, why is it being given an obj=
ect that can assume states it cannot handle?</span>=C2=A0That is, rather th=
an:</span></div><div><span style=3D"display: inline !important; float: none=
; background-color: transparent; color: rgb(34, 34, 34); font-family: "=
;Arial","Helvetica",sans-serif; font-size: 13px; font-style:=
normal; font-variant: normal; font-weight: 400; letter-spacing: normal; or=
phans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-t=
ransform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-s=
pacing: 0px;"><br></span></div><div class=3D"prettyprint" style=3D"border: =
1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(=
250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span class=3D"styled-by-prettify" style=3D"color: #008;">if</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: #660;">(</span><span class=3D"st=
yled-by-prettify" style=3D"color: #008;">var</span><span class=3D"styled-by=
-prettify" style=3D"color: #660;">.</span><span class=3D"styled-by-prettify=
" style=3D"color: #000;">index</span><span class=3D"styled-by-prettify" sty=
le=3D"color: #660;">()</span><span class=3D"styled-by-prettify" style=3D"co=
lor: #000;"> </span><span class=3D"styled-by-prettify" style=3D"color: #660=
;">=3D=3D</span><span class=3D"styled-by-prettify" style=3D"color: #000;"> =
required_index</span><span class=3D"styled-by-prettify" style=3D"color: #66=
0;">)</span><span class=3D"styled-by-prettify" style=3D"color: #000;"><br><=
/span><span class=3D"styled-by-prettify" style=3D"color: #660;">{</span><sp=
an class=3D"styled-by-prettify" style=3D"color: #000;"><br>=C2=A0 </span><s=
pan class=3D"styled-by-prettify" style=3D"color: #008;">auto</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: #000;"> </span><span class=3D"st=
yled-by-prettify" style=3D"color: #660;">&</span><span class=3D"styled-=
by-prettify" style=3D"color: #000;">value </span><span class=3D"styled-by-p=
rettify" style=3D"color: #660;">=3D</span><span class=3D"styled-by-prettify=
" style=3D"color: #000;"> </span><span class=3D"styled-by-prettify" style=
=3D"color: #008;">get</span><span class=3D"styled-by-prettify" style=3D"col=
or: #080;"><required_index></span><span class=3D"styled-by-prettify" =
style=3D"color: #660;">(</span><span class=3D"styled-by-prettify" style=3D"=
color: #008;">var</span><span class=3D"styled-by-prettify" style=3D"color: =
#660;">);</span><span class=3D"styled-by-prettify" style=3D"color: #000;"><=
br></span><span class=3D"styled-by-prettify" style=3D"color: #660;">}</span=
></div></code></div><div><span style=3D"display: inline !important; float: =
none; background-color: transparent; color: rgb(34, 34, 34); font-family: &=
quot;Arial","Helvetica",sans-serif; font-size: 13px; font-st=
yle: normal; font-variant: normal; font-weight: 400; letter-spacing: normal=
; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; te=
xt-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; wo=
rd-spacing: 0px;"><br></span></div><div><span style=3D"display: inline !imp=
ortant; float: none; background-color: transparent; color: rgb(34, 34, 34);=
font-family: "Arial","Helvetica",sans-serif; font-size=
: 13px; font-style: normal; font-variant: normal; font-weight: 400; letter-=
spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-=
indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-sp=
ace: normal; word-spacing: 0px;">You do this:</span></div><div><span style=
=3D"display: inline !important; float: none; background-color: transparent;=
color: rgb(34, 34, 34); font-family: "Arial","Helvetica&quo=
t;,sans-serif; font-size: 13px; font-style: normal; font-variant: normal; f=
ont-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text=
-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-str=
oke-width: 0px; white-space: normal; word-spacing: 0px;"><br></span></div><=
div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); wo=
rd-wrap: break-word; background-color: rgb(250, 250, 250);"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span class=3D"styled-by-prettif=
y" style=3D"color: #008;">if</span><span class=3D"styled-by-prettify" style=
=3D"color: #660;">(</span><span class=3D"styled-by-prettify" style=3D"color=
: #008;">auto</span><span class=3D"styled-by-prettify" style=3D"color: #000=
;"> ptr </span><span class=3D"styled-by-prettify" style=3D"color: #660;">=
=3D</span><span class=3D"styled-by-prettify" style=3D"color: #000;"> get_if=
</span><span class=3D"styled-by-prettify" style=3D"color: #080;"><requir=
ed_index></span><span class=3D"styled-by-prettify" style=3D"color: #660;=
">(&</span><span class=3D"styled-by-prettify" style=3D"color: #008;">va=
r</span><span class=3D"styled-by-prettify" style=3D"color: #660;">);</span>=
<span class=3D"styled-by-prettify" style=3D"color: #000;"> ptr</span><span =
class=3D"styled-by-prettify" style=3D"color: #660;">)</span><span class=3D"=
styled-by-prettify" style=3D"color: #000;"><br></span><span class=3D"styled=
-by-prettify" style=3D"color: #660;">{</span><span class=3D"styled-by-prett=
ify" style=3D"color: #000;"><br>=C2=A0 </span><span class=3D"styled-by-pret=
tify" style=3D"color: #800;">//use `ptr`</span><span class=3D"styled-by-pre=
ttify" style=3D"color: #000;"><br></span><span class=3D"styled-by-prettify"=
style=3D"color: #660;">}</span></div></code></div><div><span style=3D"disp=
lay: inline !important; float: none; background-color: transparent; color: =
rgb(34, 34, 34); font-family: "Arial","Helvetica",sans-=
serif; font-size: 13px; font-style: normal; font-variant: normal; font-weig=
ht: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decorat=
ion: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-widt=
h: 0px; white-space: normal; word-spacing: 0px;"><br></span><span style=3D"=
display: inline !important; float: none; background-color: transparent; col=
or: rgb(34, 34, 34); font-family: "Arial","Helvetica",s=
ans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-=
weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-dec=
oration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-=
width: 0px; white-space: normal; word-spacing: 0px;"></span></div><div><spa=
n style=3D"display: inline !important; float: none; background-color: trans=
parent; color: rgb(34, 34, 34); font-family: "Arial","Helvet=
ica",sans-serif; font-size: 13px; font-style: normal; font-variant: no=
rmal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: lef=
t; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-t=
ext-stroke-width: 0px; white-space: normal; word-spacing: 0px;">The fundame=
ntal difference between `optional` and `variant` is that the former only ev=
er has 2 states. The behavior for the unengaged state will almost always be=
"do nothing", while the behavior for the engaged state will be &=
quot;do something". </span>Your code strongly suggests that you're=
trying to treat a `variant` like an `optional`. And we have a way to do th=
at: get a pointer to the member.</div><div><b><br></b></div><div>Also, I=
9;m curious as to your application where a single conditional check is suff=
icient to make the type "(almost) useless for me". Seriously, is =
that trivial performance <i>really</i> sufficient to go write your own vari=
ant type or to use something less feature-rich?</div><div><br></div><div>Yo=
u're also missing another problem with checked vs. unchecked operations=
: consistency.</div><div><br></div><div>In the C++ standard library, the wa=
y you tell whether an operation is checked or unchecked is that the uncheck=
ed operation uses an<i> operator</i>. `vector::operator[]`, `optional::oper=
ator*`, and so on are operators. If you use a named function, then it is a =
checked operation. `vector::at`, `optional::value`, and so forth.</div><div=
><br></div><div>You can't really have an operator-form of the `variant`=
`get` function. After all, you need to provide a template index/type, and =
you can't pass something like that as a function parameter to an operat=
or. After all, operators cannot take explicit template parameters without c=
alling them by spelling out the operator (`variant::operator[]<std::stri=
ng>(0)`).</div><div><br></div><div>Well... you<i> can</i> work around th=
is, but it would require wrapping it up in a constexpr type, and then havin=
g a template extract the type from the parameter. So you'd have to do s=
omething like this:</div><div><br></div><div class=3D"prettyprint" style=3D=
"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-co=
lor: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subpret=
typrint"><span class=3D"styled-by-prettify" style=3D"color: #008;">var</spa=
n><span class=3D"styled-by-prettify" style=3D"color: #660;">[</span><span c=
lass=3D"styled-by-prettify" style=3D"color: #000;">type_container</span><sp=
an class=3D"styled-by-prettify" style=3D"color: #660;"><</span><span cla=
ss=3D"styled-by-prettify" style=3D"color: #606;">Type</span><span class=3D"=
styled-by-prettify" style=3D"color: #660;">>{}];</span><span class=3D"st=
yled-by-prettify" style=3D"color: #000;"><br></span><span class=3D"styled-b=
y-prettify" style=3D"color: #008;">var</span><span class=3D"styled-by-prett=
ify" style=3D"color: #660;">[</span><span class=3D"styled-by-prettify" styl=
e=3D"color: #066;">3</span><span class=3D"styled-by-prettify" style=3D"colo=
r: #000;">_const_index</span><span class=3D"styled-by-prettify" style=3D"co=
lor: #660;">];</span></div></code></div><div><br></div><div>And allow templ=
ate argument deduction of `operator[]` to extract the typename or index to =
access.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv bgcolor=3D"#FFFFFF" text=3D"#000000">
</div>
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/7c323bd5-b9c7-4be4-971d-f617c6341665%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/7c323bd5-b9c7-4be4-971d-f617c6341665=
%40isocpp.org</a>.<br />
------=_Part_7354_878793721.1516120510275--
------=_Part_7353_1150976193.1516120510274--
.
Author: Oleksandr Pikozh <o.pikozh@gmail.com>
Date: Tue, 16 Jan 2018 20:02:41 +0200
Raw View
This is a multi-part message in MIME format.
--------------6ABAF1BE4199198796C2C43A
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
On 16.01.18 18:35, Nicol Bolas wrote:
> On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksandr Pikozh=20
> wrote:
>
> Well, an object is often used in different ways from different
> parts of code: more carefree from relatively-rarely-called
> routines and more optimized from relatively-often-called routines.
> Therefore it's good for the same tool to support different modes;
> sometimes I want checking, sometimes I don't (i.e. I want
> std::variant that keeps its `index`, but sometimes to allow to do
> the `get`-like thing without internal checks); as for me, that's
> the main goal of C++ =E2=80=94 to support higher-level programming wi=
thout
> losing the low-level control. Absence of unchecked operations
> (comparable to std::optional::operator* and
> std::vector::operator[]) makes std::variant (almost) useless for
> me: it looks more psychologically-comfortable to use "enum state +
> union value" from the beginning, than to integrate std::variant
> with feeling that it implies checks that I can never get rid
> of(even in cases when inner type is guaranteed by outer logic).
>
> Besides that the same your argument can be applied for
> std::optional too =E2=80=94 "if you didn't want checking, you'd be us=
ing a
> `T value` instead of `std::optional<T> value`", right? (But no, we
> still have checkless `std::optional::operator*` =E2=80=94 because the=
re is
> no need to check again in `if (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-lik=
e cases, for
> example.)
>
> "you're supposed to be visiting it and acting on it that way" =E2=80=
=94 am
> I supposed to act _only_ in that way?
>
>
> I generally consider the use of `get` on a variant/at all/ to be a=20
> code-smell. A function which takes a variant is a function that is=20
> expected to be able to operate correctly on/all/ of the possible=20
> values in the variant. And the most effective way to achieve that is=20
> to use visitation when you want to access the member. By using `get`,=20
> you're saying that the code in question simply can't handle the other=20
> possible states of the variant. That's the wrong way to use a variant.
>
> Visitation fixes so many problems. It makes it statically impossible=20
> for you to forget to handle a state. It makes your code more readable=20
> (to a degree), since you can use the variant value like it were a=20
> regular value. It discourages lots of conditions. And so forth.
>
> That's not to say that `get` is bad. It's simply not a tool that=20
> should be in such frequent use that not having an unchecked version is=20
> a legitimate problem.
Looks like oversimplification for me.
The set of real-life cases is much more rich.
E.g. we can have an std::variant field in a class =E2=80=94 and some=20
more-universal methods (that handle all states combinations) in the=20
class can call some more-specialized ones (that handle only specific=20
state combinations). Of course, we can cache references (pointers) to=20
members of std::variant and pass them from method to method (in addition=20
to passing `this`, which already has access to the whole std::variant=20
field), but it decreases aesthetics of the code (and additionally looks=20
redundant at first glance, because with the most expected (but not=20
guaranteed, of course) implementation of variant, the pointer to the=20
member would have fixed offset from the pointer to the whole std::variant).
> Consider your example of "when inner type is guaranteed by outer=20
> logic". How did this "outer logic" provide this guarantee? Did it=20
> create the `variant` with that state? If so... why did it bundle it in=20
> a `variant`, when it clearly only provides an object of a specific=20
> type? Did the "outer logic" already do the test? If so, why did it not=20
> unpack the object directly when it did that test, and just pass the=20
> object of the right type? If the "inner" logic can only handle a=20
> specific state, why is it being given an object that can assume states=20
> it cannot handle?=C2=A0That is, rather than:
>
> |
> if(var.index()=3D=3Drequired_index)
> {
> auto&value =3Dget<required_index>(var);
> }
> |
>
> You do this:
>
> |
> if(autoptr =3Dget_if<required_index>(&var);ptr)
> {
> //use `ptr`
> }
> |
>
> The fundamental difference between `optional` and `variant` is that=20
> the former only ever has 2 states. The behavior for the unengaged=20
> state will almost always be "do nothing", while the behavior for the=20
> engaged state will be "do something". Your code strongly suggests that=20
> you're trying to treat a `variant` like an `optional`. And we have a=20
> way to do that: get a pointer to the member.
Yes, I consider variant as a generalization of optional. But (for some=20
reasons that look bogus for me) the generalization isn't smooth. IMHO it=20
is better to fix it (even if no so much people feel practical problems=20
due to that shagginess =E2=80=94 just for aesthetic reasons at least).
> Also, I'm curious as to your application where a single conditional=20
> check is sufficient to make the type "(almost) useless for me".=20
> Seriously, is that trivial performance /really/ sufficient to go write=20
> your own variant type or to use something less feature-rich?
It's more about consistency and psychology, not about actual=20
benchmarking yet. I am writing right now a piece of code that with high=20
probability will be a part of bottleneck. I realize that in some cases=20
std::variant does redundant checks (at least with the way I use it). I=20
expect them to be avoidable (as in std::optional and others), but they=20
aren't. So it's psychologically simpler for me to throw std::variant out=20
and not to use in the "foundation" (that will probably be a bottleneck)=20
any things that have _known_ overhead. Not necessarily variant::get will=20
be a problem (and most probably something absolutely else will), but I=20
don't like a feeling of creating future problems when writing the code=20
(i.e. to write a code with a known and easy-avoidable redundancy, which=20
doesn't brings and significant improvements into the code aesthetics or=20
some other tremendous benefits).
> You're also missing another problem with checked vs. unchecked=20
> operations: consistency.
>
> In the C++ standard library, the way you tell whether an operation is=20
> checked or unchecked is that the unchecked operation uses=20
> an/operator/. `vector::operator[]`, `optional::operator*`, and so on=20
> are operators. If you use a named function, then it is a checked=20
> operation. `vector::at`, `optional::value`, and so forth.
>
> You can't really have an operator-form of the `variant` `get`=20
> function. After all, you need to provide a template index/type, and=20
> you can't pass something like that as a function parameter to an=20
> operator. After all, operators cannot take explicit template=20
> parameters without calling them by spelling out the operator=20
> (`variant::operator[]<std::string>(0)`).
I never heard about "methods-are-checked, functions-are-unchecked" rule=20
in stdlib. Is is stated somewhere?
As for me, much more expected understanding of consistency here would be=20
that every class (where it's applicable) has two ways of access: checked=20
and unchecked. (If the std::vector and std::optional had no unchecked=20
access, then I would have no disturbance about std::variant =E2=80=94 I'd j=
ust=20
see that as style of C++ stdlib; even if only std::optional had no=20
unchecked access, then it would look understandable for me (stdlib is=20
old, std::vector created long before std::optional and std::variant,=20
style changed since then); but now it looks as breaking its own style.)
And if unchecked things really need to be operators (which I doubt, even=20
if the such rule exists and wasn't broken yet, it will be surely be=20
broken at some point of time in future due to the growing of stdlib and=20
growing of the amount of strongly-needed-to-be-unchecked things), why=20
not simply the explicit cast operator? (Ah, you are right, explicit cast=20
operator will allow only access by type, not by index =E2=80=94 still I don=
't=20
feel both access by index and .)
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/d560a76d-fa64-ed3e-a887-1e340958cfaf%40gmail.com=
..
--------------6ABAF1BE4199198796C2C43A
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
On 16.01.18 18:35, Nicol Bolas wrote:<br>
<blockquote type=3D"cite"
cite=3D"mid:7c323bd5-b9c7-4be4-971d-f617c6341665@isocpp.org">
<div dir=3D"ltr">On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5,
Oleksandr Pikozh wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000"> Well, an object is
often used in different ways from different parts of code:
more <span lang=3D"en"><span>carefree from
relatively-rarely-called routines and more optimized
from </span></span><span lang=3D"en"><span><span
lang=3D"en"><span>relatively-often-called routines</span>=
</span>.
Therefore it's good for the same tool to support
different modes; sometimes I want checking, sometimes I
don't (i.e. I want std::variant that keeps its `index`,
but sometimes to allow to do the `get`-like thing
without internal checks); as for me, that's the main
goal of C++ =E2=80=94 to support higher-level programming
without losing the low-level control. Absence of
unchecked operations (comparable to
std::optional::operator* and std::vector::operator[])
makes std::variant (almost) useless for me: it looks
more psychologically-comfortable to use "enum state +
union value" from the beginning, than to integrate
std::variant with feeling that it implies checks that I
can never get rid of</span></span><span lang=3D"en"><span><=
span
lang=3D"en"><span> (even in cases when inner type is
guaranteed by outer logic).</span></span></span></span>
<p><span lang=3D"en"><span><span lang=3D"en"><span>Besides that
the same your argument can be applied for
std::optional too =E2=80=94 "</span></span></span></s=
pan><span
lang=3D"en"><span><span lang=3D"en"><span>if you didn't wan=
t
checking, you'd be using a `T value` instead of
`std::optional<T> value`</span></span></span></=
span><span
lang=3D"en"><span><span lang=3D"en"><span><span lang=3D"en"=
><span><span
lang=3D"en"><span>"</span></span></span></span>=
,
right? (But no, we still have checkless
`std::optional::operator*` =E2=80=94 because there is=
no
need to check again in `if (o) {=E2=80=A6; f(*o);
=E2=80=A6;}`-like cases, for example.)<br>
</span></span></span></span></p>
<p><span lang=3D"en"><span><span lang=3D"en"><span>"</span></sp=
an></span></span><span
lang=3D"en"><span><span lang=3D"en"><span>you're supposed t=
o
be visiting it and acting on it that way" =E2=80=94 a=
m I
supposed to act _only_ in that way?<br>
</span></span></span></span></p>
</div>
</blockquote>
<div><br>
</div>
<div>I generally consider the use of `get` on a variant<i> at
all</i> to be a code-smell. A function which takes a variant
is a function that is expected to be able to operate correctly
on<i> all</i> of the possible values in the variant. And the
most effective way to achieve that is to use visitation when
you want to access the member. By using `get`, you're saying
that the code in question simply can't handle the other
possible states of the variant. That's the wrong way to use a
variant.</div>
<div><br>
</div>
<div>Visitation fixes so many problems. It makes it statically
impossible for you to forget to handle a state. It makes your
code more readable (to a degree), since you can use the
variant value like it were a regular value. It discourages
lots of conditions. And so forth.</div>
<div><br>
</div>
<div>That's not to say that `get` is bad. It's simply not a tool
that should be in such frequent use that not having an
unchecked version is a legitimate problem.</div>
</div>
</blockquote>
Looks like oversimplification for me.<br>
The set of real-life cases is much more rich.<br>
E.g. we can have an std::variant field in a class =E2=80=94 and some
more-universal methods (that handle all states combinations) in the
class can call some more-specialized ones (that handle only specific
state combinations). Of course, we can cache references (pointers)
to members of std::variant and pass them from method to method (in
addition to passing `this`, which already has access to the whole
std::variant field), but it decreases aesthetics of the code (and
additionally looks redundant at first glance, because with the most
expected (but not guaranteed, of course) implementation of variant,
the pointer to the member would have fixed offset from the pointer
to the whole std::variant).<br>
<br>
<blockquote type=3D"cite"
cite=3D"mid:7c323bd5-b9c7-4be4-971d-f617c6341665@isocpp.org">
<div dir=3D"ltr">
<div>Consider your example of "<span style=3D"display: inline
!important; float: none; background-color: transparent;
color: rgb(34, 34, 34); font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;">when inner type is
guaranteed by outer logic". How did this "outer logic"
provide this guarantee? Did it create the `variant` with
that state? If so... why did it bundle it in a `variant`,
when it clearly only provides an object of a specific type?
Did the "outer logic" already do the test? If so, why did it
not unpack the object directly when it did that test, and
just pass the object of the right type? <span
style=3D"background-color: transparent; border-bottom-color:
rgb(34, 34, 34); border-bottom-style: none;
border-bottom-width: 0px; border-image-outset: 0;
border-image-repeat: stretch; border-image-slice: 100%;
border-image-source: none; border-image-width: 1;
border-left-color: rgb(34, 34, 34); border-left-style:
none; border-left-width: 0px; border-right-color: rgb(34,
34, 34); border-right-style: none; border-right-width:
0px; border-top-color: rgb(34, 34, 34); border-top-style:
none; border-top-width: 0px; color: rgb(34, 34, 34);
display: inline; float: none; font-family:
&quot;Arial&quot;,&quot;Helvetica&quot;,sans-=
serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; margin-bottom:
0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;
orphans: 2; padding-bottom: 0px; padding-left: 0px;
padding-right: 0px; padding-top: 0px; text-align: left;
text-decoration: none; text-indent: 0px; text-transform:
none; -webkit-text-stroke-width: 0px; white-space: normal;
word-spacing: 0px;">If the "inner" logic can only handle a
specific state, why is it being given an object that can
assume states it cannot handle?</span>=C2=A0That is, rather
than:</span></div>
<div><span style=3D"display: inline !important; float: none;
background-color: transparent; color: rgb(34, 34, 34);
font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;"><br>
</span></div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); word-wrap: break-word; background-color: rgb(250, 250,
250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: #008;">if</span><span
class=3D"styled-by-prettify" style=3D"color: #660;">(</span=
><span
class=3D"styled-by-prettify" style=3D"color: #008;">var</sp=
an><span
class=3D"styled-by-prettify" style=3D"color: #660;">.</span=
><span
class=3D"styled-by-prettify" style=3D"color: #000;">index</=
span><span
class=3D"styled-by-prettify" style=3D"color: #660;">()</spa=
n><span
class=3D"styled-by-prettify" style=3D"color: #000;"> </span=
><span
class=3D"styled-by-prettify" style=3D"color: #660;">=3D=3D<=
/span><span
class=3D"styled-by-prettify" style=3D"color: #000;">
required_index</span><span class=3D"styled-by-prettify"
style=3D"color: #660;">)</span><span
class=3D"styled-by-prettify" style=3D"color: #000;"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
#660;">{</span><span class=3D"styled-by-prettify"
style=3D"color: #000;"><br>
=C2=A0 </span><span class=3D"styled-by-prettify" style=3D"c=
olor:
#008;">auto</span><span class=3D"styled-by-prettify"
style=3D"color: #000;"> </span><span
class=3D"styled-by-prettify" style=3D"color: #660;">&</=
span><span
class=3D"styled-by-prettify" style=3D"color: #000;">value <=
/span><span
class=3D"styled-by-prettify" style=3D"color: #660;">=3D</sp=
an><span
class=3D"styled-by-prettify" style=3D"color: #000;"> </span=
><span
class=3D"styled-by-prettify" style=3D"color: #008;">get</sp=
an><span
class=3D"styled-by-prettify" style=3D"color: #080;"><req=
uired_index></span><span
class=3D"styled-by-prettify" style=3D"color: #660;">(</span=
><span
class=3D"styled-by-prettify" style=3D"color: #008;">var</sp=
an><span
class=3D"styled-by-prettify" style=3D"color: #660;">);</spa=
n><span
class=3D"styled-by-prettify" style=3D"color: #000;"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
#660;">}</span></div>
</code></div>
<div><span style=3D"display: inline !important; float: none;
background-color: transparent; color: rgb(34, 34, 34);
font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;"><br>
</span></div>
<div><span style=3D"display: inline !important; float: none;
background-color: transparent; color: rgb(34, 34, 34);
font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;">You do this:</span></d=
iv>
<div><span style=3D"display: inline !important; float: none;
background-color: transparent; color: rgb(34, 34, 34);
font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;"><br>
</span></div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); word-wrap: break-word; background-color: rgb(250, 250,
250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: #008;">if</span><span
class=3D"styled-by-prettify" style=3D"color: #660;">(</span=
><span
class=3D"styled-by-prettify" style=3D"color: #008;">auto</s=
pan><span
class=3D"styled-by-prettify" style=3D"color: #000;"> ptr </=
span><span
class=3D"styled-by-prettify" style=3D"color: #660;">=3D</sp=
an><span
class=3D"styled-by-prettify" style=3D"color: #000;"> get_if=
</span><span
class=3D"styled-by-prettify" style=3D"color: #080;"><req=
uired_index></span><span
class=3D"styled-by-prettify" style=3D"color: #660;">(&<=
/span><span
class=3D"styled-by-prettify" style=3D"color: #008;">var</sp=
an><span
class=3D"styled-by-prettify" style=3D"color: #660;">);</spa=
n><span
class=3D"styled-by-prettify" style=3D"color: #000;"> ptr</s=
pan><span
class=3D"styled-by-prettify" style=3D"color: #660;">)</span=
><span
class=3D"styled-by-prettify" style=3D"color: #000;"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
#660;">{</span><span class=3D"styled-by-prettify"
style=3D"color: #000;"><br>
=C2=A0 </span><span class=3D"styled-by-prettify" style=3D"c=
olor:
#800;">//use `ptr`</span><span
class=3D"styled-by-prettify" style=3D"color: #000;"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
#660;">}</span></div>
</code></div>
<div><span style=3D"display: inline !important; float: none;
background-color: transparent; color: rgb(34, 34, 34);
font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;"><br>
</span><span style=3D"display: inline !important; float: none;
background-color: transparent; color: rgb(34, 34, 34);
font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;"></span></div>
<div><span style=3D"display: inline !important; float: none;
background-color: transparent; color: rgb(34, 34, 34);
font-family:
"Arial","Helvetica",sans-serif;
font-size: 13px; font-style: normal; font-variant: normal;
font-weight: 400; letter-spacing: normal; orphans: 2;
text-align: left; text-decoration: none; text-indent: 0px;
text-transform: none; -webkit-text-stroke-width: 0px;
white-space: normal; word-spacing: 0px;">The fundamental
difference between `optional` and `variant` is that the
former only ever has 2 states. The behavior for the
unengaged state will almost always be "do nothing", while
the behavior for the engaged state will be "do something". </sp=
an>Your
code strongly suggests that you're trying to treat a `variant`
like an `optional`. And we have a way to do that: get a
pointer to the member.</div>
</div>
</blockquote>
Yes, I consider variant as a generalization of optional. But (for
some reasons that look bogus for me) the generalization isn't
smooth. IMHO it is better to fix it (even if no so much people feel
practical problems due to that shagginess =E2=80=94 just for aesthetic
reasons at least).<br>
<br>
<blockquote type=3D"cite"
cite=3D"mid:7c323bd5-b9c7-4be4-971d-f617c6341665@isocpp.org">
<div dir=3D"ltr">
<div>Also, I'm curious as to your application where a single
conditional check is sufficient to make the type "(almost)
useless for me". Seriously, is that trivial performance <i>really=
</i>
sufficient to go write your own variant type or to use
something less feature-rich?</div>
</div>
</blockquote>
It's more about consistency and psychology, not about actual
benchmarking yet. I am writing right now a piece of code that with
high probability will be a part of bottleneck. I realize that in
some cases std::variant does redundant checks (at least with the way
I use it). I expect them to be avoidable (as in std::optional and
others), but they aren't. So it's psychologically simpler for me to
throw std::variant out and not to use in the "foundation" (that will
probably be a bottleneck) any things that have _known_ overhead. Not
necessarily variant::get will be a problem (and most probably
something absolutely else will), but I don't like a feeling of
creating future problems when writing the code (i.e. to write a code
with a known and easy-avoidable redundancy, which doesn't brings and
significant improvements into the code aesthetics or some other <span
data-dobid=3D"hdw">tremendous benefits</span>). <br>
<br>
<blockquote type=3D"cite"
cite=3D"mid:7c323bd5-b9c7-4be4-971d-f617c6341665@isocpp.org">
<div dir=3D"ltr">
<div>You're also missing another problem with checked vs.
unchecked operations: consistency.</div>
<div><br>
</div>
<div>In the C++ standard library, the way you tell whether an
operation is checked or unchecked is that the unchecked
operation uses an<i> operator</i>. `vector::operator[]`,
`optional::operator*`, and so on are operators. If you use a
named function, then it is a checked operation. `vector::at`,
`optional::value`, and so forth.</div>
<div><br>
</div>
<div>You can't really have an operator-form of the `variant`
`get` function. After all, you need to provide a template
index/type, and you can't pass something like that as a
function parameter to an operator. After all, operators cannot
take explicit template parameters without calling them by
spelling out the operator
(`variant::operator[]<std::string>(0)`).</div>
</div>
</blockquote>
I never heard about "methods-are-checked, functions-are-unchecked"
rule in stdlib. Is is stated somewhere?<br>
As for me, much more expected understanding of consistency here
would be that every class (where it's applicable) has two ways of
access: checked and unchecked. (If the std::vector and std::optional
had no unchecked access, then I would have no <span id=3D"result_box"
class=3D"short_text" lang=3D"en"><span class=3D"">disturbance about
std::variant =E2=80=94 I'd just see that as style of C++ stdlib; ev=
en if
only std::optional </span></span>had no unchecked access, then
it would look understandable for me (stdlib is old, std::vector
created long before std::optional and std::variant, style changed
since then); but now it looks as breaking its own style.)<br>
And if unchecked things really need to be operators (which I doubt,
even if the such rule exists and wasn't broken yet, it will be
surely be broken at some point of time in future due to the growing
of stdlib and growing of the amount of
strongly-needed-to-be-unchecked things), why not simply the explicit
cast operator? (Ah, you are right, explicit cast operator will allow
only access by type, not by index =E2=80=94 still I don't feel both acc=
ess
by index and .)<br>
<br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/d560a76d-fa64-ed3e-a887-1e340958cfaf%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/d560a76d-fa64-ed3e-a887-1e340958cfaf%=
40gmail.com</a>.<br />
--------------6ABAF1BE4199198796C2C43A--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 16 Jan 2018 14:17:40 -0500
Raw View
--94eb2c057986a803c30562e9950a
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tue, Jan 16, 2018 at 11:35 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksandr Pikozh wrote=
:
>>
>> Well, an object is often used in different ways from different parts of
>> code: more carefree from relatively-rarely-called routines and more
>> optimized from relatively-often-called routines. Therefore it's good for
>> the same tool to support different modes; sometimes I want checking,
>> sometimes I don't (i.e. I want std::variant that keeps its `index`, but
>> sometimes to allow to do the `get`-like thing without internal checks); =
as
>> for me, that's the main goal of C++ =E2=80=94 to support higher-level pr=
ogramming
>> without losing the low-level control. Absence of unchecked operations
>> (comparable to std::optional::operator* and std::vector::operator[]) mak=
es
>> std::variant (almost) useless for me: it looks more
>> psychologically-comfortable to use "enum state + union value" from the
>> beginning, than to integrate std::variant with feeling that it implies
>> checks that I can never get rid of (even in cases when inner type is
>> guaranteed by outer logic).
>>
>> Besides that the same your argument can be applied for std::optional too
>> =E2=80=94 "if you didn't want checking, you'd be using a `T value` inste=
ad of
>> `std::optional<T> value`", right? (But no, we still have checkless
>> `std::optional::operator*` =E2=80=94 because there is no need to check a=
gain in `if
>> (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like cases, for example.)
>>
>> "you're supposed to be visiting it and acting on it that way" =E2=80=94 =
am I
>> supposed to act _only_ in that way?
>>
>
> I generally consider the use of `get` on a variant* at all* to be a
> code-smell. A function which takes a variant is a function that is expect=
ed
> to be able to operate correctly on* all* of the possible values in the
> variant. And the most effective way to achieve that is to use visitation
> when you want to access the member. By using `get`, you're saying that th=
e
> code in question simply can't handle the other possible states of the
> variant. That's the wrong way to use a variant.
>
> Visitation fixes so many problems. It makes it statically impossible for
> you to forget to handle a state. It makes your code more readable (to a
> degree), since you can use the variant value like it were a regular value=
..
> It discourages lots of conditions. And so forth.
>
> That's not to say that `get` is bad. It's simply not a tool that should b=
e
> in such frequent use that not having an unchecked version is a legitimate
> problem.
>
> Consider your example of "when inner type is guaranteed by outer logic".
> How did this "outer logic" provide this guarantee? Did it create the
> `variant` with that state? If so... why did it bundle it in a `variant`,
> when it clearly only provides an object of a specific type? Did the "oute=
r
> logic" already do the test? If so, why did it not unpack the object
> directly when it did that test, and just pass the object of the right typ=
e? If
> the "inner" logic can only handle a specific state, why is it being given
> an object that can assume states it cannot handle? That is, rather than:
>
> if(var.index() =3D=3D required_index)
> {
> auto &value =3D get<required_index>(var);
> }
>
> You do this:
>
> if(auto ptr =3D get_if<required_index>(&var); ptr)
> {
> //use `ptr`
> }
>
> The fundamental difference between `optional` and `variant` is that the
> former only ever has 2 states. The behavior for the unengaged state will
> almost always be "do nothing", while the behavior for the engaged state
> will be "do something". Your code strongly suggests that you're trying to
> treat a `variant` like an `optional`. And we have a way to do that: get a
> pointer to the member.
>
> Also, I'm curious as to your application where a single conditional check
> is sufficient to make the type "(almost) useless for me". Seriously, is
> that trivial performance *really* sufficient to go write your own variant
> type or to use something less feature-rich?
>
> You're also missing another problem with checked vs. unchecked operations=
:
> consistency.
>
> In the C++ standard library, the way you tell whether an operation is
> checked or unchecked is that the unchecked operation uses an* operator*.
> `vector::operator[]`, `optional::operator*`, and so on are operators. If
> you use a named function, then it is a checked operation. `vector::at`,
> `optional::value`, and so forth.
>
The std isn't very consistent, but it does tend to favour the fast over the
safe. It might have been better to make the unsafe operations long/ugly
names, but that would have hurt C++ adoption in the early days.
One attempt at consistency is that (due to pointers) operator* is seen as
"potentially dangerous", so optional wanted to use the same syntax for the
same danger. Great.
Note, however, that variant is using std::get, which was previously
noexcept (for tuple), but can throw for variant - different warning signs
for the same syntax :-(
And they are fundamentally different operations "get one of many" vs "get
the only one, if correct". This unfortunate naming is also why Structured
Bindings check for tuple_size in addition to checking whether get "works"
(ie compiles). std::get should have been called std::tuple_get: to be more
specific, to not steal a general name, and to match tuple_size and
tuple_element. And variant should have used something else.
And optional doesn't use get, it uses value(). (But std::value() would
also be a bad name for std::get_could_throw())
Smart pointers use get, they are also a warning sign (loss of abstraction)
- but a different one from variant (could throw), and different from
optional.value() (also could throw).
Anyhow, someone could easily propose a "unchecked_get" for variant. I
think, in this case, it would need to be an ugly name.
Or call it get_ub() since it could lead to Undefined Behaviour, and who
doesn't want to get that.
--=20
Be seeing you,
Tony
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAOHCbisTJuZcmrJFdvH_YUH5qsEbQQJLBgKtFR0b2gZRg6C=
3Xw%40mail.gmail.com.
--94eb2c057986a803c30562e9950a
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Jan 16, 2018 at 11:35 AM, Nicol Bolas <span dir=3D"ltr"><<a =
href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</=
a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><sp=
an class=3D"">On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksandr =
Pikozh wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
Well, an object is often used in different ways from different parts
of code: more <span lang=3D"en"><span>carefree from relatively-rarely-c=
alled routines and
more optimized from </span></span><span lang=3D"en"><span><span lan=
g=3D"en"><span>relatively-often-called
routines</span></span>. Therefore it's good for the same
tool to support different modes; sometimes I want checking,
sometimes I don't (i.e. I want std::variant that keeps its
`index`, but sometimes to allow to do the `get`-like thing
without internal checks); as for me, that's the main goal of C+=
+
=E2=80=94 to support higher-level programming without losing the
low-level control. Absence of unchecked operations (comparable
to std::optional::operator* and std::vector::operator[]) makes
std::variant (almost) useless for me: it looks more
psychologically-comfortable to use "enum state + union value&q=
uot;
from the beginning, than to integrate std::variant with feeling
that it implies checks that I can never get rid of</span></span><sp=
an lang=3D"en"><span><span lang=3D"en"><span>
(even in cases when inner type is guaranteed by outer
logic).</span></span></span></span>
<p><span lang=3D"en"><span><span lang=3D"en"><span>Besides
that the same your argument can be applied for std::optional
too =E2=80=94 "</span></span></span></span><span lang=3D=
"en"><span><span lang=3D"en"><span>if
you didn't want checking, you'd be using a `T value`
instead of `std::optional<T> value`</span></span></span=
></span><span lang=3D"en"><span><span lang=3D"en"><span><span lang=3D"en"><=
span><span lang=3D"en"><span>"</span></span></span></span>,
right? (But no, we still have checkless
`std::optional::operator*` =E2=80=94 because there is no need=
to
check again in `if (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like c=
ases, for
example.)<br>
</span></span></span></span></p>
<p><span lang=3D"en"><span><span lang=3D"en"><span>"</span></span>=
</span></span><span lang=3D"en"><span><span lang=3D"en"><span>you're
supposed to be visiting it and acting on it that way" =
=E2=80=94 am
I supposed to act _only_ in that way?<br></span></span></span=
></span></p></div></blockquote><div><br></div></span><div>I generally consi=
der the use of `get` on a variant<i> at all</i> to be a code-smell. A funct=
ion which takes a variant is a function that is expected to be able to oper=
ate correctly on<i> all</i> of the possible values in the variant. And the =
most effective way to achieve that is to use visitation when you want to ac=
cess the member. By using `get`, you're saying that the code in questio=
n simply can't handle the other possible states of the variant. That=
9;s the wrong way to use a variant.</div><div><br></div><div>Visitation fix=
es so many problems. It makes it statically impossible for you to forget to=
handle a state. It makes your code more readable (to a degree), since you =
can use the variant value like it were a regular value. It discourages lots=
of conditions. And so forth.</div><div><br></div><div>That's not to sa=
y that `get` is bad. It's simply not a tool that should be in such freq=
uent use that not having an unchecked version is a legitimate problem.</div=
><div><br></div><div>Consider your example of "<span style=3D"display:=
inline!important;float:none;background-color:transparent;color:rgb(34,34,34=
);font-family:"Arial","Helvetica",sans-serif;font-size:=
13px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:n=
ormal;text-align:left;text-decoration:none;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px">when inner type is guaranteed by o=
uter
logic". How did this "outer logic" provide this =
guarantee? Did it create the `variant` with that state? If so... why did it=
bundle it in a `variant`, when it clearly only provides an object of a spe=
cific type? Did the "outer logic" already do the test? If so, why=
did it not unpack the object directly when it did that test, and just pass=
the object of the right type? <span>If the "inner" logic can onl=
y handle a specific state, why is it being given an object that can assume =
states it cannot handle?</span>=C2=A0That is, rather than:</span></div><div=
><span style=3D"display:inline!important;float:none;background-color:transp=
arent;color:rgb(34,34,34);font-family:"Arial","Helvetica&quo=
t;,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-wei=
ght:400;letter-spacing:normal;text-align:left;text-decoration:none;text-ind=
ent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></span=
></div><div class=3D"m_8434276007629405093prettyprint" style=3D"border:1px =
solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,25=
0)"><code class=3D"m_8434276007629405093prettyprint"><div class=3D"m_843427=
6007629405093subprettyprint"><span class=3D"m_8434276007629405093styled-by-=
prettify" style=3D"color:#008">if</span><span class=3D"m_843427600762940509=
3styled-by-prettify" style=3D"color:#660">(</span><span class=3D"m_84342760=
07629405093styled-by-prettify" style=3D"color:#008">var</span><span class=
=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#660">.</span><=
span class=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#000"=
>index</span><span class=3D"m_8434276007629405093styled-by-prettify" style=
=3D"color:#660">()</span><span class=3D"m_8434276007629405093styled-by-pret=
tify" style=3D"color:#000"> </span><span class=3D"m_8434276007629405093styl=
ed-by-prettify" style=3D"color:#660">=3D=3D</span><span class=3D"m_84342760=
07629405093styled-by-prettify" style=3D"color:#000"> required_index</span><=
span class=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#660"=
>)</span><span class=3D"m_8434276007629405093styled-by-prettify" style=3D"c=
olor:#000"><br></span><span class=3D"m_8434276007629405093styled-by-prettif=
y" style=3D"color:#660">{</span><span class=3D"m_8434276007629405093styled-=
by-prettify" style=3D"color:#000"><br>=C2=A0 </span><span class=3D"m_843427=
6007629405093styled-by-prettify" style=3D"color:#008">auto</span><span clas=
s=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#000"> </span>=
<span class=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#660=
">&</span><span class=3D"m_8434276007629405093styled-by-prettify" style=
=3D"color:#000">value </span><span class=3D"m_8434276007629405093styled-by-=
prettify" style=3D"color:#660">=3D</span><span class=3D"m_84342760076294050=
93styled-by-prettify" style=3D"color:#000"> </span><span class=3D"m_8434276=
007629405093styled-by-prettify" style=3D"color:#008">get</span><span class=
=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#080"><requi=
red_index></span><span class=3D"m_8434276007629405093styled-by-prettify"=
style=3D"color:#660">(</span><span class=3D"m_8434276007629405093styled-by=
-prettify" style=3D"color:#008">var</span><span class=3D"m_8434276007629405=
093styled-by-prettify" style=3D"color:#660">);</span><span class=3D"m_84342=
76007629405093styled-by-prettify" style=3D"color:#000"><br></span><span cla=
ss=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#660">}</span=
></div></code></div><div><span style=3D"display:inline!important;float:none=
;background-color:transparent;color:rgb(34,34,34);font-family:"Arial&q=
uot;,"Helvetica",sans-serif;font-size:13px;font-style:normal;font=
-variant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-=
decoration:none;text-indent:0px;text-transform:none;white-space:normal;word=
-spacing:0px"><br></span></div><div><span style=3D"display:inline!important=
;float:none;background-color:transparent;color:rgb(34,34,34);font-family:&q=
uot;Arial","Helvetica",sans-serif;font-size:13px;font-style:=
normal;font-variant:normal;font-weight:400;letter-spacing:normal;text-align=
:left;text-decoration:none;text-indent:0px;text-transform:none;white-space:=
normal;word-spacing:0px">You do this:</span></div><div><span style=3D"displ=
ay:inline!important;float:none;background-color:transparent;color:rgb(34,34=
,34);font-family:"Arial","Helvetica",sans-serif;font-si=
ze:13px;font-style:normal;font-variant:normal;font-weight:400;letter-spacin=
g:normal;text-align:left;text-decoration:none;text-indent:0px;text-transfor=
m:none;white-space:normal;word-spacing:0px"><br></span></div><div class=3D"=
m_8434276007629405093prettyprint" style=3D"border:1px solid rgb(187,187,187=
);word-wrap:break-word;background-color:rgb(250,250,250)"><code class=3D"m_=
8434276007629405093prettyprint"><div class=3D"m_8434276007629405093subprett=
yprint"><span class=3D"m_8434276007629405093styled-by-prettify" style=3D"co=
lor:#008">if</span><span class=3D"m_8434276007629405093styled-by-prettify" =
style=3D"color:#660">(</span><span class=3D"m_8434276007629405093styled-by-=
prettify" style=3D"color:#008">auto</span><span class=3D"m_8434276007629405=
093styled-by-prettify" style=3D"color:#000"> ptr </span><span class=3D"m_84=
34276007629405093styled-by-prettify" style=3D"color:#660">=3D</span><span c=
lass=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#000"> get_=
if</span><span class=3D"m_8434276007629405093styled-by-prettify" style=3D"c=
olor:#080"><required_index></span><span class=3D"m_843427600762940509=
3styled-by-prettify" style=3D"color:#660">(&</span><span class=3D"m_843=
4276007629405093styled-by-prettify" style=3D"color:#008">var</span><span cl=
ass=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#660">);</sp=
an><span class=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#=
000"> ptr</span><span class=3D"m_8434276007629405093styled-by-prettify" sty=
le=3D"color:#660">)</span><span class=3D"m_8434276007629405093styled-by-pre=
ttify" style=3D"color:#000"><br></span><span class=3D"m_8434276007629405093=
styled-by-prettify" style=3D"color:#660">{</span><span class=3D"m_843427600=
7629405093styled-by-prettify" style=3D"color:#000"><br>=C2=A0 </span><span =
class=3D"m_8434276007629405093styled-by-prettify" style=3D"color:#800">//us=
e `ptr`</span><span class=3D"m_8434276007629405093styled-by-prettify" style=
=3D"color:#000"><br></span><span class=3D"m_8434276007629405093styled-by-pr=
ettify" style=3D"color:#660">}</span></div></code></div><div><span style=3D=
"display:inline!important;float:none;background-color:transparent;color:rgb=
(34,34,34);font-family:"Arial","Helvetica",sans-serif;f=
ont-size:13px;font-style:normal;font-variant:normal;font-weight:400;letter-=
spacing:normal;text-align:left;text-decoration:none;text-indent:0px;text-tr=
ansform:none;white-space:normal;word-spacing:0px"><br></span><span style=3D=
"display:inline!important;float:none;background-color:transparent;color:rgb=
(34,34,34);font-family:"Arial","Helvetica",sans-serif;f=
ont-size:13px;font-style:normal;font-variant:normal;font-weight:400;letter-=
spacing:normal;text-align:left;text-decoration:none;text-indent:0px;text-tr=
ansform:none;white-space:normal;word-spacing:0px"></span></div><div><span s=
tyle=3D"display:inline!important;float:none;background-color:transparent;co=
lor:rgb(34,34,34);font-family:"Arial","Helvetica",sans-=
serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;=
letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px;=
text-transform:none;white-space:normal;word-spacing:0px">The fundamental di=
fference between `optional` and `variant` is that the former only ever has =
2 states. The behavior for the unengaged state will almost always be "=
do nothing", while the behavior for the engaged state will be "do=
something". </span>Your code strongly suggests that you're trying=
to treat a `variant` like an `optional`. And we have a way to do that: get=
a pointer to the member.</div><div><b><br></b></div><div>Also, I'm cur=
ious as to your application where a single conditional check is sufficient =
to make the type "(almost) useless for me". Seriously, is that tr=
ivial performance <i>really</i> sufficient to go write your own variant typ=
e or to use something less feature-rich?</div><div><br></div><div>You'r=
e also missing another problem with checked vs. unchecked operations: consi=
stency.</div><div><br></div><div>In the C++ standard library, the way you t=
ell whether an operation is checked or unchecked is that the unchecked oper=
ation uses an<i> operator</i>. `vector::operator[]`, `optional::operator*`,=
and so on are operators. If you use a named function, then it is a checked=
operation. `vector::at`, `optional::value`, and so forth.</div></div></blo=
ckquote><div><br></div><div><br></div><div>The std isn't very consisten=
t, but it does tend to favour the fast over the safe.=C2=A0 It might have b=
een better to make the unsafe operations long/ugly names, but that would ha=
ve hurt C++ adoption in the early days.</div><div><br></div><div>One attemp=
t at consistency is that (due to pointers) operator* is seen as "poten=
tially dangerous", so optional wanted to use the same syntax for the s=
ame danger. Great.</div><div><br></div><div>Note, however, that variant is =
using std::get, which was previously noexcept (for tuple), but can throw fo=
r variant - different warning signs for the same syntax :-(</div><div><br><=
/div><div>And they are fundamentally different operations "get one of =
many" vs "get the only one, if correct".=C2=A0 This unfortun=
ate naming is also why Structured Bindings check for tuple_size in addition=
to checking whether get "works" (ie compiles).=C2=A0 std::get sh=
ould have been called std::tuple_get: to be more specific, to not steal a g=
eneral name, and to match tuple_size and tuple_element. And variant should =
have used something else.</div><div><br></div><div>And optional doesn't=
use get, it uses value().=C2=A0 (But std::value() would also be a bad name=
for std::get_could_throw())</div><div>Smart pointers use get, they are als=
o a warning sign (loss of abstraction) - but a different one from variant (=
could throw), and different from optional.value() (also could throw).<br></=
div><div><br></div><div><br></div><div>Anyhow, someone could easily propose=
a "unchecked_get" for variant.=C2=A0 I think, in this case, it w=
ould need to be an ugly name.</div><div>Or call it get_ub() since it could =
lead to Undefined Behaviour, and who doesn't want to get that.</div><di=
v><br></div><br></div>-- <br><div class=3D"gmail_signature" data-smartmail=
=3D"gmail_signature"><div dir=3D"ltr"><div>Be seeing you,<br></div>Tony<br>=
</div></div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAOHCbisTJuZcmrJFdvH_YUH5qsEbQQJLBgKt=
FR0b2gZRg6C3Xw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOHCbisTJuZcmrJF=
dvH_YUH5qsEbQQJLBgKtFR0b2gZRg6C3Xw%40mail.gmail.com</a>.<br />
--94eb2c057986a803c30562e9950a--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Tue, 16 Jan 2018 21:34:48 +0100
Raw View
This is a multi-part message in MIME format.
--------------5ACB230FB53D832FE9B41952
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 16/01/2018 =C3=A0 07:33, Oleksandr Pikozh a =C3=A9crit=C2=A0:
>
> In std::variant we have:
> - ??? =E2=80=94 doesn't check whether a variant contains specified index/=
type;
> - method get =E2=80=94 throws std::bad_variant_access when a variant does=
n't=20
> contain specified index/type.
>
> Why we don't have any fast (unchecked) ways to access std::variant?=20
> Assuming context when user has already checked for presence of=20
> required item somehow and now needs the fastest access (i.e. he agrees=20
> to get UB when absent).
>
I believe the standard committee could considered it if you have a=20
motivating use case that cannot be managed with std::visit.
std::visit is a safe tool. Adding an unsafe tool when a safe one could=20
be used wouldn't help. We need a use case that will be more efficient=20
with your unsafe function.
Vicente
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/883fa674-b1f2-53ef-6a29-806b43e60a0f%40wanadoo.f=
r.
--------------5ACB230FB53D832FE9B41952
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
<div class=3D"moz-cite-prefix">Le 16/01/2018 =C3=A0 07:33, Oleksandr Pi=
kozh
a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:959f20d3-0455-951d-70fe-60bf0110cad7@gmail.com"><br>
In std::variant we have:
<br>
- ??? =E2=80=94 doesn't check whether a variant contains specified
index/type;
<br>
- method get =E2=80=94 throws std::bad_variant_access when a variant
doesn't contain specified index/type.
<br>
<br>
Why we don't have any fast (unchecked) ways to access
std::variant? Assuming context when user has already checked for
presence of required item somehow and now needs the fastest access
(i.e. he agrees to get UB when absent).
<br>
<br>
</blockquote>
<p><font size=3D"+1">I believe the standard committee could considered
it if you have a motivating use case that cannot be managed with
std::visit.</font></p>
<p><br>
<font size=3D"+1"><font size=3D"+1">std::visit is a safe tool. Adding
an unsafe tool when a safe one could be used wouldn't help. We
need a use case that will be more efficient with your unsafe
function.<br>
</font></font></p>
<p><font size=3D"+1">Vicente</font><br>
</p>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/883fa674-b1f2-53ef-6a29-806b43e60a0f%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/883fa674-b1f2-53ef-6a29-806b43e60a0f=
%40wanadoo.fr</a>.<br />
--------------5ACB230FB53D832FE9B41952--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Tue, 16 Jan 2018 21:37:51 +0100
Raw View
Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9crit=C2=A0:
> While it's not a bad idea (pattern matching in other
> languages naturally support this use), in practise
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.html
>
> may be easier to use.
>
It is weird. The committee required to remove from expected<T,E> every=20
monadic operation. Now we have a paper that request the addition of the=20
monadic operations to optional. Not that I'm against this member=20
function approach, but we should be coherent.
Vicente
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/96371617-d65f-f1a7-4b17-380201fc8dc9%40wanadoo.f=
r.
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 16 Jan 2018 16:31:41 -0500
Raw View
--94eb2c0af81aeb75850562eb7470
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tue, Jan 16, 2018 at 3:37 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
> Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9crit :
>
>> While it's not a bad idea (pattern matching in other
>> languages naturally support this use), in practise
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.html
>>
>> may be easier to use.
>>
>> It is weird. The committee required to remove from expected<T,E> every
> monadic operation. Now we have a paper that request the addition of the
> monadic operations to optional. Not that I'm against this member function
> approach, but we should be coherent.
>
> Vicente
>
>
It may be that the committee wanted expected<> to get in first, then add
monadic later. Like optional.
Or it may just be that the committee is not one person, but a bunch, and it
changes "its" mind regularly.
--=20
Be seeing you,
Tony
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAOHCbivhHe%2B5tiTCT%2BzMByX_U46sSFYKPhiQYHcJmxb=
qCwgUsA%40mail.gmail.com.
--94eb2c0af81aeb75850562eb7470
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, Jan 16, 2018 at 3:37 PM, Vicente J. Botet Escriba <span dir=3D"=
ltr"><<a href=3D"mailto:vicente.botet@wanadoo.fr" target=3D"_blank">vice=
nte.botet@wanadoo.fr</a>></span> wrote:<br><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><span class=3D"">Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9crit=C2=
=A0:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
While it's not a bad idea (pattern matching in other<br>
languages naturally support this use), in practise<br>
<br>
<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.=
html" rel=3D"noreferrer" target=3D"_blank">http://www.open-std.org/jtc1/s<w=
br>c22/wg21/docs/papers/2017/p079<wbr>8r0.html</a><br>
<br>
may be easier to use.<br>
<br>
</blockquote></span>
It is weird. The committee required to remove from expected<T,E> ever=
y monadic operation. Now we have a paper that request the addition of the m=
onadic operations to optional. Not that I'm against this member functio=
n approach, but we should be coherent.<br>
<br>
Vicente<span class=3D""><br>
</span><br></blockquote></div></div><div class=3D"gmail_extra"><br></div><d=
iv class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">It may be tha=
t the committee wanted expected<> to get in first, then add monadic l=
ater.=C2=A0 Like optional.</div><div class=3D"gmail_extra">Or it may just b=
e that the committee is not one person, but a bunch, and it changes "i=
ts" mind regularly.</div><div class=3D"gmail_extra"><br></div><div cla=
ss=3D"gmail_extra">-- <br><div class=3D"gmail_signature" data-smartmail=3D"=
gmail_signature"><div dir=3D"ltr"><div>Be seeing you,<br></div>Tony<br></di=
v></div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAOHCbivhHe%2B5tiTCT%2BzMByX_U46sSFYK=
PhiQYHcJmxbqCwgUsA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOHCbivhHe%2=
B5tiTCT%2BzMByX_U46sSFYKPhiQYHcJmxbqCwgUsA%40mail.gmail.com</a>.<br />
--94eb2c0af81aeb75850562eb7470--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 16 Jan 2018 14:29:12 -0800 (PST)
Raw View
------=_Part_3580_1546404219.1516141752526
Content-Type: multipart/alternative;
boundary="----=_Part_3581_24942960.1516141752526"
------=_Part_3581_24942960.1516141752526
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tuesday, January 16, 2018 at 4:31:48 PM UTC-5, Tony V E wrote:
>
>
>
> On Tue, Jan 16, 2018 at 3:37 PM, Vicente J. Botet Escriba <
> vicent...@wanadoo.fr <javascript:>> wrote:
>
>> Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9crit :
>>
>>> While it's not a bad idea (pattern matching in other
>>> languages naturally support this use), in practise
>>>
>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.html
>>>
>>> may be easier to use.
>>>
>>> It is weird. The committee required to remove from expected<T,E> every=
=20
>> monadic operation. Now we have a paper that request the addition of the=
=20
>> monadic operations to optional. Not that I'm against this member functio=
n=20
>> approach, but we should be coherent.
>>
>> Vicente
>>
>>
>
> It may be that the committee wanted expected<> to get in first, then add=
=20
> monadic later. Like optional.
> Or it may just be that the committee is not one person, but a bunch, and=
=20
> it changes "its" mind regularly.
>
Or maybe it's just one paper, and a paper being written doesn't mean it's=
=20
gonna happen.
>
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/7661a29d-c8ca-43b7-8899-659aa6cfe5b5%40isocpp.or=
g.
------=_Part_3581_24942960.1516141752526
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, January 16, 2018 at 4:31:48 PM UTC-5, =
Tony V E wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><br><div><br><div class=3D"gmail_quote">On Tue, Jan 16, 2018 at 3:37 PM, =
Vicente J. Botet Escriba <span dir=3D"ltr"><<a onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofoll=
ow" gdf-obfuscated-mailto=3D"GrVzah3xAQAJ">vicent...@wanadoo.fr</a>></sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><span>Le 16/01/2018 =C3=A0 16:=
38, Zhihao Yuan a =C3=A9crit=C2=A0:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
While it's not a bad idea (pattern matching in other<br>
languages naturally support this use), in practise<br>
<br>
<a onmousedown=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2=
F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0798r0.=
html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE0umZmplbb2zrP2SNCVIAVPOBeJA&#=
39;;return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\x=
3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017=
%2Fp0798r0.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE0umZmplbb2zrP2SNCV=
IAVPOBeJA';return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21=
/docs/papers/2017/p0798r0.html" target=3D"_blank" rel=3D"nofollow">http://w=
ww.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2017/<wbr>p0798r0.html</a><=
br>
<br>
may be easier to use.<br>
<br>
</blockquote></span>
It is weird. The committee required to remove from expected<T,E> ever=
y monadic operation. Now we have a paper that request the addition of the m=
onadic operations to optional. Not that I'm against this member functio=
n approach, but we should be coherent.<br>
<br>
Vicente<span><br>
</span><br></blockquote></div></div><div><br></div><div><br></div><div>It m=
ay be that the committee wanted expected<> to get in first, then add =
monadic later.=C2=A0 Like optional.</div><div>Or it may just be that the co=
mmittee is not one person, but a bunch, and it changes "its" mind=
regularly.</div></div></blockquote><div><br></div><div>Or maybe it's j=
ust one paper, and a paper being written doesn't mean it's gonna ha=
ppen.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><div>
</div></div>
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/7661a29d-c8ca-43b7-8899-659aa6cfe5b5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/7661a29d-c8ca-43b7-8899-659aa6cfe5b5=
%40isocpp.org</a>.<br />
------=_Part_3581_24942960.1516141752526--
------=_Part_3580_1546404219.1516141752526--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 16 Jan 2018 15:38:00 -0800 (PST)
Raw View
------=_Part_8486_523311757.1516145880373
Content-Type: multipart/alternative;
boundary="----=_Part_8487_156567537.1516145880373"
------=_Part_8487_156567537.1516145880373
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tuesday, January 16, 2018 at 1:02:56 PM UTC-5, Oleksandr Pikozh wrote:
>
> On 16.01.18 18:35, Nicol Bolas wrote:
>
> On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksandr Pikozh wrote=
:=20
>>
>> Well, an object is often used in different ways from different parts of=
=20
>> code: more carefree from relatively-rarely-called routines and more=20
>> optimized from relatively-often-called routines. Therefore it's good for=
=20
>> the same tool to support different modes; sometimes I want checking,=20
>> sometimes I don't (i.e. I want std::variant that keeps its `index`, but=
=20
>> sometimes to allow to do the `get`-like thing without internal checks); =
as=20
>> for me, that's the main goal of C++ =E2=80=94 to support higher-level pr=
ogramming=20
>> without losing the low-level control. Absence of unchecked operations=20
>> (comparable to std::optional::operator* and std::vector::operator[]) mak=
es=20
>> std::variant (almost) useless for me: it looks more=20
>> psychologically-comfortable to use "enum state + union value" from the=
=20
>> beginning, than to integrate std::variant with feeling that it implies=
=20
>> checks that I can never get rid of (even in cases when inner type is=20
>> guaranteed by outer logic).=20
>>
>> Besides that the same your argument can be applied for std::optional too=
=20
>> =E2=80=94 "if you didn't want checking, you'd be using a `T value` inste=
ad of=20
>> `std::optional<T> value`", right? (But no, we still have checkless=20
>> `std::optional::operator*` =E2=80=94 because there is no need to check a=
gain in `if=20
>> (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like cases, for example.)
>>
>> "you're supposed to be visiting it and acting on it that way" =E2=80=94 =
am I=20
>> supposed to act _only_ in that way?
>>
>
> I generally consider the use of `get` on a variant* at all* to be a=20
> code-smell. A function which takes a variant is a function that is expect=
ed=20
> to be able to operate correctly on* all* of the possible values in the=20
> variant. And the most effective way to achieve that is to use visitation=
=20
> when you want to access the member. By using `get`, you're saying that th=
e=20
> code in question simply can't handle the other possible states of the=20
> variant. That's the wrong way to use a variant.
>
> Visitation fixes so many problems. It makes it statically impossible for=
=20
> you to forget to handle a state. It makes your code more readable (to a=
=20
> degree), since you can use the variant value like it were a regular value=
..=20
> It discourages lots of conditions. And so forth.
>
> That's not to say that `get` is bad. It's simply not a tool that should b=
e=20
> in such frequent use that not having an unchecked version is a legitimate=
=20
> problem.
>
> Looks like oversimplification for me.
> The set of real-life cases is much more rich.
> E.g. we can have an std::variant field in a class =E2=80=94 and some=20
> more-universal methods (that handle all states combinations) in the class=
=20
> can call some more-specialized ones (that handle only specific state=20
> combinations).
>
Yeah, that sounds like broken code just* waiting* to happen. Such code=20
would be far safer if it were passed a reference to the object it's=20
actually working on, rather than being based on some assumption about it.=
=20
Yes, I know those are private functions, but you're making it way too easy=
=20
to accidentally do the wrong thing with your private interface.
Of course, we can cache references (pointers) to members of std::variant=20
> and pass them from method to method (in addition to passing `this`, which=
=20
> already has access to the whole std::variant field), but it decreases=20
> aesthetics of the code (and additionally looks redundant at first glance,=
=20
> because with the most expected (but not guaranteed, of course)=20
> implementation of variant, the pointer to the member would have fixed=20
> offset from the pointer to the whole std::variant).
>
> Consider your example of "when inner type is guaranteed by outer logic".=
=20
> How did this "outer logic" provide this guarantee? Did it create the=20
> `variant` with that state? If so... why did it bundle it in a `variant`,=
=20
> when it clearly only provides an object of a specific type? Did the "oute=
r=20
> logic" already do the test? If so, why did it not unpack the object=20
> directly when it did that test, and just pass the object of the right typ=
e? If=20
> the "inner" logic can only handle a specific state, why is it being given=
=20
> an object that can assume states it cannot handle? That is, rather than:
>
> if(var.index() =3D=3D required_index)
> {
> auto &value =3D get<required_index>(var);
> }
>
> You do this:
>
> if(auto ptr =3D get_if<required_index>(&var); ptr)
> {
> //use `ptr`
> }
>
> The fundamental difference between `optional` and `variant` is that the=
=20
> former only ever has 2 states. The behavior for the unengaged state will=
=20
> almost always be "do nothing", while the behavior for the engaged state=
=20
> will be "do something". Your code strongly suggests that you're trying to=
=20
> treat a `variant` like an `optional`. And we have a way to do that: get a=
=20
> pointer to the member.
>
> Yes, I consider variant as a generalization of optional.
>
That's like saying you see an array of integers as a generalization of an=
=20
integer. I mean yeah, you can see it that way. But you don't use one in the=
=20
places you'd use the other, and you don't usually use one in any way=20
resembling the way you use the other.
The use cases for these types are so broadly disparate that they don't need=
=20
to have the same interface.
But (for some reasons that look bogus for me) the generalization isn't=20
> smooth. IMHO it is better to fix it (even if no so much people feel=20
> practical problems due to that shagginess =E2=80=94 just for aesthetic re=
asons at=20
> least).
>
> Also, I'm curious as to your application where a single conditional check=
=20
> is sufficient to make the type "(almost) useless for me". Seriously, is=
=20
> that trivial performance *really* sufficient to go write your own variant=
=20
> type or to use something less feature-rich?
>
> It's more about consistency and psychology, not about actual benchmarking=
=20
> yet. I am writing right now a piece of code that with high probability wi=
ll=20
> be a part of bottleneck. I realize that in some cases std::variant does=
=20
> redundant checks (at least with the way I use it). I expect them to be=20
> avoidable (as in std::optional and others), but they aren't. So it's=20
> psychologically simpler for me to throw std::variant out and not to use i=
n=20
> the "foundation" (that will probably be a bottleneck) any things that hav=
e=20
> _known_ overhead.
>
So it's "psychologically simpler" for you to spend a bunch of time coding=
=20
something that you might not need, rather than using an off-the-shelf tool=
=20
that does exactly what you need just *possibly* slower. Perhaps you're=20
focusing too much on your psychology and not enough on what causes your=20
project to actually get done.
I understand the kind of thing you're talking about. I get that impulse=20
every now and then too, even when I'm coding in non-C++ languages. That=20
micro-optimization voice that says, "ugh, do I really need a conditional=20
branch here? Can't I find a clever way to avoid that?" I even had to stop=
=20
myself from digging through Lua manuals and such to find a function that=20
could concatenate a bunch of strings without wrapping them in a table.
You would be surprised how much telling that voice to shut up improves your=
=20
productivity. *Without* making your code materially slower.
Just consider a variant example:
if(auto var =3D get_variant(); var.index() =3D=3D 3)
{
auto &value =3D get<3>(var);
}
Well, the `get` function is visible to the compiler, as is the `index`=20
function. And `3` is a constant expression, so it is visible to the=20
compiler too.
Which means the compiler has 100% of the information available in the local=
=20
scope to recognize that `get` will do the same check you just did. So if it=
=20
inlines the `get` call, it is at least theoretically possible for the=20
compiler to optimize out the second test post-inlining.
Does that mean it* certainly* will? No. But Godbolt says GCC does.=20
<https://godbolt.org/g/DReC5Y> It completely optimizes out the test and=20
exception throwing.
Now obviously this is a highly simplified case, and there will be cases=20
where compilers can't reasonably tell. But the farther the initial test is=
=20
from where it gets used, the more likely it is that you will accidentally=
=20
call it incorrectly.
Not necessarily variant::get will be a problem (and most probably something=
=20
> absolutely else will), but I don't like a feeling of creating future=20
> problems when writing the code (i.e. to write a code with a known and=20
> easy-avoidable redundancy, which doesn't brings and significant=20
> improvements into the code aesthetics or some other tremendous benefits).=
=20
>
> You're also missing another problem with checked vs. unchecked operations=
:=20
> consistency.
>
> In the C++ standard library, the way you tell whether an operation is=20
> checked or unchecked is that the unchecked operation uses an* operator*.=
=20
> `vector::operator[]`, `optional::operator*`, and so on are operators. If=
=20
> you use a named function, then it is a checked operation. `vector::at`,=
=20
> `optional::value`, and so forth.
>
> You can't really have an operator-form of the `variant` `get` function.=
=20
> After all, you need to provide a template index/type, and you can't pass=
=20
> something like that as a function parameter to an operator. After all,=20
> operators cannot take explicit template parameters without calling them b=
y=20
> spelling out the operator (`variant::operator[]<std::string>(0)`).
>
> I never heard about "methods-are-checked, functions-are-unchecked" rule i=
n=20
> stdlib. Is is stated somewhere?=20
>
As for me, much more expected understanding of consistency here would be=20
> that every class (where it's applicable) has two ways of access: checked=
=20
> and unchecked. (If the std::vector and std::optional had no unchecked=20
> access, then I would have no disturbance about std::variant =E2=80=94 I'd=
just=20
> see that as style of C++ stdlib; even if only std::optional had no=20
> unchecked access, then it would look understandable for me (stdlib is old=
,=20
> std::vector created long before std::optional and std::variant, style=20
> changed since then); but now it looks as breaking its own style.)
>
And if unchecked things really need to be operators (which I doubt, even if=
=20
> the such rule exists and wasn't broken yet, it will be surely be broken a=
t=20
> some point of time in future due to the growing of stdlib and growing of=
=20
> the amount of strongly-needed-to-be-unchecked things), why not simply the=
=20
> explicit cast operator? (Ah, you are right, explicit cast operator will=
=20
> allow only access by type, not by index =E2=80=94 still I don't feel both=
access by=20
> index and .)
>
If you have a legitimate reason to need to have unchecked access to a=20
variant, whatever reasoning you use applies just as well to unchecked=20
access by index. Just because you personally doesn't use it doesn't mean=20
that other people wanting the same thing don't.
Whatever the solution is, it should not make access-by-index a second-class=
=20
feature of `variant`. Some people really need that to work.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/5edea79c-9249-4d24-b6b1-6c4b4f0d4e0c%40isocpp.or=
g.
------=_Part_8487_156567537.1516145880373
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, January 16, 2018 at 1:02:56 PM UTC-5, Oleksand=
r Pikozh wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
On 16.01.18 18:35, Nicol Bolas wrote:<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5,
Oleksandr Pikozh wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000"> Well, an object is
often used in different ways from different parts of code:
more <span lang=3D"en"><span>carefree from
relatively-rarely-called routines and more optimized
from </span></span><span lang=3D"en"><span><span lang=3D"en=
"><span>relatively-often-called routines</span></span>.
Therefore it's good for the same tool to support
different modes; sometimes I want checking, sometimes I
don't (i.e. I want std::variant that keeps its `index`,
but sometimes to allow to do the `get`-like thing
without internal checks); as for me, that's the main
goal of C++ =E2=80=94 to support higher-level programming
without losing the low-level control. Absence of
unchecked operations (comparable to
std::optional::operator* and std::vector::operator[])
makes std::variant (almost) useless for me: it looks
more psychologically-comfortable to use "enum state +
union value" from the beginning, than to integrate
std::variant with feeling that it implies checks that I
can never get rid of</span></span><span lang=3D"en"><span><=
span lang=3D"en"><span> (even in cases when inner type is
guaranteed by outer logic).</span></span></span></span>
<p><span lang=3D"en"><span><span lang=3D"en"><span>Besides that
the same your argument can be applied for
std::optional too =E2=80=94 "</span></span></spa=
n></span><span lang=3D"en"><span><span lang=3D"en"><span>if you didn't =
want
checking, you'd be using a `T value` instead of
`std::optional<T> value`</span></span></span></=
span><span lang=3D"en"><span><span lang=3D"en"><span><span lang=3D"en"><spa=
n><span lang=3D"en"><span>"</span></span></span></span>,
right? (But no, we still have checkless
`std::optional::operator*` =E2=80=94 because there is=
no
need to check again in `if (o) {=E2=80=A6; f(*o);
=E2=80=A6;}`-like cases, for example.)<br>
</span></span></span></span></p>
<p><span lang=3D"en"><span><span lang=3D"en"><span>"</span=
></span></span></span><span lang=3D"en"><span><span lang=3D"en"><span>you&#=
39;re supposed to
be visiting it and acting on it that way" =E2=80=
=94 am I
supposed to act _only_ in that way?<br>
</span></span></span></span></p>
</div>
</blockquote>
<div><br>
</div>
<div>I generally consider the use of `get` on a variant<i> at
all</i> to be a code-smell. A function which takes a variant
is a function that is expected to be able to operate correctly
on<i> all</i> of the possible values in the variant. And the
most effective way to achieve that is to use visitation when
you want to access the member. By using `get`, you're saying
that the code in question simply can't handle the other
possible states of the variant. That's the wrong way to use a
variant.</div>
<div><br>
</div>
<div>Visitation fixes so many problems. It makes it statically
impossible for you to forget to handle a state. It makes your
code more readable (to a degree), since you can use the
variant value like it were a regular value. It discourages
lots of conditions. And so forth.</div>
<div><br>
</div>
<div>That's not to say that `get` is bad. It's simply not a=
tool
that should be in such frequent use that not having an
unchecked version is a legitimate problem.</div>
</div>
</blockquote>
Looks like oversimplification for me.<br>
The set of real-life cases is much more rich.<br>
E.g. we can have an std::variant field in a class =E2=80=94 and some
more-universal methods (that handle all states combinations) in the
class can call some more-specialized ones (that handle only specific
state combinations).</div></blockquote><div><br></div><div>Yeah, that s=
ounds like broken code just<i> waiting</i> to happen. Such code would be fa=
r safer if it were passed a reference to the object it's actually worki=
ng on, rather than being based on some assumption about it. Yes, I know tho=
se are private functions, but you're making it way too easy to accident=
ally do the wrong thing with your private interface.</div><div><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D=
"#000000">Of course, we can cache references (pointers)
to members of std::variant and pass them from method to method (in
addition to passing `this`, which already has access to the whole
std::variant field), but it decreases aesthetics of the code (and
additionally looks redundant at first glance, because with the most
expected (but not guaranteed, of course) implementation of variant,
the pointer to the member would have fixed offset from the pointer
to the whole std::variant).<br>
<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>Consider your example of "<span style=3D"display:inline!i=
mportant;float:none;background-color:transparent;color:rgb(34,34,34);font-f=
amily:"Arial","Helvetica",sans-serif;font-size:13px;fon=
t-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;te=
xt-align:left;text-decoration:none;text-indent:0px;text-transform:none;whit=
e-space:normal;word-spacing:0px">when inner type is
guaranteed by outer logic". How did this "outer logic=
"
provide this guarantee? Did it create the `variant` with
that state? If so... why did it bundle it in a `variant`,
when it clearly only provides an object of a specific type?
Did the "outer logic" already do the test? If so, why=
did it
not unpack the object directly when it did that test, and
just pass the object of the right type? <span>If the "inne=
r" logic can only handle a
specific state, why is it being given an object that can
assume states it cannot handle?</span>=C2=A0That is, rather
than:</span></div>
<div><span style=3D"display:inline!important;float:none;background-=
color:transparent;color:rgb(34,34,34);font-family:"Arial","H=
elvetica",sans-serif;font-size:13px;font-style:normal;font-variant:nor=
mal;font-weight:400;letter-spacing:normal;text-align:left;text-decoration:n=
one;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
"><br>
</span></div>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-wor=
d;background-color:rgb(250,250,250)"><code>
<div><span style=3D"color:#008">if</span><span style=3D"color:#=
660">(</span><span style=3D"color:#008">var</span><span style=3D"color:#660=
">.</span><span style=3D"color:#000">index</span><span style=3D"color:#660"=
>()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D=
=3D</span><span style=3D"color:#000">
required_index</span><span style=3D"color:#660">)</span><sp=
an style=3D"color:#000"><br>
</span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>
=C2=A0 </span><span style=3D"color:#008">auto</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">&</span><span st=
yle=3D"color:#000">value </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> </span><span style=3D"color:#008">get</span><span sty=
le=3D"color:#080"><required_index></span><span style=3D"color:#660">(=
</span><span style=3D"color:#008">var</span><span style=3D"color:#660">);</=
span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span></div>
</code></div>
<div><span style=3D"display:inline!important;float:none;background-=
color:transparent;color:rgb(34,34,34);font-family:"Arial","H=
elvetica",sans-serif;font-size:13px;font-style:normal;font-variant:nor=
mal;font-weight:400;letter-spacing:normal;text-align:left;text-decoration:n=
one;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
"><br>
</span></div>
<div><span style=3D"display:inline!important;float:none;background-=
color:transparent;color:rgb(34,34,34);font-family:"Arial","H=
elvetica",sans-serif;font-size:13px;font-style:normal;font-variant:nor=
mal;font-weight:400;letter-spacing:normal;text-align:left;text-decoration:n=
one;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
">You do this:</span></div>
<div><span style=3D"display:inline!important;float:none;background-=
color:transparent;color:rgb(34,34,34);font-family:"Arial","H=
elvetica",sans-serif;font-size:13px;font-style:normal;font-variant:nor=
mal;font-weight:400;letter-spacing:normal;text-align:left;text-decoration:n=
one;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
"><br>
</span></div>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-wor=
d;background-color:rgb(250,250,250)"><code>
<div><span style=3D"color:#008">if</span><span style=3D"color:#=
660">(</span><span style=3D"color:#008">auto</span><span style=3D"color:#00=
0"> ptr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#0=
00"> get_if</span><span style=3D"color:#080"><required_index></span><=
span style=3D"color:#660">(&</span><span style=3D"color:#008">var</span=
><span style=3D"color:#660">);</span><span style=3D"color:#000"> ptr</span>=
<span style=3D"color:#660">)</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>
=C2=A0 </span><span style=3D"color:#800">//use `ptr`</span>=
<span style=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span></div>
</code></div>
<div><span style=3D"display:inline!important;float:none;background-=
color:transparent;color:rgb(34,34,34);font-family:"Arial","H=
elvetica",sans-serif;font-size:13px;font-style:normal;font-variant:nor=
mal;font-weight:400;letter-spacing:normal;text-align:left;text-decoration:n=
one;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
"><br>
</span><span style=3D"display:inline!important;float:none;backgro=
und-color:transparent;color:rgb(34,34,34);font-family:"Arial",&qu=
ot;Helvetica",sans-serif;font-size:13px;font-style:normal;font-variant=
:normal;font-weight:400;letter-spacing:normal;text-align:left;text-decorati=
on:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing=
:0px"></span></div>
<div><span style=3D"display:inline!important;float:none;background-=
color:transparent;color:rgb(34,34,34);font-family:"Arial","H=
elvetica",sans-serif;font-size:13px;font-style:normal;font-variant:nor=
mal;font-weight:400;letter-spacing:normal;text-align:left;text-decoration:n=
one;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
">The fundamental
difference between `optional` and `variant` is that the
former only ever has 2 states. The behavior for the
unengaged state will almost always be "do nothing", w=
hile
the behavior for the engaged state will be "do something&q=
uot;. </span>Your
code strongly suggests that you're trying to treat a `variant=
`
like an `optional`. And we have a way to do that: get a
pointer to the member.</div>
</div>
</blockquote>
Yes, I consider variant as a generalization of optional.</div></blockqu=
ote><div><br></div><div>That's like saying you see an array of integers=
as a generalization of an integer. I mean yeah, you can see it that way. B=
ut you don't use one in the places you'd use the other, and you don=
't usually use one in any way resembling the way you use the other.</di=
v><div><br></div><div>The use cases for these types are so broadly disparat=
e that they don't need to have the same interface.</div><div><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=
=3D"#000000">But (for
some reasons that look bogus for me) the generalization isn't
smooth. IMHO it is better to fix it (even if no so much people feel
practical problems due to that shagginess =E2=80=94 just for aesthetic
reasons at least).<br>
<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>Also, I'm curious as to your application where a single
conditional check is sufficient to make the type "(almost)
useless for me". Seriously, is that trivial performance <i>r=
eally</i>
sufficient to go write your own variant type or to use
something less feature-rich?</div>
</div>
</blockquote>
It's more about consistency and psychology, not about actual
benchmarking yet. I am writing right now a piece of code that with
high probability will be a part of bottleneck. I realize that in
some cases std::variant does redundant checks (at least with the way
I use it). I expect them to be avoidable (as in std::optional and
others), but they aren't. So it's psychologically simpler for m=
e to
throw std::variant out and not to use in the "foundation" (th=
at will
probably be a bottleneck) any things that have _known_ overhead.</div><=
/blockquote><div><br></div><div>So it's "psychologically simpler&q=
uot; for you to spend a bunch of time coding something that you might not n=
eed, rather than using an off-the-shelf tool that does exactly what you nee=
d just <i>possibly</i> slower. Perhaps you're focusing too much on your=
psychology and not enough on what causes your project to actually get done=
..</div><div><br></div><div>I understand the kind of thing you're talkin=
g about. I get that impulse every now and then too, even when I'm codin=
g in non-C++ languages. That micro-optimization voice that says, "ugh,=
do I really need a conditional branch here? Can't I find a clever way =
to avoid that?" I even had to stop myself from digging through Lua man=
uals and such to find a function that could concatenate a bunch of strings =
without wrapping them in a table.</div><div><br></div><div>You would be sur=
prised how much telling that voice to shut up improves your productivity. <=
i>Without</i> making your code materially slower.</div><div><br></div><div>=
Just consider a variant example:</div><div><br></div><div class=3D"prettypr=
int" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; =
background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><span class=3D"styled-by-prettify" style=3D"color: #0=
08;">if</span><span class=3D"styled-by-prettify" style=3D"color: #660;">(</=
span><span class=3D"styled-by-prettify" style=3D"color: #008;">auto</span><=
span class=3D"styled-by-prettify" style=3D"color: #000;"> </span><span clas=
s=3D"styled-by-prettify" style=3D"color: #008;">var</span><span class=3D"st=
yled-by-prettify" style=3D"color: #000;"> </span><span class=3D"styled-by-p=
rettify" style=3D"color: #660;">=3D</span><span class=3D"styled-by-prettify=
" style=3D"color: #000;"> get_variant</span><span class=3D"styled-by-pretti=
fy" style=3D"color: #660;">();</span><span class=3D"styled-by-prettify" sty=
le=3D"color: #000;"> </span><span class=3D"styled-by-prettify" style=3D"col=
or: #008;">var</span><span class=3D"styled-by-prettify" style=3D"color: #66=
0;">.</span><span class=3D"styled-by-prettify" style=3D"color: #000;">index=
</span><span class=3D"styled-by-prettify" style=3D"color: #660;">()</span><=
span class=3D"styled-by-prettify" style=3D"color: #000;"> </span><span clas=
s=3D"styled-by-prettify" style=3D"color: #660;">=3D=3D</span><span class=3D=
"styled-by-prettify" style=3D"color: #000;"> </span><span class=3D"styled-b=
y-prettify" style=3D"color: #066;">3</span><span class=3D"styled-by-prettif=
y" style=3D"color: #660;">)</span><span class=3D"styled-by-prettify" style=
=3D"color: #000;"><br></span><span class=3D"styled-by-prettify" style=3D"co=
lor: #660;">{</span><span class=3D"styled-by-prettify" style=3D"color: #000=
;"><br>=C2=A0 </span><span class=3D"styled-by-prettify" style=3D"color: #00=
8;">auto</span><span class=3D"styled-by-prettify" style=3D"color: #000;"> <=
/span><span class=3D"styled-by-prettify" style=3D"color: #660;">&</span=
><span class=3D"styled-by-prettify" style=3D"color: #000;">value </span><sp=
an class=3D"styled-by-prettify" style=3D"color: #660;">=3D</span><span clas=
s=3D"styled-by-prettify" style=3D"color: #000;"> </span><span class=3D"styl=
ed-by-prettify" style=3D"color: #008;">get</span><span class=3D"styled-by-p=
rettify" style=3D"color: #660;"><</span><span class=3D"styled-by-prettif=
y" style=3D"color: #066;">3</span><span class=3D"styled-by-prettify" style=
=3D"color: #660;">>(</span><span class=3D"styled-by-prettify" style=3D"c=
olor: #008;">var</span><span class=3D"styled-by-prettify" style=3D"color: #=
660;">);</span><span class=3D"styled-by-prettify" style=3D"color: #000;"><b=
r></span><span class=3D"styled-by-prettify" style=3D"color: #660;">}</span>=
</div></code></div><div><br></div><div>Well, the `get` function is visible =
to the compiler, as is the `index` function. And `3` is a constant expressi=
on, so it is visible to the compiler too.</div><div><br></div><div>Which me=
ans the compiler has 100% of the information available in the local scope t=
o recognize that `get` will do the same check you just did. So if it inline=
s the `get` call, it is at least theoretically possible for the compiler to=
optimize out the second test post-inlining.</div><div><br></div><div>Does =
that mean it<i> certainly</i> will? No. But <a href=3D"https://godbolt.org/=
g/DReC5Y">Godbolt says GCC does.</a> It completely optimizes out the test a=
nd exception throwing.</div><div><br></div><div>Now obviously this is a hig=
hly simplified case, and there will be cases where compilers can't reas=
onably tell. But the farther the initial test is from where it gets used, t=
he more likely it is that you will accidentally call it incorrectly.</div><=
div><i><br></i></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgco=
lor=3D"#FFFFFF" text=3D"#000000">Not
necessarily variant::get will be a problem (and most probably
something absolutely else will), but I don't like a feeling of
creating future problems when writing the code (i.e. to write a code
with a known and easy-avoidable redundancy, which doesn't brings an=
d
significant improvements into the code aesthetics or some other <span>t=
remendous benefits</span>). <br>
<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>You're also missing another problem with checked vs.
unchecked operations: consistency.</div>
<div><br>
</div>
<div>In the C++ standard library, the way you tell whether an
operation is checked or unchecked is that the unchecked
operation uses an<i> operator</i>. `vector::operator[]`,
`optional::operator*`, and so on are operators. If you use a
named function, then it is a checked operation. `vector::at`,
`optional::value`, and so forth.</div>
<div><br>
</div>
<div>You can't really have an operator-form of the `variant`
`get` function. After all, you need to provide a template
index/type, and you can't pass something like that as a
function parameter to an operator. After all, operators cannot
take explicit template parameters without calling them by
spelling out the operator
(`variant::operator[]<std::<wbr>string>(0)`).</div>
</div>
</blockquote>
I never heard about "methods-are-checked, functions-are-unchecked&=
quot;
rule in stdlib. Is is stated somewhere?=C2=A0</div></blockquote><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000=
000">As for me, much more expected understanding of consistency here
would be that every class (where it's applicable) has two ways of
access: checked and unchecked. (If the std::vector and std::optional
had no unchecked access, then I would have no <span lang=3D"en"><span>d=
isturbance about
std::variant =E2=80=94 I'd just see that as style of C++ stdlib=
; even if
only std::optional </span></span>had no unchecked access, then
it would look understandable for me (stdlib is old, std::vector
created long before std::optional and std::variant, style changed
since then); but now it looks as breaking its own style.)<br></div></bl=
ockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFF=
FF" text=3D"#000000">
And if unchecked things really need to be operators (which I doubt,
even if the such rule exists and wasn't broken yet, it will be
surely be broken at some point of time in future due to the growing
of stdlib and growing of the amount of
strongly-needed-to-be-<wbr>unchecked things), why not simply the explic=
it
cast operator? (Ah, you are right, explicit cast operator will allow
only access by type, not by index =E2=80=94 still I don't feel both=
access
by index and .)<br></div></blockquote><div><br></div><div>If you have a=
legitimate reason to need to have unchecked access to a variant, whatever =
reasoning you use applies just as well to unchecked access by index. Just b=
ecause you personally doesn't use it doesn't mean that other people=
wanting the same thing don't.</div><div><br></div><div>Whatever the so=
lution is, it should not make access-by-index a second-class feature of `va=
riant`. Some people really need that to work.</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5edea79c-9249-4d24-b6b1-6c4b4f0d4e0c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5edea79c-9249-4d24-b6b1-6c4b4f0d4e0c=
%40isocpp.org</a>.<br />
------=_Part_8487_156567537.1516145880373--
------=_Part_8486_523311757.1516145880373--
.
Author: Oleksandr Pikozh <o.pikozh@gmail.com>
Date: Wed, 17 Jan 2018 10:05:34 +0200
Raw View
This is a multi-part message in MIME format.
--------------9E0F4CAA1CB6F0866F102075
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
On 16.01.18 22:34, Vicente J. Botet Escriba wrote:
> Le 16/01/2018 =C3=A0 07:33, Oleksandr Pikozh a =C3=A9crit=C2=A0:
>>
>> In std::variant we have:
>> - ??? =E2=80=94 doesn't check whether a variant contains specified index=
/type;
>> - method get =E2=80=94 throws std::bad_variant_access when a variant doe=
sn't=20
>> contain specified index/type.
>>
>> Why we don't have any fast (unchecked) ways to access std::variant?=20
>> Assuming context when user has already checked for presence of=20
>> required item somehow and now needs the fastest access (i.e. he=20
>> agrees to get UB when absent).
>>
> I believe the standard committee could considered it if you have a=20
> motivating use case that cannot be managed with std::visit.
>
>
> std::visit is a safe tool. Adding an unsafe tool when a safe one could=20
> be used wouldn't help. We need a use case that will be more efficient=20
> with your unsafe function.
>
> Vicente
>
The `std::visit` simply doesn't allow relying on `index`, for example.
For example
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
=C2=A0=C2=A0=C2=A0 void do_something() {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::variant<T1, T2, T3> varian=
t =3D get(=E2=80=A6);
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switch (variant.index) {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case 0:=
f1(variant.get<0>()); break;
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case 1:=
f2(variant.get<1>()); break;
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case 2:=
f3(variant.get<2>()); break;
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 default=
: assert(false);
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
=C2=A0=C2=A0=C2=A0 }
cannot be replaced with
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
=C2=A0=C2=A0=C2=A0 void do_something() {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), [&](=
auto& arg) {
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 using arg_type =3D std::decay_t<decltype(=
arg)>;
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if constexpr (std::is_same_v<arg_type, T1=
>)
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 f1(arg);
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else if constexpr (std::is_same=
_v<arg_type, T2>)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 f2(arg)=
;
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else if constexpr (std::is_same_v<arg_typ=
e, T3>)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 f3(arg)=
;
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 assert(=
false);
=C2=A0=C2=A0=C2=A0 });
=C2=A0=C2=A0=C2=A0 }
or even like
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
=C2=A0=C2=A0=C2=A0 void do_something() {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct visitor {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void op=
erator()(const T1 &arg) const {f1(arg);}
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void op=
erator()(const T2 &arg) const {f2(arg);}
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void op=
erator()(const T3 &arg) const {f3(arg);}
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 };
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), visi=
tor());
=C2=A0=C2=A0=C2=A0 }
in cases when we expect <T1, T2, T3> to be possibly duplicate types=20
(e.g. <int, int, std::string>).
Although I don't consider usage with duplicate types and (therefore)=20
relying on index to be important parts of std::variant (personally I, if=20
I designed std::variant, probably wouldn't allow it at all (possibly=20
having it in a different class, like std::multiset vs std::set)), they=20
are allowed, so the way is already chosen. And even I sometimes use it=20
(e.g. when I got a set of=20
having-common-interface-but-non-having-common-ancestor=20
Java-iterator-like classes with `i.hasNext()` and `i.next()`-like=20
methods and was going to build a `concatenate(i1, i2, i3)`-like=20
function). But those who go this way (trying to assume that std::variant=20
allows duplicate types) finally find incompleteness of std::variant for=20
that approach.
P.S.: Sorry, if I described it not enough clearly, I was in hurry.=20
Please, say if it's not understandable =E2=80=94 then I may rewrite later.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/b62a444e-3242-0858-3103-81bc05dfbee0%40gmail.com=
..
--------------9E0F4CAA1CB6F0866F102075
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
On 16.01.18 22:34, Vicente J. Botet Escriba wrote:<br>
<blockquote type=3D"cite"
cite=3D"mid:883fa674-b1f2-53ef-6a29-806b43e60a0f@wanadoo.fr">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<div class=3D"moz-cite-prefix">Le 16/01/2018 =C3=A0 07:33, Oleksandr
Pikozh a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:959f20d3-0455-951d-70fe-60bf0110cad7@gmail.com"><br>
In std::variant we have: <br>
- ??? =E2=80=94 doesn't check whether a variant contains specified
index/type; <br>
- method get =E2=80=94 throws std::bad_variant_access when a varian=
t
doesn't contain specified index/type. <br>
<br>
Why we don't have any fast (unchecked) ways to access
std::variant? Assuming context when user has already checked for
presence of required item somehow and now needs the fastest
access (i.e. he agrees to get UB when absent). <br>
<br>
</blockquote>
<p><font size=3D"+1">I believe the standard committee could
considered it if you have a motivating use case that cannot be
managed with std::visit.</font></p>
<p><br>
<font size=3D"+1"><font size=3D"+1">std::visit is a safe tool.
Adding an unsafe tool when a safe one could be used wouldn't
help. We need a use case that will be more efficient with
your unsafe function.<br>
</font></font></p>
<p><font size=3D"+1">Vicente</font><br>
</p>
</blockquote>
<br>
The `std::visit` simply doesn't allow relying on `index`, for
example.<br>
<br>
For example<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>=
;<br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::variant<T1, T2, T3&g=
t; variant =3D get(=E2=80=A6);<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switch (variant.index) {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case=
0: f1(variant.get<0>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case=
1: f2(variant.get<1>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case=
2: f3(variant.get<2>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 defa=
ult: assert(false);<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
cannot be replaced with<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>=
;<br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), [=
&](auto& arg) {<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 using arg_type =3D std::decay_t<dec=
ltype(arg)>;<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if constexpr (std::is_same_v<arg_ty=
pe, T1>)<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 f1(arg);<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else if constexpr (std::is_s=
ame_v<arg_type, T2>)<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 f2(a=
rg);<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else if constexpr (std::is_same_v<a=
rg_type, T3>)<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 f3(a=
rg);<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 asse=
rt(false);<br>
=C2=A0 =C2=A0=C2=A0
=C2=A0=C2=A0=C2=A0 });<br>
=C2=A0=C2=A0=C2=A0 }<br>
=C2=A0=C2=A0=C2=A0 <br>
or even like<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>=
;<br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct visitor {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void=
operator()(const T1 &arg) const {f1(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void=
operator()(const T2 &arg) const {f2(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void=
operator()(const T3 &arg) const {f3(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 };<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), v=
isitor());<br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
in cases when we expect <T1, T2, T3> to be possibly duplicate
types (e.g. <int, int, std::string>).<br>
<br>
Although I don't consider usage with duplicate types and (therefore)
relying on index to be important parts of std::variant (personally
I, if I designed std::variant, probably wouldn't allow it at all
(possibly having it in a different class, like std::multiset vs
std::set)), they are allowed, so the way is already chosen. And even
I sometimes use it (e.g. when I got a set of
having-common-interface-but-non-having-common-ancestor
Java-iterator-like classes with `i.hasNext()` and `i.next()`-like
methods and was going to build a `concatenate(i1, i2, i3)`-like
function). But those who go this way (trying to assume that
std::variant allows duplicate types) finally find incompleteness of
std::variant for that approach.<br>
<br>
P.S.: Sorry, if I described it not enough clearly, I was in hurry.
Please, say if it's not understandable =E2=80=94 then I may rewrite lat=
er.<br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b62a444e-3242-0858-3103-81bc05dfbee0%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b62a444e-3242-0858-3103-81bc05dfbee0%=
40gmail.com</a>.<br />
--------------9E0F4CAA1CB6F0866F102075--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 17 Jan 2018 19:01:04 +0100
Raw View
This is a multi-part message in MIME format.
--------------BAEB26E0D98CDFB322ECE587
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 17/01/2018 =C3=A0 09:05, Oleksandr Pikozh a =C3=A9crit=C2=A0:
> On 16.01.18 22:34, Vicente J. Botet Escriba wrote:
>> Le 16/01/2018 =C3=A0 07:33, Oleksandr Pikozh a =C3=A9crit=C2=A0:
>>>
>>> In std::variant we have:
>>> - ??? =E2=80=94 doesn't check whether a variant contains specified inde=
x/type;
>>> - method get =E2=80=94 throws std::bad_variant_access when a variant do=
esn't=20
>>> contain specified index/type.
>>>
>>> Why we don't have any fast (unchecked) ways to access std::variant?=20
>>> Assuming context when user has already checked for presence of=20
>>> required item somehow and now needs the fastest access (i.e. he=20
>>> agrees to get UB when absent).
>>>
>> I believe the standard committee could considered it if you have a=20
>> motivating use case that cannot be managed with std::visit.
>>
>>
>> std::visit is a safe tool. Adding an unsafe tool when a safe one=20
>> could be used wouldn't help. We need a use case that will be more=20
>> efficient with your unsafe function.
>>
>> Vicente
>>
>
> The `std::visit` simply doesn't allow relying on `index`, for example.
>
> For example
>
> =C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
> =C2=A0=C2=A0=C2=A0 void do_something() {
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::variant<T1, T2, T3> varia=
nt =3D get(=E2=80=A6);
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switch (variant.index) {
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case 0=
: f1(variant.get<0>()); break;
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case 1=
: f2(variant.get<1>()); break;
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case 2=
: f3(variant.get<2>()); break;
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 defaul=
t: assert(false);
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
> =C2=A0=C2=A0=C2=A0 }
>
> cannot be replaced with
>
> =C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
> =C2=A0=C2=A0=C2=A0 void do_something() {
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), [&]=
(auto& arg) {
> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 using arg_type =3D s=
td::decay_t<decltype(arg)>;
> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if constexpr (std::i=
s_same_v<arg_type, T1>)
> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 f1(arg);
> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else if co=
nstexpr (std::is_same_v<arg_type, T2>)
> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 f2(arg);
> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else if constexpr (s=
td::is_same_v<arg_type, T3>)
> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 f3(arg);
> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else
> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 assert(false);
> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 });
> =C2=A0=C2=A0=C2=A0 }
>
> or even like
>
> =C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
> =C2=A0=C2=A0=C2=A0 void do_something() {
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct visitor {
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void o=
perator()(const T1 &arg) const {f1(arg);}
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void o=
perator()(const T2 &arg) const {f2(arg);}
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void o=
perator()(const T3 &arg) const {f3(arg);}
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 };
> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), vis=
itor());
> =C2=A0=C2=A0=C2=A0 }
>
> in cases when we expect <T1, T2, T3> to be possibly duplicate types=20
> (e.g. <int, int, std::string>).
>
Ok, I see the case, but I wonder of the usability of such a variant. The=20
standard doesn't forbid to have twice the same type, but I would never=20
try to use something like that. I would prefer to wrap the types and use=20
std::visit.
> Although I don't consider usage with duplicate types and (therefore)=20
> relying on index to be important parts of std::variant (personally I,=20
> if I designed std::variant, probably wouldn't allow it at all=20
> (possibly having it in a different class, like std::multiset vs=20
> std::set)), they are allowed, so the way is already chosen. And even I=20
> sometimes use it (e.g. when I got a set of=20
> having-common-interface-but-non-having-common-ancestor=20
> Java-iterator-like classes with `i.hasNext()` and `i.next()`-like=20
> methods and was going to build a `concatenate(i1, i2, i3)`-like=20
> function). But those who go this way (trying to assume that=20
> std::variant allows duplicate types) finally find incompleteness of=20
> std::variant for that approach.
I agree that the unsafe access could have a sense in this case and be=20
coherent.
I'll give it a neutral vote as I don't think I need it, but maybe if you=20
can elaborate with a realistic example, I could change my mind.
>
> P.S.: Sorry, if I described it not enough clearly, I was in hurry.=20
> Please, say if it's not understandable =E2=80=94 then I may rewrite later=
..
Don't worry, I believe I understood it.
Vicente
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/37699e79-5dd5-740d-21e4-efdacce5dbc9%40wanadoo.f=
r.
--------------BAEB26E0D98CDFB322ECE587
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
<div class=3D"moz-cite-prefix">Le 17/01/2018 =C3=A0 09:05, Oleksandr Pi=
kozh
a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:b62a444e-3242-0858-3103-81bc05dfbee0@gmail.com">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
On 16.01.18 22:34, Vicente J. Botet Escriba wrote:<br>
<blockquote type=3D"cite"
cite=3D"mid:883fa674-b1f2-53ef-6a29-806b43e60a0f@wanadoo.fr">
<meta http-equiv=3D"Content-Type" content=3D"text/html;
charset=3Dutf-8">
<div class=3D"moz-cite-prefix">Le 16/01/2018 =C3=A0 07:33, Oleksand=
r
Pikozh a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:959f20d3-0455-951d-70fe-60bf0110cad7@gmail.com"><br>
In std::variant we have: <br>
- ??? =E2=80=94 doesn't check whether a variant contains specifie=
d
index/type; <br>
- method get =E2=80=94 throws std::bad_variant_access when a vari=
ant
doesn't contain specified index/type. <br>
<br>
Why we don't have any fast (unchecked) ways to access
std::variant? Assuming context when user has already checked
for presence of required item somehow and now needs the
fastest access (i.e. he agrees to get UB when absent). <br>
<br>
</blockquote>
<p><font size=3D"+1">I believe the standard committee could
considered it if you have a motivating use case that cannot
be managed with std::visit.</font></p>
<p><br>
<font size=3D"+1"><font size=3D"+1">std::visit is a safe tool.
Adding an unsafe tool when a safe one could be used
wouldn't help. We need a use case that will be more
efficient with your unsafe function.<br>
</font></font></p>
<p><font size=3D"+1">Vicente</font><br>
</p>
</blockquote>
<br>
The `std::visit` simply doesn't allow relying on `index`, for
example.<br>
<br>
For example<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3&=
gt;<br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::variant<T1, T2, T3=
> variant =3D get(=E2=80=A6);<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switch (variant.index) {<b=
r>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ca=
se 0: f1(variant.get<0>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ca=
se 1: f2(variant.get<1>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ca=
se 2: f3(variant.get<2>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 de=
fault: assert(false);<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
cannot be replaced with<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3&=
gt;<br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6),=
[&](auto& arg) {<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 using arg_type =
=3D std::decay_t<decltype(arg)>;<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if constexpr (st=
d::is_same_v<arg_type, T1>)<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 f1(arg);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else i=
f constexpr (std::is_same_v<arg_type,
T2>)<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 f2(arg);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else if constexp=
r (std::is_same_v<arg_type,
T3>)<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 f3(arg);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 assert(false);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 });<br>
=C2=A0=C2=A0=C2=A0 }<br>
=C2=A0=C2=A0=C2=A0 <br>
or even like<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3&=
gt;<br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct visitor {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 vo=
id operator()(const T1 &arg) const {f1(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 vo=
id operator()(const T2 &arg) const {f2(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 vo=
id operator()(const T3 &arg) const {f3(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 };<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6),=
visitor());<br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
in cases when we expect <T1, T2, T3> to be possibly
duplicate types (e.g. <int, int, std::string>).<br>
<br>
</blockquote>
Ok, I see the case, but I wonder of the usability of such a variant.
The standard doesn't forbid to have twice the same type, but I would
never try to use something like that. I would prefer to wrap the
types and use std::visit.<br>
<br>
<blockquote type=3D"cite"
cite=3D"mid:b62a444e-3242-0858-3103-81bc05dfbee0@gmail.com">
Although I don't consider usage with duplicate types and
(therefore) relying on index to be important parts of std::variant
(personally I, if I designed std::variant, probably wouldn't allow
it at all (possibly having it in a different class, like
std::multiset vs std::set)), they are allowed, so the way is
already chosen. And even I sometimes use it (e.g. when I got a set
of having-common-interface-but-non-having-common-ancestor
Java-iterator-like classes with `i.hasNext()` and `i.next()`-like
methods and was going to build a `concatenate(i1, i2, i3)`-like
function). But those who go this way (trying to assume that
std::variant allows duplicate types) finally find incompleteness
of std::variant for that approach.<br>
</blockquote>
I agree that the unsafe access could have a sense in this case and
be coherent. <br>
I'll give it a neutral vote as I don't think I need it, but maybe if
you can elaborate with a realistic example, I could change my mind.<br>
<blockquote type=3D"cite"
cite=3D"mid:b62a444e-3242-0858-3103-81bc05dfbee0@gmail.com"> <br>
P.S.: Sorry, if I described it not enough clearly, I was in hurry.
Please, say if it's not understandable =E2=80=94 then I may rewrite l=
ater.<br>
</blockquote>
Don't worry, I believe I understood it.<br>
<p><br>
</p>
<p>Vicente<br>
</p>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/37699e79-5dd5-740d-21e4-efdacce5dbc9%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/37699e79-5dd5-740d-21e4-efdacce5dbc9=
%40wanadoo.fr</a>.<br />
--------------BAEB26E0D98CDFB322ECE587--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 17 Jan 2018 19:09:42 +0100
Raw View
This is a multi-part message in MIME format.
--------------93B8E124A7F4582A5D790BB1
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 16/01/2018 =C3=A0 22:31, Tony V E a =C3=A9crit=C2=A0:
>
>
> On Tue, Jan 16, 2018 at 3:37 PM, Vicente J. Botet Escriba=20
> <vicente.botet@wanadoo.fr <mailto:vicente.botet@wanadoo.fr>> wrote:
>
> Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9crit=C2=A0:
>
> While it's not a bad idea (pattern matching in other
> languages naturally support this use), in practise
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.h=
tml
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.=
html>
>
> may be easier to use.
>
> It is weird. The committee required to remove from expected<T,E>
> every monadic operation. Now we have a paper that request the
> addition of the monadic operations to optional. Not that I'm
> against this member function approach, but we should be coherent.
>
>
>
> It may be that the committee wanted expected<> to get in first, then=20
> add monadic later. Like optional.
> Or it may just be that the committee is not one person, but a bunch,=20
> and it changes "its" mind regularly.
>
Then I didn't understood what the committee wanted. I believed that the=20
committee wanted a non-member function interface, hence my Monadic paper.
Vicente
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/9fc3bfd4-dfa5-cc41-6e7a-f386e606094a%40wanadoo.f=
r.
--------------93B8E124A7F4582A5D790BB1
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
<div class=3D"moz-cite-prefix">Le 16/01/2018 =C3=A0 22:31, Tony V E a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:CAOHCbivhHe+5tiTCT+zMByX_U46sSFYKPhiQYHcJmxbqCwgUsA@mail.gmail.=
com">
<div dir=3D"ltr"><br>
<div class=3D"gmail_extra"><br>
<div class=3D"gmail_quote">On Tue, Jan 16, 2018 at 3:37 PM,
Vicente J. Botet Escriba <span dir=3D"ltr"><<a
href=3D"mailto:vicente.botet@wanadoo.fr" target=3D"_blank"
moz-do-not-send=3D"true">vicente.botet@wanadoo.fr</a>></=
span>
wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex"><span
class=3D"">Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9=
crit=C2=A0:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
While it's not a bad idea (pattern matching in other<br>
languages naturally support this use), in practise<br>
<br>
<a
href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.htm=
l"
rel=3D"noreferrer" target=3D"_blank"
moz-do-not-send=3D"true">http://www.open-std.org/jtc1/s=
<wbr>c22/wg21/docs/papers/2017/p079<wbr>8r0.html</a><br>
<br>
may be easier to use.<br>
<br>
</blockquote>
</span>
It is weird. The committee required to remove from
expected<T,E> every monadic operation. Now we have a
paper that request the addition of the monadic operations
to optional. Not that I'm against this member function
approach, but we should be coherent.<br>
</blockquote>
</div>
</div>
<br>
<div class=3D"gmail_extra"><br>
</div>
<div class=3D"gmail_extra">It may be that the committee wanted
expected<> to get in first, then add monadic later.=C2=A0
Like optional.</div>
<div class=3D"gmail_extra">Or it may just be that the committee is
not one person, but a bunch, and it changes "its" mind
regularly.</div>
<div class=3D"gmail_extra"><br>
</div>
</div>
</blockquote>
Then I didn't understood what the committee wanted. I believed that
the committee wanted a non-member function interface, hence my
Monadic paper. <br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9fc3bfd4-dfa5-cc41-6e7a-f386e606094a%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9fc3bfd4-dfa5-cc41-6e7a-f386e606094a=
%40wanadoo.fr</a>.<br />
--------------93B8E124A7F4582A5D790BB1--
.
Author: Zhihao Yuan <zy@miator.net>
Date: Wed, 17 Jan 2018 13:52:26 -0500
Raw View
This is a multi-part message in MIME format.
--b1_99de1f898328db081ce81159d4e13877
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
I referenced the paper just to show an example
about `and_then` & `or_else`, whether they should members or non-members ar=
e not what I planned to comment on.
Sent from ProtonMail mobile
-------- Original Message --------
On Jan 17, 2018, 12:09 PM, Vicente J. Botet Escriba wrote:
> Le 16/01/2018 =C3=A0 22:31, Tony V E a =C3=A9crit :
>
>> On Tue, Jan 16, 2018 at 3:37 PM, Vicente J. Botet Escriba <vicente.botet=
@wanadoo.fr> wrote:
>>
>>> Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9crit :
>>>
>>>> While it's not a bad idea (pattern matching in other
>>>> languages naturally support this use), in practise
>>>>
>>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0798r0.html
>>>>
>>>> may be easier to use.
>>>
>>> It is weird. The committee required to remove from expected<T,E> every =
monadic operation. Now we have a paper that request the addition of the mon=
adic operations to optional. Not that I'm against this member function appr=
oach, but we should be coherent.
>>
>> It may be that the committee wanted expected<> to get in first, then add=
monadic later. Like optional.
>> Or it may just be that the committee is not one person, but a bunch, and=
it changes "its" mind regularly.
>
> Then I didn't understood what the committee wanted. I believed that the c=
ommittee wanted a non-member function interface, hence my Monadic paper.
>
> Vicente
>
> --
> You received this message because you are subscribed to the Google Groups=
"ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit [https://groups.google.com/a/iso=
cpp.org/d/msgid/std-proposals/9fc3bfd4-dfa5-cc41-6e7a-f386e606094a%40wanado=
o.fr](https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9fc3bfd4=
-dfa5-cc41-6e7a-f386e606094a%40wanadoo.fr?utm_medium=3Demail&utm_source=3Df=
ooter).
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAk0y_BRj-0MiwWhFDFrDVWg7oTs_zm8i5lg-85yxXB6ZbXc=
-69Zv57BNh_WdX3BBRU9zdIi2aeQHvBQVTRdgxBUKvydscWOzwRUmgukMZU%3D%40miator.net=
..
--b1_99de1f898328db081ce81159d4e13877
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
I referenced the paper just to show an example<br>about `and_then` & `or_el=
se`, whether they should members or non-members are not what I planned to c=
omment on.<br><br><br>Sent from ProtonMail mobile<br><br><br><br>-------- O=
riginal Message --------<br>On Jan 17, 2018, 12:09 PM, Vicente J. Botet Esc=
riba < vicente.botet@wanadoo.fr> wrote:<blockquote class=3D"protonmail_quot=
e"><br><html><head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body>
<div class=3D"moz-cite-prefix">Le 16/01/2018 =C3=A0 22:31, Tony V E a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite" cite=3D"mid:CAOHCbivhHe+5tiTCT+zMByX_U46sSFYK=
PhiQYHcJmxbqCwgUsA@mail.gmail.com">
<div dir=3D"ltr"><br>
<div class=3D"gmail_extra"><br>
<div class=3D"gmail_quote">On Tue, Jan 16, 2018 at 3:37 PM,
Vicente J. Botet Escriba <span dir=3D"ltr"><<a href=3D"mailt=
o:vicente.botet@wanadoo.fr" target=3D"_blank" moz-do-not-send=3D"true">vice=
nte.botet@wanadoo.fr</a>></span>
wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=
=3D"">Le 16/01/2018 =C3=A0 16:38, Zhihao Yuan a =C3=A9crit :<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
While it's not a bad idea (pattern matching in other<br>
languages naturally support this use), in practise<br>
<br>
<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/pa=
pers/2017/p0798r0.html" rel=3D"noreferrer" target=3D"_blank" moz-do-not-sen=
d=3D"true">http://www.open-std.org/jtc1/s<wbr>c22/wg21/docs/papers/2017/p07=
9<wbr>8r0.html</a><br>
<br>
may be easier to use.<br>
<br>
</blockquote>
</span>
It is weird. The committee required to remove from
expected<T,E> every monadic operation. Now we have a
paper that request the addition of the monadic operations
to optional. Not that I'm against this member function
approach, but we should be coherent.<br>
</blockquote>
</div>
</div>
<br>
<div class=3D"gmail_extra"><br>
</div>
<div class=3D"gmail_extra">It may be that the committee wanted
expected<> to get in first, then add monadic later.
Like optional.</div>
<div class=3D"gmail_extra">Or it may just be that the committee is
not one person, but a bunch, and it changes "its" mind
regularly.</div>
<div class=3D"gmail_extra"><br>
</div>
</div>
</blockquote>
Then I didn't understood what the committee wanted. I believed that
the committee wanted a non-member function interface, hence my
Monadic paper. <br>
<br>
Vicente<br>
=20
<p></p>
-- <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 e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9fc3bfd4-dfa5-cc41-6e7a-f386e606094a%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.goo=
gle.com/a/isocpp.org/d/msgid/std-proposals/9fc3bfd4-dfa5-cc41-6e7a-f386e606=
094a%40wanadoo.fr</a>.<br>
</body></html></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAk0y_BRj-0MiwWhFDFrDVWg7oTs_zm8i5lg-=
85yxXB6ZbXc-69Zv57BNh_WdX3BBRU9zdIi2aeQHvBQVTRdgxBUKvydscWOzwRUmgukMZU%3D%4=
0miator.net?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAk0y_BRj-0MiwWhFDFrDVWg7oTs_zm8i5lg-=
85yxXB6ZbXc-69Zv57BNh_WdX3BBRU9zdIi2aeQHvBQVTRdgxBUKvydscWOzwRUmgukMZU%3D%4=
0miator.net</a>.<br />
--b1_99de1f898328db081ce81159d4e13877--
.
Author: Oleksandr Pikozh <o.pikozh@gmail.com>
Date: Wed, 17 Jan 2018 20:59:43 +0200
Raw View
This is a multi-part message in MIME format.
--------------47DD56AED936AF81A899DE50
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
On 17.01.18 20:01, Vicente J. Botet Escriba wrote:
> Le 17/01/2018 =C3=A0 09:05, Oleksandr Pikozh a =C3=A9crit=C2=A0:
>> On 16.01.18 22:34, Vicente J. Botet Escriba wrote:
>>> Le 16/01/2018 =C3=A0 07:33, Oleksandr Pikozh a =C3=A9crit=C2=A0:
>>>>
>>>> In std::variant we have:
>>>> - ??? =E2=80=94 doesn't check whether a variant contains specified ind=
ex/type;
>>>> - method get =E2=80=94 throws std::bad_variant_access when a variant=
=20
>>>> doesn't contain specified index/type.
>>>>
>>>> Why we don't have any fast (unchecked) ways to access std::variant?=20
>>>> Assuming context when user has already checked for presence of=20
>>>> required item somehow and now needs the fastest access (i.e. he=20
>>>> agrees to get UB when absent).
>>>>
>>> I believe the standard committee could considered it if you have a=20
>>> motivating use case that cannot be managed with std::visit.
>>>
>>>
>>> std::visit is a safe tool. Adding an unsafe tool when a safe one=20
>>> could be used wouldn't help. We need a use case that will be more=20
>>> efficient with your unsafe function.
>>>
>>> Vicente
>>>
>>
>> The `std::visit` simply doesn't allow relying on `index`, for example.
>>
>> For example
>>
>> =C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
>> =C2=A0=C2=A0=C2=A0 void do_something() {
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::variant<T1, T2, T3> vari=
ant =3D get(=E2=80=A6);
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switch (variant.index) {
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case =
0: f1(variant.get<0>()); break;
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case =
1: f2(variant.get<1>()); break;
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case =
2: f3(variant.get<2>()); break;
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 defau=
lt: assert(false);
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>> =C2=A0=C2=A0=C2=A0 }
>>
>> cannot be replaced with
>>
>> =C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
>> =C2=A0=C2=A0=C2=A0 void do_something() {
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), [&=
](auto& arg) {
>> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 using arg_type =3D =
std::decay_t<decltype(arg)>;
>> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if constexpr (std::=
is_same_v<arg_type, T1>)
>> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 f1(arg);
>> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else if c=
onstexpr (std::is_same_v<arg_type, T2>)
>> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 f2(arg);
>> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else if constexpr (=
std::is_same_v<arg_type, T3>)
>> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 f3(arg);
>> =C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else
>> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 assert(false);
>> =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 });
>> =C2=A0=C2=A0=C2=A0 }
>>
>> or even like
>>
>> =C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T3>
>> =C2=A0=C2=A0=C2=A0 void do_something() {
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct visitor {
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void =
operator()(const T1 &arg) const {f1(arg);}
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void =
operator()(const T2 &arg) const {f2(arg);}
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void =
operator()(const T3 &arg) const {f3(arg);}
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 };
>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6), vi=
sitor());
>> =C2=A0=C2=A0=C2=A0 }
>>
>> in cases when we expect <T1, T2, T3> to be possibly duplicate types=20
>> (e.g. <int, int, std::string>).
>>
> Ok, I see the case, but I wonder of the usability of such a variant.=20
> The standard doesn't forbid to have twice the same type, but I would=20
> never try to use something like that. I would prefer to wrap the types=20
> and use std::visit.
I personally consider such case to be strange for a usual variant, but=20
still perfectly valid and usable for some "special variant" type and=20
some more rare use cases. I.e. I'd create two variant types: something=20
like std::variant (with no type duplication support and probably with no=20
`index` field / `get<index>()` method at all, but with `=3D value`=20
operator, implicit from-value constructor and implicit to-value cast=20
operator) and std::explicit_variant (with `index` field, with=20
possibility to duplicate types, but without `=3D value` operator (probably=
=20
`reset(size_t index, Value value)` method instead), without implicit=20
from-value constructor (maybe `(size_t index, Value value)` constructor=20
instead, with `visit(std::function<void(size_t, Value)>)` visiting), and=20
without implicit to-value cast operator (`get<index>()` method instead))=20
=E2=80=94 with considering the first one as "main", but understanding that =
some=20
cases need second (like std::set and std::multiset). But stdlib=20
architects decided to merge both in the single class; so that class=20
needs to support full feature set for both approaches.
>
>> Although I don't consider usage with duplicate types and (therefore)=20
>> relying on index to be important parts of std::variant (personally I,=20
>> if I designed std::variant, probably wouldn't allow it at all=20
>> (possibly having it in a different class, like std::multiset vs=20
>> std::set)), they are allowed, so the way is already chosen. And even=20
>> I sometimes use it (e.g. when I got a set of=20
>> having-common-interface-but-non-having-common-ancestor=20
>> Java-iterator-like classes with `i.hasNext()` and `i.next()`-like=20
>> methods and was going to build a `concatenate(i1, i2, i3)`-like=20
>> function). But those who go this way (trying to assume that=20
>> std::variant allows duplicate types) finally find incompleteness of=20
>> std::variant for that approach.
> I agree that the unsafe access could have a sense in this case and be=20
> coherent.
> I'll give it a neutral vote as I don't think I need it, but maybe if=20
> you can elaborate with a realistic example, I could change my mind.
>>
>> P.S.: Sorry, if I described it not enough clearly, I was in hurry.=20
>> Please, say if it's not understandable =E2=80=94 then I may rewrite late=
r.
> Don't worry, I believe I understood it.
>
>
> Vicente
>
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/e2ee17f4-0b5b-1cf1-3d79-29611793d9e4%40gmail.com=
..
--------------47DD56AED936AF81A899DE50
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
On 17.01.18 20:01, Vicente J. Botet Escriba wrote:<br>
<blockquote type=3D"cite"
cite=3D"mid:37699e79-5dd5-740d-21e4-efdacce5dbc9@wanadoo.fr">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<div class=3D"moz-cite-prefix">Le 17/01/2018 =C3=A0 09:05, Oleksandr
Pikozh a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:b62a444e-3242-0858-3103-81bc05dfbee0@gmail.com">
<meta http-equiv=3D"Content-Type" content=3D"text/html;
charset=3Dutf-8">
On 16.01.18 22:34, Vicente J. Botet Escriba wrote:<br>
<blockquote type=3D"cite"
cite=3D"mid:883fa674-b1f2-53ef-6a29-806b43e60a0f@wanadoo.fr">
<meta http-equiv=3D"Content-Type" content=3D"text/html;
charset=3Dutf-8">
<div class=3D"moz-cite-prefix">Le 16/01/2018 =C3=A0 07:33, Oleksa=
ndr
Pikozh a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:959f20d3-0455-951d-70fe-60bf0110cad7@gmail.com"><br=
>
In std::variant we have: <br>
- ??? =E2=80=94 doesn't check whether a variant contains specif=
ied
index/type; <br>
- method get =E2=80=94 throws std::bad_variant_access when a va=
riant
doesn't contain specified index/type. <br>
<br>
Why we don't have any fast (unchecked) ways to access
std::variant? Assuming context when user has already checked
for presence of required item somehow and now needs the
fastest access (i.e. he agrees to get UB when absent). <br>
<br>
</blockquote>
<p><font size=3D"+1">I believe the standard committee could
considered it if you have a motivating use case that
cannot be managed with std::visit.</font></p>
<p><br>
<font size=3D"+1"><font size=3D"+1">std::visit is a safe tool.
Adding an unsafe tool when a safe one could be used
wouldn't help. We need a use case that will be more
efficient with your unsafe function.<br>
</font></font></p>
<p><font size=3D"+1">Vicente</font><br>
</p>
</blockquote>
<br>
The `std::visit` simply doesn't allow relying on `index`, for
example.<br>
<br>
For example<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T=
3><br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::variant<T1, T2, =
T3> variant =3D get(=E2=80=A6);<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switch (variant.index) {=
<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
case 0: f1(variant.get<0>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
case 1: f2(variant.get<1>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
case 2: f3(variant.get<2>()); break;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
default: assert(false);<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }<br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
cannot be replaced with<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T=
3><br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6=
), [&](auto& arg) {<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 using arg_type=
=3D std::decay_t<decltype(arg)>;<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 if constexpr (=
std::is_same_v<arg_type, T1>)<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 f1(arg);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else=
if constexpr (std::is_same_v<arg_type,
T2>)<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 f2(arg);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else if conste=
xpr (std::is_same_v<arg_type,
T3>)<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 f3(arg);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 else<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 assert(false);<br>
=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 });<br>
=C2=A0=C2=A0=C2=A0 }<br>
=C2=A0=C2=A0=C2=A0 <br>
or even like<br>
<br>
=C2=A0=C2=A0=C2=A0 template<typename T1, typename T2, typename T=
3><br>
=C2=A0=C2=A0=C2=A0 void do_something() {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct visitor {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
void operator()(const T1 &arg) const {f1(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
void operator()(const T2 &arg) const {f2(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
void operator()(const T3 &arg) const {f3(arg);}<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 };<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::visit(get(=E2=80=A6=
), visitor());<br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
in cases when we expect <T1, T2, T3> to be possibly
duplicate types (e.g. <int, int, std::string>).<br>
<br>
</blockquote>
Ok, I see the case, but I wonder of the usability of such a
variant. The standard doesn't forbid to have twice the same type,
but I would never try to use something like that. I would prefer
to wrap the types and use std::visit.<br>
</blockquote>
I personally consider such case to be strange for a usual variant,
but still perfectly valid and usable for some "special variant" type
and some more rare use cases. I.e. I'd create two variant types:
something like std::variant (with no type duplication support and
probably with no `index` field / `get<index>()` method at all,
but with `=3D value` operator, implicit from-value constructor and
implicit to-value cast operator) and std::explicit_variant (with
`index` field, with possibility to duplicate types, but without `=3D
value` operator (probably `reset(size_t index, Value value)` method
instead), without implicit from-value constructor (maybe `(size_t
index, Value value)` constructor instead, with
`visit(std::function<void(size_t, Value)>)` visiting), and
without implicit to-value cast operator (`get<index>()` method
instead)) =E2=80=94 with considering the first one as "main", but
understanding that some cases need second (like std::set and
std::multiset). But stdlib architects decided to merge both in the
single class; so that class needs to support full feature set for
both approaches.<br>
<br>
<blockquote type=3D"cite"
cite=3D"mid:37699e79-5dd5-740d-21e4-efdacce5dbc9@wanadoo.fr"> <br>
<blockquote type=3D"cite"
cite=3D"mid:b62a444e-3242-0858-3103-81bc05dfbee0@gmail.com">
Although I don't consider usage with duplicate types and
(therefore) relying on index to be important parts of
std::variant (personally I, if I designed std::variant, probably
wouldn't allow it at all (possibly having it in a different
class, like std::multiset vs std::set)), they are allowed, so
the way is already chosen. And even I sometimes use it (e.g.
when I got a set of
having-common-interface-but-non-having-common-ancestor
Java-iterator-like classes with `i.hasNext()` and
`i.next()`-like methods and was going to build a
`concatenate(i1, i2, i3)`-like function). But those who go this
way (trying to assume that std::variant allows duplicate types)
finally find incompleteness of std::variant for that approach.<br>
</blockquote>
I agree that the unsafe access could have a sense in this case and
be coherent. <br>
I'll give it a neutral vote as I don't think I need it, but maybe
if you can elaborate with a realistic example, I could change my
mind.<br>
<blockquote type=3D"cite"
cite=3D"mid:b62a444e-3242-0858-3103-81bc05dfbee0@gmail.com"> <br>
P.S.: Sorry, if I described it not enough clearly, I was in
hurry. Please, say if it's not understandable =E2=80=94 then I may
rewrite later.<br>
</blockquote>
Don't worry, I believe I understood it.<br>
<p><br>
</p>
<p>Vicente<br>
</p>
</blockquote>
<br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e2ee17f4-0b5b-1cf1-3d79-29611793d9e4%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e2ee17f4-0b5b-1cf1-3d79-29611793d9e4%=
40gmail.com</a>.<br />
--------------47DD56AED936AF81A899DE50--
.
Author: Oleksandr Pikozh <o.pikozh@gmail.com>
Date: Thu, 15 Feb 2018 16:42:49 +0200
Raw View
This is a multi-part message in MIME format.
--------------7A29FBD02C162E2D88273F92
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
On 16.01.18 21:17, Tony V E wrote:
> On Tue, Jan 16, 2018 at 11:35 AM, Nicol Bolas <jmckesson@gmail.com=20
> <mailto:jmckesson@gmail.com>> wrote:
>
> On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksandr
> Pikozh wrote:
>
> Well, an object is often used in different ways from different
> parts of code: more carefree from relatively-rarely-called
> routines and more optimized from relatively-often-called
> routines. Therefore it's good for the same tool to support
> different modes; sometimes I want checking, sometimes I don't
> (i.e. I want std::variant that keeps its `index`, but
> sometimes to allow to do the `get`-like thing without internal
> checks); as for me, that's the main goal of C++ =E2=80=94 to supp=
ort
> higher-level programming without losing the low-level control.
> Absence of unchecked operations (comparable to
> std::optional::operator* and std::vector::operator[]) makes
> std::variant (almost) useless for me: it looks more
> psychologically-comfortable to use "enum state + union value"
> from the beginning, than to integrate std::variant with
> feeling that it implies checks that I can never get rid
> of(even in cases when inner type is guaranteed by outer logic).
>
> Besides that the same your argument can be applied for
> std::optional too =E2=80=94 "if you didn't want checking, you'd b=
e
> using a `T value` instead of `std::optional<T> value`", right?
> (But no, we still have checkless `std::optional::operator*` =E2=
=80=94
> because there is no need to check again in `if (o) {=E2=80=A6; f(=
*o);
> =E2=80=A6;}`-like cases, for example.)
>
> "you're supposed to be visiting it and acting on it that way"
> =E2=80=94 am I supposed to act _only_ in that way?
>
>
> I generally consider the use of `get` on a variant/at all/ to be a
> code-smell. A function which takes a variant is a function that is
> expected to be able to operate correctly on/all/ of the possible
> values in the variant. And the most effective way to achieve that
> is to use visitation when you want to access the member. By using
> `get`, you're saying that the code in question simply can't handle
> the other possible states of the variant. That's the wrong way to
> use a variant.
>
> Visitation fixes so many problems. It makes it statically
> impossible for you to forget to handle a state. It makes your code
> more readable (to a degree), since you can use the variant value
> like it were a regular value. It discourages lots of conditions.
> And so forth.
>
> That's not to say that `get` is bad. It's simply not a tool that
> should be in such frequent use that not having an unchecked
> version is a legitimate problem.
>
> Consider your example of "when inner type is guaranteed by outer
> logic". How did this "outer logic" provide this guarantee? Did it
> create the `variant` with that state? If so... why did it bundle
> it in a `variant`, when it clearly only provides an object of a
> specific type? Did the "outer logic" already do the test? If so,
> why did it not unpack the object directly when it did that test,
> and just pass the object of the right type? If the "inner" logic
> can only handle a specific state, why is it being given an object
> that can assume states it cannot handle?=C2=A0That is, rather than:
>
> |
> if(var.index()=3D=3Drequired_index)
> {
> auto&value =3Dget<required_index>(var);
> }
> |
>
> You do this:
>
> |
> if(autoptr =3Dget_if<required_index>(&var);ptr)
> {
> //use `ptr`
> }
> |
>
> The fundamental difference between `optional` and `variant` is
> that the former only ever has 2 states. The behavior for the
> unengaged state will almost always be "do nothing", while the
> behavior for the engaged state will be "do something". Your code
> strongly suggests that you're trying to treat a `variant` like an
> `optional`. And we have a way to do that: get a pointer to the member=
..
> *
> *
> Also, I'm curious as to your application where a single
> conditional check is sufficient to make the type "(almost) useless
> for me". Seriously, is that trivial performance /really/
> sufficient to go write your own variant type or to use something
> less feature-rich?
>
> You're also missing another problem with checked vs. unchecked
> operations: consistency.
>
> In the C++ standard library, the way you tell whether an operation
> is checked or unchecked is that the unchecked operation uses
> an/operator/. `vector::operator[]`, `optional::operator*`, and so
> on are operators. If you use a named function, then it is a
> checked operation. `vector::at`, `optional::value`, and so forth.
>
>
>
> The std isn't very consistent, but it does tend to favour the fast=20
> over the safe.=C2=A0 It might have been better to make the unsafe=20
> operations long/ugly names, but that would have hurt C++ adoption in=20
> the early days.
>
> One attempt at consistency is that (due to pointers) operator* is seen=20
> as "potentially dangerous", so optional wanted to use the same syntax=20
> for the same danger. Great.
>
> Note, however, that variant is using std::get, which was previously=20
> noexcept (for tuple), but can throw for variant - different warning=20
> signs for the same syntax :-(
>
> And they are fundamentally different operations "get one of many" vs=20
> "get the only one, if correct".=C2=A0 This unfortunate naming is also why=
=20
> Structured Bindings check for tuple_size in addition to checking=20
> whether get "works" (ie compiles).=C2=A0 std::get should have been called=
=20
> std::tuple_get: to be more specific, to not steal a general name, and=20
> to match tuple_size and tuple_element. And variant should have used=20
> something else.
>
> And optional doesn't use get, it uses value().=C2=A0 (But std::value()=20
> would also be a bad name for std::get_could_throw())
> Smart pointers use get, they are also a warning sign (loss of=20
> abstraction) - but a different one from variant (could throw), and=20
> different from optional.value() (also could throw).
>
>
> Anyhow, someone could easily propose a "unchecked_get" for variant.=C2=A0=
I=20
> think, in this case, it would need to be an ugly name.
> Or call it get_ub() since it could lead to Undefined Behaviour, and=20
> who doesn't want to get that.
"I think, in this case, it would need to be an ugly name" =E2=80=94 sure, t=
hat=20
was exactly my thought (I didn't intend a new method to have a nice name).
Does the phrase "anyhow, someone could easily propose a 'unchecked_get'=20
for variant" means that I can try writing a proposal (in the way=20
described in this guide: https://isocpp.org/std/submit-a-proposal)? Or=20
is this practicallyunpromising?
Thanks.
P.S.: Sorry for answering / continuing the thread only now, at that time=20
I was unable to reply to the rest of the thread.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/89c2a0c2-6107-9186-9057-0b858887bf8e%40gmail.com=
..
--------------7A29FBD02C162E2D88273F92
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
On 16.01.18 21:17, Tony V E wrote:<br>
<blockquote type=3D"cite"
cite=3D"mid:CAOHCbisTJuZcmrJFdvH_YUH5qsEbQQJLBgKtFR0b2gZRg6C3Xw@mail.gmail.=
com">
<div dir=3D"ltr">On Tue, Jan 16, 2018 at 11:35 AM, Nicol Bolas <span
dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com"
target=3D"_blank" moz-do-not-send=3D"true">jmckesson@gmail.com<=
/a>></span>
wrote:<br>
<div class=3D"gmail_extra">
<div class=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr"><span class=3D"">On Tuesday, January 16, 201=
8
at 10:53:38 AM UTC-5, Oleksandr Pikozh wrote:
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px
#ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000"> Well, an
object is often used in different ways from
different parts of code: more <span lang=3D"en"><span=
>carefree
from relatively-rarely-called routines and
more optimized from </span></span><span
lang=3D"en"><span><span lang=3D"en"><span>relativel=
y-often-called
routines</span></span>. Therefore it's
good for the same tool to support different
modes; sometimes I want checking, sometimes I
don't (i.e. I want std::variant that keeps its
`index`, but sometimes to allow to do the
`get`-like thing without internal checks); as
for me, that's the main goal of C++ =E2=80=94 to
support higher-level programming without
losing the low-level control. Absence of
unchecked operations (comparable to
std::optional::operator* and
std::vector::operator[]) makes std::variant
(almost) useless for me: it looks more
psychologically-comfortable to use "enum state
+ union value" from the beginning, than to
integrate std::variant with feeling that it
implies checks that I can never get rid of</span>=
</span><span
lang=3D"en"><span><span lang=3D"en"><span> (even in
cases when inner type is guaranteed by
outer logic).</span></span></span></span>
<p><span lang=3D"en"><span><span lang=3D"en"><span>Be=
sides
that the same your argument can be
applied for std::optional too =E2=80=94 "</=
span></span></span></span><span
lang=3D"en"><span><span lang=3D"en"><span>if you
didn't want checking, you'd be using a
`T value` instead of
`std::optional<T> value`</span></span=
></span></span><span
lang=3D"en"><span><span lang=3D"en"><span><span
lang=3D"en"><span><span lang=3D"en"><span=
>"</span></span></span></span>,
right? (But no, we still have checkless
`std::optional::operator*` =E2=80=94 becaus=
e
there is no need to check again in `if
(o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like ca=
ses, for
example.)<br>
</span></span></span></span></p>
<p><span lang=3D"en"><span><span lang=3D"en"><span>"<=
/span></span></span></span><span
lang=3D"en"><span><span lang=3D"en"><span>you're
supposed to be visiting it and acting on
it that way" =E2=80=94 am I supposed to act
_only_ in that way?<br>
</span></span></span></span></p>
</div>
</blockquote>
<div><br>
</div>
</span>
<div>I generally consider the use of `get` on a variant<i>
at all</i> to be a code-smell. A function which
takes a variant is a function that is expected to be
able to operate correctly on<i> all</i> of the
possible values in the variant. And the most effective
way to achieve that is to use visitation when you want
to access the member. By using `get`, you're saying
that the code in question simply can't handle the
other possible states of the variant. That's the wrong
way to use a variant.</div>
<div><br>
</div>
<div>Visitation fixes so many problems. It makes it
statically impossible for you to forget to handle a
state. It makes your code more readable (to a degree),
since you can use the variant value like it were a
regular value. It discourages lots of conditions. And
so forth.</div>
<div><br>
</div>
<div>That's not to say that `get` is bad. It's simply
not a tool that should be in such frequent use that
not having an unchecked version is a legitimate
problem.</div>
<div><br>
</div>
<div>Consider your example of "<span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px">when
inner type is guaranteed by outer logic". How did
this "outer logic" provide this guarantee? Did it
create the `variant` with that state? If so... why
did it bundle it in a `variant`, when it clearly
only provides an object of a specific type? Did the
"outer logic" already do the test? If so, why did it
not unpack the object directly when it did that
test, and just pass the object of the right type? <span=
>If
the "inner" logic can only handle a specific
state, why is it being given an object that can
assume states it cannot handle?</span>=C2=A0That is,
rather than:</span></div>
<div><span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px"><br>
</span></div>
<div class=3D"m_8434276007629405093prettyprint"
style=3D"border:1px solid
rgb(187,187,187);word-wrap:break-word;background-color:rg=
b(250,250,250)"><code
class=3D"m_8434276007629405093prettyprint">
<div class=3D"m_8434276007629405093subprettyprint"><spa=
n
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">if</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">(</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">var</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">.</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000">index</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">()</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"> </span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">=3D=3D</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"> required_index</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">)</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"><br>
</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">{</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"><br>
=C2=A0 </span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">auto</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"> </span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">&</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000">value </span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">=3D</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"> </span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">get</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#080"><required_index></span><=
span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">(</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">var</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">);</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"><br>
</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">}</span></div>
</code></div>
<div><span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px"><br>
</span></div>
<div><span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px">You
do this:</span></div>
<div><span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px"><br>
</span></div>
<div class=3D"m_8434276007629405093prettyprint"
style=3D"border:1px solid
rgb(187,187,187);word-wrap:break-word;background-color:rg=
b(250,250,250)"><code
class=3D"m_8434276007629405093prettyprint">
<div class=3D"m_8434276007629405093subprettyprint"><spa=
n
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">if</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">(</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">auto</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"> ptr </span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">=3D</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"> get_if</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#080"><required_index></span><=
span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">(&</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#008">var</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">);</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"> ptr</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">)</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"><br>
</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">{</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"><br>
=C2=A0 </span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#800">//use `ptr`</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#000"><br>
</span><span
class=3D"m_8434276007629405093styled-by-prettify"
style=3D"color:#660">}</span></div>
</code></div>
<div><span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px"><br>
</span><span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px"></span></div>
<div><span
style=3D"display:inline!important;float:none;background-color:transparent;c=
olor:rgb(34,34,34);font-family:"Arial","Helvetica",sans=
-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400=
;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px">The
fundamental difference between `optional` and
`variant` is that the former only ever has 2 states.
The behavior for the unengaged state will almost
always be "do nothing", while the behavior for the
engaged state will be "do something". </span>Your
code strongly suggests that you're trying to treat a
`variant` like an `optional`. And we have a way to do
that: get a pointer to the member.</div>
<div><b><br>
</b></div>
<div>Also, I'm curious as to your application where a
single conditional check is sufficient to make the
type "(almost) useless for me". Seriously, is that
trivial performance <i>really</i> sufficient to go
write your own variant type or to use something less
feature-rich?</div>
<div><br>
</div>
<div>You're also missing another problem with checked
vs. unchecked operations: consistency.</div>
<div><br>
</div>
<div>In the C++ standard library, the way you tell
whether an operation is checked or unchecked is that
the unchecked operation uses an<i> operator</i>.
`vector::operator[]`, `optional::operator*`, and so on
are operators. If you use a named function, then it is
a checked operation. `vector::at`, `optional::value`,
and so forth.</div>
</div>
</blockquote>
<div><br>
</div>
<div><br>
</div>
<div>The std isn't very consistent, but it does tend to
favour the fast over the safe.=C2=A0 It might have been bette=
r
to make the unsafe operations long/ugly names, but that
would have hurt C++ adoption in the early days.</div>
<div><br>
</div>
<div>One attempt at consistency is that (due to pointers)
operator* is seen as "potentially dangerous", so optional
wanted to use the same syntax for the same danger. Great.</di=
v>
<div><br>
</div>
<div>Note, however, that variant is using std::get, which
was previously noexcept (for tuple), but can throw for
variant - different warning signs for the same syntax :-(</di=
v>
<div><br>
</div>
<div>And they are fundamentally different operations "get
one of many" vs "get the only one, if correct".=C2=A0 This
unfortunate naming is also why Structured Bindings check
for tuple_size in addition to checking whether get "works"
(ie compiles).=C2=A0 std::get should have been called
std::tuple_get: to be more specific, to not steal a
general name, and to match tuple_size and tuple_element.
And variant should have used something else.</div>
<div><br>
</div>
<div>And optional doesn't use get, it uses value().=C2=A0 (But
std::value() would also be a bad name for
std::get_could_throw())</div>
<div>Smart pointers use get, they are also a warning sign
(loss of abstraction) - but a different one from variant
(could throw), and different from optional.value() (also
could throw).<br>
</div>
<div><br>
</div>
<div><br>
</div>
<div>Anyhow, someone could easily propose a "unchecked_get"
for variant.=C2=A0 I think, in this case, it would need to be
an ugly name.</div>
<div>Or call it get_ub() since it could lead to Undefined
Behaviour, and who doesn't want to get that.</div>
</div>
</div>
</div>
</blockquote>
<br>
"I think, in this case, it would need to be an ugly name" =E2=80=94 sur=
e,
that was exactly my thought (I didn't intend a new method to have a
nice name).<br>
<br>
Does the phrase "anyhow, someone could easily propose a
'unchecked_get' for variant" means that I can try writing a proposal
(in the way described in thi<tt></tt>s guide:
<a class=3D"moz-txt-link-freetext" href=3D"https://isocpp.org/std/submi=
t-a-proposal">https://isocpp.org/std/submit-a-proposal</a>)? Or is this pra=
ctically<span
class=3D"gt-baf-word-clickable"> </span><span id=3D"result_box"
class=3D"short_text" lang=3D"en"><span class=3D"">unpromising</span><=
/span>?<br>
<br>
Thanks.<br>
<br>
P.S.: Sorry for answering / continuing the thread only now, at that
time I was unable to reply to the rest of the thread.<br>
<br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/89c2a0c2-6107-9186-9057-0b858887bf8e%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/89c2a0c2-6107-9186-9057-0b858887bf8e%=
40gmail.com</a>.<br />
--------------7A29FBD02C162E2D88273F92--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 15 Feb 2018 07:36:07 -0800 (PST)
Raw View
------=_Part_1132_1677678150.1518708967766
Content-Type: multipart/alternative;
boundary="----=_Part_1133_330521614.1518708967767"
------=_Part_1133_330521614.1518708967767
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Thursday, February 15, 2018 at 9:43:07 AM UTC-5, Oleksandr Pikozh wrote:
>
> On 16.01.18 21:17, Tony V E wrote:
>
> On Tue, Jan 16, 2018 at 11:35 AM, Nicol Bolas <jmck...@gmail.com=20
> <javascript:>> wrote:
>
>> On Tuesday, January 16, 2018 at 10:53:38 AM UTC-5, Oleksandr Pikozh=20
>> wrote:=20
>>>
>>> Well, an object is often used in different ways from different parts of=
=20
>>> code: more carefree from relatively-rarely-called routines and more=20
>>> optimized from relatively-often-called routines. Therefore it's good=20
>>> for the same tool to support different modes; sometimes I want checking=
,=20
>>> sometimes I don't (i.e. I want std::variant that keeps its `index`, but=
=20
>>> sometimes to allow to do the `get`-like thing without internal checks);=
as=20
>>> for me, that's the main goal of C++ =E2=80=94 to support higher-level p=
rogramming=20
>>> without losing the low-level control. Absence of unchecked operations=
=20
>>> (comparable to std::optional::operator* and std::vector::operator[]) ma=
kes=20
>>> std::variant (almost) useless for me: it looks more=20
>>> psychologically-comfortable to use "enum state + union value" from the=
=20
>>> beginning, than to integrate std::variant with feeling that it implies=
=20
>>> checks that I can never get rid of (even in cases when inner type is=20
>>> guaranteed by outer logic).=20
>>>
>>> Besides that the same your argument can be applied for std::optional to=
o=20
>>> =E2=80=94 "if you didn't want checking, you'd be using a `T value` inst=
ead of=20
>>> `std::optional<T> value`", right? (But no, we still have checkless=20
>>> `std::optional::operator*` =E2=80=94 because there is no need to check =
again in `if=20
>>> (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like cases, for example.)
>>>
>>> "you're supposed to be visiting it and acting on it that way" =E2=80=94=
am I=20
>>> supposed to act _only_ in that way?
>>>
>>
>> I generally consider the use of `get` on a variant* at all* to be a=20
>> code-smell. A function which takes a variant is a function that is expec=
ted=20
>> to be able to operate correctly on* all* of the possible values in the=
=20
>> variant. And the most effective way to achieve that is to use visitation=
=20
>> when you want to access the member. By using `get`, you're saying that t=
he=20
>> code in question simply can't handle the other possible states of the=20
>> variant. That's the wrong way to use a variant.
>>
>> Visitation fixes so many problems. It makes it statically impossible for=
=20
>> you to forget to handle a state. It makes your code more readable (to a=
=20
>> degree), since you can use the variant value like it were a regular valu=
e.=20
>> It discourages lots of conditions. And so forth.
>>
>> That's not to say that `get` is bad. It's simply not a tool that should=
=20
>> be in such frequent use that not having an unchecked version is a=20
>> legitimate problem.
>>
>> Consider your example of "when inner type is guaranteed by outer logic".=
=20
>> How did this "outer logic" provide this guarantee? Did it create the=20
>> `variant` with that state? If so... why did it bundle it in a `variant`,=
=20
>> when it clearly only provides an object of a specific type? Did the "out=
er=20
>> logic" already do the test? If so, why did it not unpack the object=20
>> directly when it did that test, and just pass the object of the right ty=
pe? If=20
>> the "inner" logic can only handle a specific state, why is it being give=
n=20
>> an object that can assume states it cannot handle? That is, rather than:
>>
>> if(var.index() =3D=3D required_index)
>> {
>> auto &value =3D get<required_index>(var);
>> }
>>
>> You do this:
>>
>> if(auto ptr =3D get_if<required_index>(&var); ptr)
>> {
>> //use `ptr`
>> }
>>
>> The fundamental difference between `optional` and `variant` is that the=
=20
>> former only ever has 2 states. The behavior for the unengaged state will=
=20
>> almost always be "do nothing", while the behavior for the engaged state=
=20
>> will be "do something". Your code strongly suggests that you're trying=
=20
>> to treat a `variant` like an `optional`. And we have a way to do that: g=
et=20
>> a pointer to the member.
>>
>> Also, I'm curious as to your application where a single conditional chec=
k=20
>> is sufficient to make the type "(almost) useless for me". Seriously, is=
=20
>> that trivial performance *really* sufficient to go write your own=20
>> variant type or to use something less feature-rich?
>>
>> You're also missing another problem with checked vs. unchecked=20
>> operations: consistency.
>>
>> In the C++ standard library, the way you tell whether an operation is=20
>> checked or unchecked is that the unchecked operation uses an* operator*.=
=20
>> `vector::operator[]`, `optional::operator*`, and so on are operators. If=
=20
>> you use a named function, then it is a checked operation. `vector::at`,=
=20
>> `optional::value`, and so forth.
>>
>
>
> The std isn't very consistent, but it does tend to favour the fast over=
=20
> the safe. It might have been better to make the unsafe operations=20
> long/ugly names, but that would have hurt C++ adoption in the early days.
>
> One attempt at consistency is that (due to pointers) operator* is seen as=
=20
> "potentially dangerous", so optional wanted to use the same syntax for th=
e=20
> same danger. Great.
>
> Note, however, that variant is using std::get, which was previously=20
> noexcept (for tuple), but can throw for variant - different warning signs=
=20
> for the same syntax :-(
>
> And they are fundamentally different operations "get one of many" vs "get=
=20
> the only one, if correct". This unfortunate naming is also why Structure=
d=20
> Bindings check for tuple_size in addition to checking whether get "works"=
=20
> (ie compiles). std::get should have been called std::tuple_get: to be mo=
re=20
> specific, to not steal a general name, and to match tuple_size and=20
> tuple_element. And variant should have used something else.
>
> And optional doesn't use get, it uses value(). (But std::value() would=
=20
> also be a bad name for std::get_could_throw())
> Smart pointers use get, they are also a warning sign (loss of abstraction=
)=20
> - but a different one from variant (could throw), and different from=20
> optional.value() (also could throw).
>
>
> Anyhow, someone could easily propose a "unchecked_get" for variant. I=20
> think, in this case, it would need to be an ugly name.
> Or call it get_ub() since it could lead to Undefined Behaviour, and who=
=20
> doesn't want to get that.
>
>
> "I think, in this case, it would need to be an ugly name" =E2=80=94 sure,=
that was=20
> exactly my thought (I didn't intend a new method to have a nice name).
>
> Does the phrase "anyhow, someone could easily propose a 'unchecked_get'=
=20
> for variant" means that I can try writing a proposal (in the way describe=
d=20
> in this guide: https://isocpp.org/std/submit-a-proposal)? Or is this=20
> practically unpromising?
>
You can certainly try it. But:
1. Your proposal will need good motivation. Preferably real-world code, and=
=20
preferably not a simplified case. The problem with simplified cases is that=
=20
compilers will often catch them and optimize out the second check. The=20
other thing such motivation requires is show that you genuinely *cannot*=20
design your code in some other way (by passing a reference/pointer rather=
=20
than a `variant` or whatever).
Remember: `variant` is supposed to be a *safe* type; by providing an=20
unchecked-get, you're removing safety from the type. To overcome that, your=
=20
motivation needs to be unassailable.
2. You'll need someone to go to a standards meeting to get the proposal=20
discussed. That could be yourself or someone else.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/8f608ec5-1147-4652-abea-d207acaea633%40isocpp.or=
g.
------=_Part_1133_330521614.1518708967767
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, February 15, 2018 at 9:43:07 AM UTC-5=
, Oleksandr Pikozh wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div text=3D"#000000" bgcolor=3D"#FFFFFF">
On 16.01.18 21:17, Tony V E wrote:<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Tue, Jan 16, 2018 at 11:35 AM, Nicol Bolas <span =
dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-ma=
ilto=3D"4ojPZjzbCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'java=
script:';return true;" onclick=3D"this.href=3D'javascript:';ret=
urn true;">jmck...@gmail.com</a>></span>
wrote:<br>
<div>
<div class=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr"><span>On Tuesday, January 16, 2018
at 10:53:38 AM UTC-5, Oleksandr Pikozh wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000"> Well, an
object is often used in different ways from
different parts of code: more <span lang=3D"en"><span=
>carefree
from relatively-rarely-called routines and
more optimized from </span></span><span lang=3D"e=
n"><span><span lang=3D"en"><span>relatively-often-called
routines</span></span>. Therefore it's
good for the same tool to support different
modes; sometimes I want checking, sometimes I
don't (i.e. I want std::variant that keeps it=
s
`index`, but sometimes to allow to do the
`get`-like thing without internal checks); as
for me, that's the main goal of C++ =E2=80=94=
to
support higher-level programming without
losing the low-level control. Absence of
unchecked operations (comparable to
std::optional::operator* and
std::vector::operator[]) makes std::variant
(almost) useless for me: it looks more
psychologically-comfortable to use "enum sta=
te
+ union value" from the beginning, than to
integrate std::variant with feeling that it
implies checks that I can never get rid of</span>=
</span><span lang=3D"en"><span><span lang=3D"en"><span> (even in
cases when inner type is guaranteed by
outer logic).</span></span></span></span>
<p><span lang=3D"en"><span><span lang=3D"en"><span>Be=
sides
that the same your argument can be
applied for std::optional too =E2=80=94 &qu=
ot;</span></span></span></span><span lang=3D"en"><span><span lang=3D"en"><s=
pan>if you
didn't want checking, you'd be usin=
g a
`T value` instead of
`std::optional<T> value`</span></span=
></span></span><span lang=3D"en"><span><span lang=3D"en"><span><span lang=
=3D"en"><span><span lang=3D"en"><span>"</span></span></span></span>,
right? (But no, we still have checkless
`std::optional::operator*` =E2=80=94 becaus=
e
there is no need to check again in `if
(o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like ca=
ses, for
example.)<br>
</span></span></span></span></p>
<p><span lang=3D"en"><span><span lang=3D"en"><span>&q=
uot;</span></span></span></span><span lang=3D"en"><span><span lang=3D"en"><=
span>you're
supposed to be visiting it and acting on
it that way" =E2=80=94 am I supposed t=
o act
_only_ in that way?<br>
</span></span></span></span></p>
</div>
</blockquote>
<div><br>
</div>
</span>
<div>I generally consider the use of `get` on a variant<i>
at all</i> to be a code-smell. A function which
takes a variant is a function that is expected to be
able to operate correctly on<i> all</i> of the
possible values in the variant. And the most effective
way to achieve that is to use visitation when you want
to access the member. By using `get`, you're saying
that the code in question simply can't handle the
other possible states of the variant. That's the wron=
g
way to use a variant.</div>
<div><br>
</div>
<div>Visitation fixes so many problems. It makes it
statically impossible for you to forget to handle a
state. It makes your code more readable (to a degree),
since you can use the variant value like it were a
regular value. It discourages lots of conditions. And
so forth.</div>
<div><br>
</div>
<div>That's not to say that `get` is bad. It's simp=
ly
not a tool that should be in such frequent use that
not having an unchecked version is a legitimate
problem.</div>
<div><br>
</div>
<div>Consider your example of "<span style=3D"display:=
inline!important;float:none;background-color:transparent;color:rgb(34,34,34=
);font-family:"Arial","Helvetica",sans-serif;font-size:=
13px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:n=
ormal;text-align:left;text-decoration:none;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px">when
inner type is guaranteed by outer logic". How did
this "outer logic" provide this guarantee? Di=
d it
create the `variant` with that state? If so... why
did it bundle it in a `variant`, when it clearly
only provides an object of a specific type? Did the
"outer logic" already do the test? If so, why=
did it
not unpack the object directly when it did that
test, and just pass the object of the right type? <span=
>If
the "inner" logic can only handle a specifi=
c
state, why is it being given an object that can
assume states it cannot handle?</span>=C2=A0That is,
rather than:</span></div>
<div><span style=3D"display:inline!important;float:none;bac=
kground-color:transparent;color:rgb(34,34,34);font-family:"Arial"=
,"Helvetica",sans-serif;font-size:13px;font-style:normal;font-var=
iant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-deco=
ration:none;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px"><br>
</span></div>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:b=
reak-word;background-color:rgb(250,250,250)"><code>
<div><span style=3D"color:#008">if</span><span style=3D=
"color:#660">(</span><span style=3D"color:#008">var</span><span style=3D"co=
lor:#660">.</span><span style=3D"color:#000">index</span><span style=3D"col=
or:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">=3D=3D</span><span style=3D"color:#000"> required_index</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#008">auto</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">&</span>=
<span style=3D"color:#000">value </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">get</span><=
span style=3D"color:#080"><required_index></span><span style=3D"color=
:#660">(</span><span style=3D"color:#008">var</span><span style=3D"color:#6=
60">);</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span></div>
</code></div>
<div><span style=3D"display:inline!important;float:none;bac=
kground-color:transparent;color:rgb(34,34,34);font-family:"Arial"=
,"Helvetica",sans-serif;font-size:13px;font-style:normal;font-var=
iant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-deco=
ration:none;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px"><br>
</span></div>
<div><span style=3D"display:inline!important;float:none;bac=
kground-color:transparent;color:rgb(34,34,34);font-family:"Arial"=
,"Helvetica",sans-serif;font-size:13px;font-style:normal;font-var=
iant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-deco=
ration:none;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px">You
do this:</span></div>
<div><span style=3D"display:inline!important;float:none;bac=
kground-color:transparent;color:rgb(34,34,34);font-family:"Arial"=
,"Helvetica",sans-serif;font-size:13px;font-style:normal;font-var=
iant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-deco=
ration:none;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px"><br>
</span></div>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:b=
reak-word;background-color:rgb(250,250,250)"><code>
<div><span style=3D"color:#008">if</span><span style=3D=
"color:#660">(</span><span style=3D"color:#008">auto</span><span style=3D"c=
olor:#000"> ptr </span><span style=3D"color:#660">=3D</span><span style=3D"=
color:#000"> get_if</span><span style=3D"color:#080"><required_index>=
</span><span style=3D"color:#660">(&</span><span style=3D"color:#008">v=
ar</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> pt=
r</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#800">//use `ptr=
`</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span></div>
</code></div>
<div><span style=3D"display:inline!important;float:none;bac=
kground-color:transparent;color:rgb(34,34,34);font-family:"Arial"=
,"Helvetica",sans-serif;font-size:13px;font-style:normal;font-var=
iant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-deco=
ration:none;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px"><br>
</span><span style=3D"display:inline!important;float:none=
;background-color:transparent;color:rgb(34,34,34);font-family:"Arial&q=
uot;,"Helvetica",sans-serif;font-size:13px;font-style:normal;font=
-variant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-=
decoration:none;text-indent:0px;text-transform:none;white-space:normal;word=
-spacing:0px"></span></div>
<div><span style=3D"display:inline!important;float:none;bac=
kground-color:transparent;color:rgb(34,34,34);font-family:"Arial"=
,"Helvetica",sans-serif;font-size:13px;font-style:normal;font-var=
iant:normal;font-weight:400;letter-spacing:normal;text-align:left;text-deco=
ration:none;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px">The
fundamental difference between `optional` and
`variant` is that the former only ever has 2 states.
The behavior for the unengaged state will almost
always be "do nothing", while the behavior fo=
r the
engaged state will be "do something". </span>=
Your
code strongly suggests that you're trying to treat a
`variant` like an `optional`. And we have a way to do
that: get a pointer to the member.</div>
<div><b><br>
</b></div>
<div>Also, I'm curious as to your application where a
single conditional check is sufficient to make the
type "(almost) useless for me". Seriously, is t=
hat
trivial performance <i>really</i> sufficient to go
write your own variant type or to use something less
feature-rich?</div>
<div><br>
</div>
<div>You're also missing another problem with checked
vs. unchecked operations: consistency.</div>
<div><br>
</div>
<div>In the C++ standard library, the way you tell
whether an operation is checked or unchecked is that
the unchecked operation uses an<i> operator</i>.
`vector::operator[]`, `optional::operator*`, and so on
are operators. If you use a named function, then it is
a checked operation. `vector::at`, `optional::value`,
and so forth.</div>
</div>
</blockquote>
<div><br>
</div>
<div><br>
</div>
<div>The std isn't very consistent, but it does tend to
favour the fast over the safe.=C2=A0 It might have been bette=
r
to make the unsafe operations long/ugly names, but that
would have hurt C++ adoption in the early days.</div>
<div><br>
</div>
<div>One attempt at consistency is that (due to pointers)
operator* is seen as "potentially dangerous", so op=
tional
wanted to use the same syntax for the same danger. Great.</di=
v>
<div><br>
</div>
<div>Note, however, that variant is using std::get, which
was previously noexcept (for tuple), but can throw for
variant - different warning signs for the same syntax :-(</di=
v>
<div><br>
</div>
<div>And they are fundamentally different operations "get
one of many" vs "get the only one, if correct"=
..=C2=A0 This
unfortunate naming is also why Structured Bindings check
for tuple_size in addition to checking whether get "work=
s"
(ie compiles).=C2=A0 std::get should have been called
std::tuple_get: to be more specific, to not steal a
general name, and to match tuple_size and tuple_element.
And variant should have used something else.</div>
<div><br>
</div>
<div>And optional doesn't use get, it uses value().=C2=A0 (=
But
std::value() would also be a bad name for
std::get_could_throw())</div>
<div>Smart pointers use get, they are also a warning sign
(loss of abstraction) - but a different one from variant
(could throw), and different from optional.value() (also
could throw).<br>
</div>
<div><br>
</div>
<div><br>
</div>
<div>Anyhow, someone could easily propose a "unchecked_get=
"
for variant.=C2=A0 I think, in this case, it would need to be
an ugly name.</div>
<div>Or call it get_ub() since it could lead to Undefined
Behaviour, and who doesn't want to get that.</div>
</div>
</div>
</div>
</blockquote>
<br>
"I think, in this case, it would need to be an ugly name" =E2=
=80=94 sure,
that was exactly my thought (I didn't intend a new method to have a
nice name).<br>
<br>
Does the phrase "anyhow, someone could easily propose a
'unchecked_get' for variant" means that I can try writing =
a proposal
(in the way described in thi<tt></tt>s guide:
<a href=3D"https://isocpp.org/std/submit-a-proposal" target=3D"_blank" =
rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url=
?q\x3dhttps%3A%2F%2Fisocpp.org%2Fstd%2Fsubmit-a-proposal\x26sa\x3dD\x26sntz=
\x3d1\x26usg\x3dAFQjCNGlLyCIYYQUZNTTJdUEpCYxvwG8Ig';return true;" oncli=
ck=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fisocpp=
..org%2Fstd%2Fsubmit-a-proposal\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGlLy=
CIYYQUZNTTJdUEpCYxvwG8Ig';return true;">https://isocpp.org/std/submit-<=
wbr>a-proposal</a>)? Or is this practically<span> </span><span lang=3D"en">=
<span>unpromising</span></span>?<br></div></blockquote><div><br>You can cer=
tainly try it. But:<br><br>1. Your proposal will need good motivation. Pref=
erably real-world code, and preferably not a simplified case. The problem w=
ith simplified cases is that compilers will often catch them and optimize o=
ut the second check. The other thing such motivation requires is show that =
you genuinely <i>cannot</i> design your code in some other way (by passing =
a reference/pointer rather than a `variant` or whatever).<br><br>Remember: =
`variant` is supposed to be a <i>safe</i> type; by providing an unchecked-g=
et, you're removing safety from the type. To overcome that, your motiva=
tion needs to be unassailable.<br><br>2. You'll need someone to go to a=
standards meeting to get the proposal discussed. That could be yourself or=
someone else.</div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/8f608ec5-1147-4652-abea-d207acaea633%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8f608ec5-1147-4652-abea-d207acaea633=
%40isocpp.org</a>.<br />
------=_Part_1133_330521614.1518708967767--
------=_Part_1132_1677678150.1518708967766--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Thu, 15 Feb 2018 15:50:07 -0800 (PST)
Raw View
------=_Part_2255_150621385.1518738607872
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Thursday, 15 February 2018 17:36:07 UTC+2, Nicol Bolas wrote:
> On Thursday, February 15, 2018 at 9:43:07 AM UTC-5, Oleksandr Pikozh wrot=
e:
> =20
> =20
> =20
> =20
>=20
> On 16.01.18 21:17, Tony V E wrote:
>=20
> =20
> =20
> On Tue, Jan 16, 2018 at 11:35 AM, Nicol Bolas <jmck...@gmail.com>
> wrote:
>=20
> =20
>=20
> =20
>=20
> =20
> =20
> On Tuesday, January 16, 2018
> at 10:53:38 AM UTC-5, Oleksandr Pikozh wrote:
> =20
> =20
> Well, an
> object is often used in different ways from
> different parts of code: more carefree
> from relatively-rarely-called routines and
> more optimized from relatively-often-called
> routines. Therefore it's
> good for the same tool to support different
> modes; sometimes I want checking, sometimes I
> don't (i.e. I want std::variant that keeps its
> `index`, but sometimes to allow to do the
> `get`-like thing without internal checks); as
> for me, that's the main goal of C++ =E2=80=94 t=
o
> support higher-level programming without
> losing the low-level control. Absence of
> unchecked operations (comparable to
> std::optional::operator* and
> std::vector::operator[]) makes std::variant
> (almost) useless for me: it looks more
> psychologically-comfortable to use "enum state
> + union value" from the beginning, than to
> integrate std::variant with feeling that it
> implies checks that I can never get rid of (eve=
n in
> cases when inner type is guaranteed by
> outer logic).
> =20
> Besides
> that the same your argument can be
> applied for std::optional too =E2=80=94 "=
if you
> didn't want checking, you'd be using a
> `T value` instead of
> `std::optional<T> value`",
> right? (But no, we still have checkless
> `std::optional::operator*` =E2=80=94 beca=
use
> there is no need to check again in `if
> (o) {=E2=80=A6; f(*o); =E2=80=A6;}`-like =
cases, for
> example.)
>=20
> =20
> =20
> "you're
> supposed to be visiting it and acting on
> it that way" =E2=80=94 am I supposed to a=
ct
> _only_ in that way?
>=20
> =20
> =20
> =20
> =20
>=20
>=20
> =20
> =20
> =20
> I generally consider the use of `get` on a variant
> at all to be a code-smell. A function which
> takes a variant is a function that is expected to be
> able to operate correctly on all of the
> possible values in the variant. And the most effective
> way to achieve that is to use visitation when you want
> to access the member. By using `get`, you're saying
> that the code in question simply can't handle the
> other possible states of the variant. That's the wrong
> way to use a variant.
> =20
>=20
>=20
> =20
> =20
> Visitation fixes so many problems. It makes it
> statically impossible for you to forget to handle a
> state. It makes your code more readable (to a degree),
> since you can use the variant value like it were a
> regular value. It discourages lots of conditions. And
> so forth.
> =20
>=20
>=20
> =20
> =20
> That's not to say that `get` is bad. It's simply
> not a tool that should be in such frequent use that
> not having an unchecked version is a legitimate
> problem.
> =20
>=20
>=20
> =20
> =20
> Consider your example of "when
> inner type is guaranteed by outer logic". How did
> this "outer logic" provide this guarantee? Did it
> create the `variant` with that state? If so... why
> did it bundle it in a `variant`, when it clearly
> only provides an object of a specific type? Did the
> "outer logic" already do the test? If so, why did it
> not unpack the object directly when it did that
> test, and just pass the object of the right type? If
> the "inner" logic can only handle a specific
> state, why is it being given an object that can
> assume states it cannot handle?=C2=A0That is,
> rather than:
> =20
>=20
>=20
> =20
> =20
>=20
> =20
> if(var.index() =3D=3D required_index)
>=20
> {
>=20
> =C2=A0 auto &value =3D get<required_index>(var);
>=20
> }
> =20
> =20
>=20
>=20
> =20
> =20
> You
> do this:
> =20
>=20
>=20
> =20
> =20
>=20
> =20
> if(auto ptr =3D get_if<required_index>(&var); ptr)
>=20
> {
>=20
> =C2=A0 //use `ptr`
>=20
> }
> =20
> =20
>=20
>=20
> =20
> =20
> The
> fundamental difference between `optional` and
> `variant` is that the former only ever has 2 states.
> The behavior for the unengaged state will almost
> always be "do nothing", while the behavior for the
> engaged state will be "do something". Your
> code strongly suggests that you're trying to treat a
> `variant` like an `optional`. And we have a way to do
> that: get a pointer to the member.
> =20
>=20
>=20
> =20
> =20
> Also, I'm curious as to your application where a
> single conditional check is sufficient to make the
> type "(almost) useless for me". Seriously, is that
> trivial performance really sufficient to go
> write your own variant type or to use something less
> feature-rich?
> =20
>=20
>=20
> =20
> =20
> You're also missing another problem with checked
> vs. unchecked operations: consistency.
> =20
>=20
>=20
> =20
> =20
> In the C++ standard library, the way you tell
> whether an operation is checked or unchecked is that
> the unchecked operation uses an operator.
> `vector::operator[]`, `optional::operator*`, and so on
> are operators. If you use a named function, then it is
> a checked operation. `vector::at`, `optional::value`,
> and so forth.
> =20
> =20
> =20
>=20
>=20
> =20
> =20
>=20
>=20
> =20
> =20
> The std isn't very consistent, but it does tend to
> favour the fast over the safe.=C2=A0 It might have been bet=
ter
> to make the unsafe operations long/ugly names, but that
> would have hurt C++ adoption in the early days.
> =20
>=20
>=20
> =20
> =20
> One attempt at consistency is that (due to pointers)
> operator* is seen as "potentially dangerous", so optional
> wanted to use the same syntax for the same danger. Great.
> =20
>=20
>=20
> =20
> =20
> Note, however, that variant is using std::get, which
> was previously noexcept (for tuple), but can throw for
> variant - different warning signs for the same syntax :-(
> =20
>=20
>=20
> =20
> =20
> And they are fundamentally different operations "get
> one of many" vs "get the only one, if correct".=C2=A0 This
> unfortunate naming is also why Structured Bindings check
> for tuple_size in addition to checking whether get "works"
> (ie compiles).=C2=A0 std::get should have been called
> std::tuple_get: to be more specific, to not steal a
> general name, and to match tuple_size and tuple_element.
> And variant should have used something else.
> =20
>=20
>=20
> =20
> =20
> And optional doesn't use get, it uses value().=C2=A0 (But
> std::value() would also be a bad name for
> std::get_could_throw())
> =20
> Smart pointers use get, they are also a warning sign
> (loss of abstraction) - but a different one from variant
> (could throw), and different from optional.value() (also
> could throw).
>=20
> =20
> =20
>=20
>=20
> =20
> =20
>=20
>=20
> =20
> =20
> Anyhow, someone could easily propose a "unchecked_get"
> for variant.=C2=A0 I think, in this case, it would need to =
be
> an ugly name.
> =20
> Or call it get_ub() since it could lead to Undefined
> Behaviour, and who doesn't want to get that.
> =20
> =20
> =20
> =20
> =20
>=20
> "I think, in this case, it would need to be an ugly name" =E2=80=94 s=
ure,
> that was exactly my thought (I didn't intend a new method to have a
> nice name).
>=20
> =20
>=20
> Does the phrase "anyhow, someone could easily propose a
> 'unchecked_get' for variant" means that I can try writing a proposal
> (in the way described in this guide:
> https://isocpp.org/std/submit-a-proposal)? Or is this practically unp=
romising?
>=20
>=20
> You can certainly try it. But:
>=20
> 1. Your proposal will need good motivation. Preferably real-world code, a=
nd preferably not a simplified case. The problem with simplified cases is t=
hat compilers will often catch them and optimize out the second check. The =
other thing such motivation requires is show that you genuinely cannot desi=
gn your code in some other way (by passing a reference/pointer rather than =
a `variant` or whatever).
>=20
> Remember: `variant` is supposed to be a safe type; by providing an unchec=
ked-get, you're removing safety from the type. To overcome that, your motiv=
ation needs to be unassailable.
>=20
> 2. You'll need someone to go to a standards meeting to get the proposal d=
iscussed. That could be yourself or someone else.
I'm not sure whether anyone's pointed this out above, but it is already pos=
sible to perform an unchecked get with the help of the optimizer:
*std::get_if<I>(&v)
Since the optimizer will eliminate the index and pointer checks, this is pr=
actically equivalent to a hypothetical
std::get_unchecked<I>(v)
So the motivation to add unchecked get would have to be clarity in code, I =
think.=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/58b6f509-7c57-456f-81f9-fcf53c572ecc%40isocpp.or=
g.
------=_Part_2255_150621385.1518738607872--
.