Topic: Switch statement support for use with std::variant.
Author: Parker Schuh <parker.schuh@gmail.com>
Date: Wed, 1 Nov 2017 08:59:17 -0700 (PDT)
Raw View
------=_Part_10903_1031879791.1509551957293
Content-Type: multipart/alternative;
boundary="----=_Part_10904_784088170.1509551957293"
------=_Part_10904_784088170.1509551957293
Content-Type: text/plain; charset="UTF-8"
// I was investigating a variant-like typesafe union like so:
// (Support code at the end of the message).
class MyUnionType {
public:
enum class TypeEnum { A_TYPE, B_TYPE, C_TYPE, };
template <typename T>
MyUnionType(T t) : tag_(type_enum<T>) {}
operator TypeEnum() const { return tag_; }
private:
TypeEnum tag_;
};
class A { };
class B { };
class C { };
ASSIGN_ENUM_TAG(MyUnionType::TypeEnum, A, A_TYPE);
ASSIGN_ENUM_TAG(MyUnionType::TypeEnum, B, B_TYPE);
ASSIGN_ENUM_TAG(MyUnionType::TypeEnum, C, C_TYPE);
void Example() {
MyUnionType value(B{});
switch (value) {
case type_enum<A>:
printf("A\n");
break;
case type_enum<B>:
printf("B\n");
break;
case type_enum<C>:
printf("C\n");
break;
}
}
but then I thought it would be nice to be able to do this same trick with
std::variant.
One could imagine this would work like so with std::variant:
void Example(const std::variant<A, B, C>& v) {
switch(get_type_enum(v)) {
case type_enum<A>:
...
break;
case type_enum<B>:
...
break;
// Ideally compilers would warn here -Wswitch that the third variant
parameter isn't handled. Worst case this would read VARIANT_TYPE_3.
// Using integers, this would not warn.
}
}
I got pretty far with this:
I had a template method that would return a unique enum type from a
std::varint<Ts...>, but I ran into the following problems:
- If it switch takes a type T (implicitly convertible to an integral type),
it tries to convert the arguments to the integral type rather than the
argument type T (which is implicitly convertible).
- And also on the other side, an inability to extract the associated Ts...
from the uniquely constructed enum:
template <typename... Ts>
class A { enum Type {} };
Cannot deduce A from Type.
I feel like solving this for variant would only require passing just a wee
bit more template information through the switch statement by way of:
allowing:
template <typename T> enum class {};
or,
Modifying the conversion rules in switch like so:
If the switch statement implicitly converts from T to type EnumT, then, if
the case statements are implicitly convertible to T, constexpr convert them
to T, and then constexpr convert the T to EnumT, otherwise convert directly
to EnumT if it can. This way the template information can be passed through
this intermediary struct.
or,
Allow purely inner definitions to be deducible. (Deduce T for A<T>::B where
template <typename T> class A { class B {}; }; (This may have a edge-case
with specializations).
or,
Type traits struct like coroutines for switch of T? This is a bit more of a
stretch, and probably isn't worth it, but would allow
switch(std::variant...) (as would the first one)
// Support code for the example at the beginning of the message:
// Defaults to something that isn't an enum.
template <typename Enum, typename T, typename =
std::enable_if_t<std::is_enum<Enum>::value>>
struct converted_to_enum {};
template <typename T>
class TypeEnumHelper {
public:
template <typename Enum, Enum = converted_to_enum<Enum, T>::value>
constexpr operator Enum() const {
return converted_to_enum<Enum, T>::value;
}
};
template <typename T>
constexpr TypeEnumHelper<T> type_enum = TypeEnumHelper<T>();
#define ASSIGN_ENUM_TAG(UnionEnumType, Class, EnumTag) \
template<> \
struct converted_to_enum<UnionEnumType, Class> { \
static constexpr UnionEnumType value = UnionEnumType:: EnumTag; \
};
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/e0683c7a-3db4-4ee6-b10b-649d13c94cd5%40isocpp.org.
------=_Part_10904_784088170.1509551957293
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"prettyprint" style=3D"background-color: rgb(=
250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bord=
er-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><div class=3D"subprettyprint" style=3D""><div class=
=3D"subprettyprint">// I was investigating a variant-like typesafe union li=
ke so:<br><div class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);">// (=
Support code at the end of the message).<br><br class=3D"Apple-interchange-=
newline">class MyUnionType {</div><div class=3D"subprettyprint" style=3D"co=
lor: rgb(0, 0, 0);">=C2=A0public:</div><div class=3D"subprettyprint" style=
=3D"color: rgb(0, 0, 0);">=C2=A0 enum class TypeEnum {=C2=A0<span style=3D"=
font-family: Arial, Helvetica, sans-serif;">A_TYPE,=C2=A0</span><span style=
=3D"font-family: Arial, Helvetica, sans-serif;">B_TYPE,=C2=A0</span><span s=
tyle=3D"font-family: Arial, Helvetica, sans-serif;">C_TYPE,=C2=A0</span><sp=
an style=3D"font-family: Arial, Helvetica, sans-serif;">};</span></div><div=
class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);"><div class=3D"subp=
rettyprint">=C2=A0 template <typename T></div><div class=3D"subpretty=
print">=C2=A0 MyUnionType(T t) : tag_(type_enum<T>) {}</div></div><di=
v class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);"><br></div><div cl=
ass=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);">=C2=A0 operator TypeE=
num() const { return tag_; }</div><div class=3D"subprettyprint" style=3D"co=
lor: rgb(0, 0, 0);"><br></div><div class=3D"subprettyprint" style=3D"color:=
rgb(0, 0, 0);">=C2=A0private:</div><div class=3D"subprettyprint" style=3D"=
color: rgb(0, 0, 0);">=C2=A0 TypeEnum tag_;</div><div class=3D"subprettypri=
nt" style=3D"color: rgb(0, 0, 0);">};</div><div class=3D"subprettyprint" st=
yle=3D"color: rgb(0, 0, 0);"><br></div><div class=3D"subprettyprint" style=
=3D"color: rgb(0, 0, 0);">class A { };</div><div class=3D"subprettyprint" s=
tyle=3D"color: rgb(0, 0, 0);">class B { };</div><div class=3D"subprettyprin=
t" style=3D"color: rgb(0, 0, 0);">class C { };</div><div class=3D"subpretty=
print" style=3D"color: rgb(0, 0, 0);"><br></div><div class=3D"subprettyprin=
t" style=3D"color: rgb(0, 0, 0);">ASSIGN_ENUM_TAG(MyUnionType::TypeEnum, A,=
A_TYPE);</div><div class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);"=
>ASSIGN_ENUM_TAG(MyUnionType::TypeEnum, B, B_TYPE);</div><div class=3D"subp=
rettyprint" style=3D"color: rgb(0, 0, 0);">ASSIGN_ENUM_TAG(MyUnionType::Typ=
eEnum, C, C_TYPE);</div><br><div class=3D"subprettyprint" style=3D"color: r=
gb(0, 0, 0);">void Example() {</div><div class=3D"subprettyprint" style=3D"=
color: rgb(0, 0, 0);">=C2=A0 MyUnionType value(B{});</div><div class=3D"sub=
prettyprint" style=3D"color: rgb(0, 0, 0);">=C2=A0 switch (value) {</div><d=
iv class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);">=C2=A0 =C2=A0cas=
e type_enum<A>:</div><div class=3D"subprettyprint" style=3D"color: rg=
b(0, 0, 0);">=C2=A0 =C2=A0 =C2=A0printf("A\n");</div><div class=
=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);">=C2=A0 =C2=A0 =C2=A0brea=
k;</div><div class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);">=C2=A0=
=C2=A0case type_enum<B>:</div><div class=3D"subprettyprint" style=3D=
"color: rgb(0, 0, 0);">=C2=A0 =C2=A0 =C2=A0printf("B\n");</div><d=
iv class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);">=C2=A0 =C2=A0 =
=C2=A0break;</div><div class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0=
);">=C2=A0 =C2=A0case type_enum<C>:</div><div class=3D"subprettyprint=
" style=3D"color: rgb(0, 0, 0);">=C2=A0 =C2=A0 =C2=A0printf("C\n"=
);</div><div class=3D"subprettyprint" style=3D"color: rgb(0, 0, 0);">=C2=A0=
=C2=A0 =C2=A0break;</div><div class=3D"subprettyprint" style=3D"color: rgb=
(0, 0, 0);">=C2=A0 }</div><div class=3D"subprettyprint" style=3D"color: rgb=
(0, 0, 0);">}</div></div></div></div></code></div><div class=3D"prettyprint=
" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187=
, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><co=
de class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"font-=
family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);=
"><br>but then I thought it would be nice to be able to do this same trick =
with std::variant.</span><br style=3D"font-family: Arial, Helvetica, sans-s=
erif; background-color: rgb(255, 255, 255);"><br style=3D"font-family: Aria=
l, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span styl=
e=3D"font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, =
255, 255);">One could imagine this would work like so with std::variant:</s=
pan><br style=3D"font-family: Arial, Helvetica, sans-serif; background-colo=
r: rgb(255, 255, 255);"><div class=3D"prettyprint" style=3D"border-width: 1=
px; border-style: solid; border-color: rgb(187, 187, 187); font-family: Ari=
al, Helvetica, sans-serif; word-wrap: break-word;"><code class=3D"prettypri=
nt"><div class=3D"subprettyprint"><font color=3D"#660066">void Example(cons=
t std::variant<A, B, C>& v) {<br>=C2=A0 switch(get_type_enum(v)) =
{<br>=C2=A0 =C2=A0 case type_enum<A>:<br>=C2=A0 =C2=A0 =C2=A0 ...<br>=
=C2=A0 =C2=A0 =C2=A0 break;<br>=C2=A0 =C2=A0 case type_enum<B>:<br>=
=C2=A0 =C2=A0 =C2=A0 ...<br>=C2=A0 =C2=A0 =C2=A0 break;<br>=C2=A0 =C2=A0 //=
Ideally compilers would warn here -Wswitch that the third variant paramete=
r isn't handled. Worst case this would read VARIANT_TYPE_3.<br>=C2=A0 =
=C2=A0 // Using integers, this would not warn.<br>=C2=A0 }<br>}</font></div=
></code></div></div></code></div><br>I got pretty far with this:<br><br>I h=
ad a template method that would return a unique enum type from a std::varin=
t<Ts...>, but I ran into the following problems:<br><br>- If it switc=
h takes a type T (implicitly convertible to an integral type), it tries to =
convert the arguments to the integral type rather than the argument type T =
(which is implicitly convertible).<br><br>- And also on the other side, an =
inability to extract the associated Ts... from the uniquely constructed enu=
m:<br>template <typename... Ts><br>class A { enum Type {} };<br><br>C=
annot deduce A from Type.<br><br>I feel like solving this for variant would=
only require passing just a wee bit more template information through the =
switch statement by way of:<br>allowing:<br>template <typename T> enu=
m class {};<br>or,<br>Modifying the conversion rules in switch like so:<br>=
If the switch statement implicitly converts from T to type EnumT, then, if =
the case statements are implicitly convertible to T, constexpr convert them=
to T, and then constexpr convert the T to EnumT, otherwise convert directl=
y to EnumT if it can. This way the template information can be passed throu=
gh this intermediary struct.<br>or,<div>Allow purely inner definitions to b=
e deducible. (Deduce T for A<T>::B where template <typename T> =
class A { class B {}; }; =C2=A0(This may have a edge-case with specializati=
ons).<br>or,<div>Type traits struct like coroutines for switch of T? This i=
s a bit more of a stretch, and probably isn't worth it, but would allow=
switch(std::variant...) (as would the first one)=C2=A0<br><br><br><div cla=
ss=3D"prettyprint" style=3D"border-width: 1px; border-style: solid; border-=
color: rgb(187, 187, 187); background-color: rgb(250, 250, 250); word-wrap:=
break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><di=
v class=3D"prettyprint" style=3D"border-width: 1px; border-style: solid; bo=
rder-color: rgb(187, 187, 187); font-family: Arial, Helvetica, sans-serif; =
word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><div class=3D"subprettyprint"><div class=3D"subprettyprint"><span st=
yle=3D"color: rgb(0, 0, 0); font-family: Arial, Helvetica, sans-serif;">// =
Support code for the example at the beginning of the message:<br><br>// Def=
aults to something that isn't an enum.</span><br></div><div class=3D"su=
bprettyprint"><font color=3D"#000000"><div class=3D"subprettyprint">templat=
e <typename Enum, typename T, typename =3D std::enable_if_t<std::is_e=
num<Enum>::value>></div><div class=3D"subprettyprint">struct co=
nverted_to_enum {};</div><div class=3D"subprettyprint"><br></div><div class=
=3D"subprettyprint">template <typename T></div><div class=3D"subprett=
yprint">class TypeEnumHelper {</div><div class=3D"subprettyprint">=C2=A0pub=
lic:</div><div class=3D"subprettyprint">=C2=A0 template <typename Enum, =
Enum =3D converted_to_enum<Enum, T>::value></div><div class=3D"sub=
prettyprint">=C2=A0 constexpr operator Enum() const {</div><div class=3D"su=
bprettyprint">=C2=A0 =C2=A0 return converted_to_enum<Enum, T>::value;=
</div><div class=3D"subprettyprint">=C2=A0 }</div><div class=3D"subprettypr=
int">};</div><div class=3D"subprettyprint"><br></div><div class=3D"subprett=
yprint">template <typename T></div><div class=3D"subprettyprint">cons=
texpr TypeEnumHelper<T> type_enum =3D TypeEnumHelper<T>();</div=
><div class=3D"subprettyprint"><br><div class=3D"subprettyprint">#define AS=
SIGN_ENUM_TAG(UnionEnumType, Class, EnumTag) \</div><div class=3D"subpretty=
print">template<> =C2=A0\</div><div class=3D"subprettyprint">struct c=
onverted_to_enum<UnionEnumType, Class> { \</div><div class=3D"subpret=
typrint">=C2=A0 static constexpr UnionEnumType value =3D UnionEnumType:: En=
umTag; \</div><div class=3D"subprettyprint">};</div></div></font></div></di=
v></div></code></div><span style=3D"font-family: Arial, Helvetica, sans-ser=
if; background-color: rgb(255, 255, 255);"></span></div></code></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/e0683c7a-3db4-4ee6-b10b-649d13c94cd5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e0683c7a-3db4-4ee6-b10b-649d13c94cd5=
%40isocpp.org</a>.<br />
------=_Part_10904_784088170.1509551957293--
------=_Part_10903_1031879791.1509551957293--
.
Author: Barry Revzin <barry.revzin@gmail.com>
Date: Wed, 1 Nov 2017 09:37:42 -0700 (PDT)
Raw View
------=_Part_11515_560473485.1509554262996
Content-Type: multipart/alternative;
boundary="----=_Part_11516_1093647123.1509554262996"
------=_Part_11516_1093647123.1509554262996
Content-Type: text/plain; charset="UTF-8"
You're looking for a language feature called pattern matching.
An earlier proposal can be found
here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0095r1.html
My understanding is that David Sankel is working with Michael Park (who
wrote a pattern matching library: http://github.com/mpark/patterns) on a
new draft.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/388ea94a-6cff-411a-abf4-e8782d207a02%40isocpp.org.
------=_Part_11516_1093647123.1509554262996
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">You're looking for a language feature called pattern m=
atching.<div><br></div><div>An earlier proposal can be found here:=C2=A0htt=
p://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0095r1.html</div><div=
>My understanding is that David Sankel is working with Michael Park (who wr=
ote a pattern matching library: http://github.com/mpark/patterns) on a new =
draft.=C2=A0</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/388ea94a-6cff-411a-abf4-e8782d207a02%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/388ea94a-6cff-411a-abf4-e8782d207a02=
%40isocpp.org</a>.<br />
------=_Part_11516_1093647123.1509554262996--
------=_Part_11515_560473485.1509554262996--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 1 Nov 2017 18:46:53 +0200
Raw View
On 1 November 2017 at 18:37, Barry Revzin <barry.revzin@gmail.com> wrote:
> You're looking for a language feature called pattern matching.
Correct. Leave switch alone.
> An earlier proposal can be found here:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0095r1.html
> My understanding is that David Sankel is working with Michael Park (who
> wrote a pattern matching library: http://github.com/mpark/patterns) on a new
> draft.
The Evolution Working Group viewed the general idea of pattern
matching favorably, although we don't
know yet when it will be ready.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/CAFk2RUbVgsbTxCahoKLkQVNKGJkiJEC3QS9ugTDVEzY6r6%3D3fw%40mail.gmail.com.
.