Topic: Core Language featuConstructors for (scoped) enums


Author: Manuel Bergler <berglerma@gmail.com>
Date: Wed, 5 Oct 2016 06:36:44 -0700 (PDT)
Raw View
------=_Part_484_1567377640.1475674604139
Content-Type: multipart/alternative;
 boundary="----=_Part_485_1033971777.1475674604139"

------=_Part_485_1033971777.1475674604139
Content-Type: text/plain; charset=UTF-8



Most of the time I use enums not as a "strong typedef" for integral types,
but rather as a means to choose between a fixed number of alternatives.
One example is the one in [dcl.enum]/10:
    enum class Col { red, yellow, green };

A common problem now arises if the color is e.g. selected by a user or
retrieved from persistent storage, i.e. when there is the need for a
conversion from an integral type to the enum and one needs to validate
the input.

For enums with fixed underlying type one technically can safely use a
static_cast from the underlying type, but then the value is potentially
one not defined by any of the enumerators. While on the surface this
seems to really only apply to user input and not to persistent data, it
can be a problem when removing old options so that suddenly some
values in the persistent store are no longer enumerators in the enum, but
still can be safely cast to the enum type. So in practice you end up
having to keep the old enumerators and have to set the sensible defaults
everywhere you switch based on the enum value, or you have to resort to
variant 2:

So an other alternative is to explicitly `switch` on the integral value:

    switch (int i) {
    case static_cast<int>(Col::red):
        return Col::red;
    case static_cast<int>(Col::yellow):
        return Col::yellow;
    case static_cast<int>(Col::green):
        return Col::yellow;
    default:
        // return a sensible default/throw an exception
    }

This approach also has two major drawbacks:
    - Most likely this `switch` is going to be encapsulated in a `to_Col`
      function, but as naming conventions differ from library to library
      the user most likely has to look it up (or is too lazy and ends up
      just using `static_cast`)
    - If one later adds another enumerator, the code will compile just fine,
      and all compilers I've tested do not emit a warning either, as they
      can't infer the intend and only see a switch over integers. This means
      it is easy to end up with an enumerator that can never be retrieved
      after it has been persisted.

And finally one can wrap the enum values in a seperate class/struct which has a
constructor that encapsulates the switch described in the alternative above.
In most cases the enum will then be defined as a nested enum inside the class.
This means one can no longer forward declare it. Additionally it discourages the
use of scoped enums inside the class, as noone wants to write `Col::Col::red`
(assuming `Color` is also the name for the wrapping class/struct), so suddenly
the enumerator happily promotes to `int` again. Moreover, since this cannot be
generalized with templates one has to write the same boilerplate code over and
over again.

So the solution that came to my mind is to allow the definition of constructors
for enums. Then one can put the switch above into the constructor and compiler
writers are possibly able to detect missing enumerators due to the added context.
Additionally it makes the language more consistent, as every user defined type
then could have constructors (one can already define a constructor for structs,
classes and even unions). It immediately solves the naming problem present in
alternative 2 above, and as far as I can tell does not have any impact on ADL/
existing code without constructors defined for their enum.

The syntax could look something like this:
    enum class Color {
       red,
       yellow,
       green;

       Color(int i);
    }

    Color::Color(int i) {
        switch (int i) {
        case static_cast<int>(Col::red):
            *this = Col::red;
        case static_cast<int>(Col::yellow):
            *this = Col::yellow;
        case static_cast<int>(Col::green):
            *this = Col::yellow;
        default:
            // set a sensible default/throw an exception
        }
    }

Note that the semicolon after the last enumerator as well as the constructor
declaration are supposed to be optional as to not break existing code.

What do you think? Has there been a similar proposal before, and if so, for what
reasons has it been rejected?

Best
Manuel

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/0a4195d5-9b4d-4f9a-82b1-36841807af27%40isocpp.org.

------=_Part_485_1033971777.1475674604139
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><pre>Most of the time I use enums not as a &quot;strong ty=
pedef&quot; for integral types,
but rather as a means to choose between a fixed number of alternatives.
One example is the one in [dcl.enum]/10:
    enum class Col { red, yellow, green };

A common problem now arises if the color is e.g. selected by a user or
retrieved from persistent storage, i.e. when there is the need for a <br>co=
nversion from an integral type to the enum and one needs to validate<br>the=
 input.

For enums with fixed underlying type one technically can safely use a
static_cast from the underlying type, but then the value is potentially<br>=
one not defined by any of the enumerators. While on the surface this<br>see=
ms to really only apply to user input and not to persistent data, it<br>can=
 be a problem when removing old options so that suddenly some<br>values in =
the persistent store are no longer enumerators in the enum, but<br>still ca=
n be safely cast to the enum type. So in practice you end up<br>having to k=
eep the old enumerators and have to set the sensible defaults<br>everywhere=
 you switch based on the enum value, or you have to resort to<br>variant 2:=
<br><br>So an other alternative is to explicitly `switch` on the integral v=
alue:

    switch (int i) {
    case static_cast&lt;int&gt;(Col::red):
        return Col::red;
    case static_cast&lt;int&gt;(Col::yellow):
        return Col::yellow;
    case static_cast&lt;int&gt;(Col::green):
        return Col::yellow;
    default:
        // return a sensible default/throw an exception
    }

This approach also has two major drawbacks:
    - Most likely this `switch` is going to be encapsulated in a `to_Col`<b=
r>     =C2=A0function, but as naming conventions differ from library to lib=
rary<br>      the user most likely has to look it up (or is too lazy and en=
ds up<br>      just using `static_cast`)
    - If one later adds another enumerator, the code will compile just fine=
,
      and all compilers I&#39;ve tested do not emit a warning either, as th=
ey
      can&#39;t infer the intend and only see a switch over integers. This =
means<br>      it is easy to end up with an enumerator that can never be re=
trieved<br>      after it has been persisted.<br><br>And finally one can wr=
ap the enum values in a seperate class/struct which has a<br>constructor th=
at encapsulates the switch described in the alternative above.<br>In most c=
ases the enum will then be defined as a nested enum inside the class.<br>Th=
is means one can no longer forward declare it. Additionally it discourages =
the<br>use of scoped enums inside the class, as noone wants to write `Col::=
Col::red`<br>(assuming `Color` is also the name for the wrapping class/stru=
ct), so suddenly<br>the enumerator happily promotes to `int` again. Moreove=
r, since this cannot be <br>generalized with templates one has to write the=
 same boilerplate code over and<br>over again.<br><br>So the solution that =
came to my mind is to allow the definition of constructors
for enums. Then one can put the switch above into the constructor and compi=
ler
writers are possibly able to detect missing enumerators due to the added co=
ntext.
Additionally it makes the language more consistent, as every user defined t=
ype
then could have constructors (one can already define a constructor for stru=
cts,
classes and even unions). It immediately solves the naming problem present =
in<br>alternative 2 above, and as far as I can tell does not have any impac=
t on ADL/<br>existing code without constructors defined for their enum.<br>=
<br>The syntax could look something like this:<br>    enum class Color {<br=
>       red,<br>       yellow,<br>       green;<br>  <br>       Color(int i=
);<br>    }<br><br>    Color::Color(int i) { <br>        switch (int i) {
        case static_cast&lt;int&gt;(Col::red):
            *this =3D Col::red;
        case static_cast&lt;int&gt;(Col::yellow):
            *this =3D Col::yellow;
        case static_cast&lt;int&gt;(Col::green):
            *this =3D Col::yellow;
        default:
            // set a sensible default/throw an exception
        }<br>    }   <br><br>Note that the semicolon after the last enumera=
tor as well as the constructor <br>declaration are supposed to be optional =
as to not break existing code. <br><br>What do you think? Has there been a =
similar proposal before, and if so, for what<br>reasons has it been rejecte=
d?<br><br>Best<br>Manuel<br></pre></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/0a4195d5-9b4d-4f9a-82b1-36841807af27%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0a4195d5-9b4d-4f9a-82b1-36841807af27=
%40isocpp.org</a>.<br />

------=_Part_485_1033971777.1475674604139--

------=_Part_484_1567377640.1475674604139--

.


Author: mihailnajdenov@gmail.com
Date: Wed, 5 Oct 2016 07:48:23 -0700 (PDT)
Raw View
------=_Part_3131_938996111.1475678904067
Content-Type: multipart/alternative;
 boundary="----=_Part_3132_221996440.1475678904067"

------=_Part_3132_221996440.1475678904067
Content-Type: text/plain; charset=UTF-8

I am not sure about an official proposal, but yes, something similar was
suggested before, I have seen it on the web.

I personally also think, enum needs some more love or introduction of a c++
alternative (like variant as an alternative to union).
For instance there should be safe and easy way to use them as flags, =
default operators and what not.
Methods are also sometimes needed, both static and instance, though this is
doable as wrapper class of course, or free-standing functions of some
namespace.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/3b3a73e9-f603-4b37-9f3a-4028be9b6a8a%40isocpp.org.

------=_Part_3132_221996440.1475678904067
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I am not sure about an official proposal, but yes, somethi=
ng similar was suggested before, I have seen it on the web.<div><br></div><=
div>I personally also think, enum needs some more love or introduction of a=
 c++ alternative (like variant as an alternative to union).=C2=A0</div><div=
>For instance there should be safe and easy way to use them as flags, =3D d=
efault operators and what not.</div><div>Methods are also sometimes needed,=
 both static and instance, though this is doable as wrapper class of course=
, or free-standing functions of some namespace.</div><div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/3b3a73e9-f603-4b37-9f3a-4028be9b6a8a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3b3a73e9-f603-4b37-9f3a-4028be9b6a8a=
%40isocpp.org</a>.<br />

------=_Part_3132_221996440.1475678904067--

------=_Part_3131_938996111.1475678904067--

.


Author: Manuel Bergler <berglerma@gmail.com>
Date: Wed, 5 Oct 2016 08:20:23 -0700 (PDT)
Raw View
------=_Part_107_831168724.1475680823517
Content-Type: multipart/alternative;
 boundary="----=_Part_108_950137090.1475680823517"

------=_Part_108_950137090.1475680823517
Content-Type: text/plain; charset=UTF-8

Am Mittwoch, 5. Oktober 2016 16:48:24 UTC+2 schrieb mihailn...@gmail.com:
>
> I am not sure about an official proposal, but yes, something similar was
> suggested before, I have seen it on the web.
>
> I personally also think, enum needs some more love or introduction of a
> c++ alternative (like variant as an alternative to union).
> For instance there should be safe and easy way to use them as flags, =
> default operators and what not.
> Methods are also sometimes needed, both static and instance, though this
> is doable as wrapper class of course, or free-standing functions of some
> namespace.
>
>
For flags there already is `std::bitset` which one can use with enumerators
of some enum as indices into the bitset, so there is no need for
`operator|` and `operator&`
for any enum by default (it would probably make things worse for enums
which were never designed to be used this way). I'd even go so far to
outright consider it bad
practice in C++ to use enums as flags, so in my opinion it is rightfully
inconvenient. I also don't see the need for member functions, even more so
seeing we might get
unified function call syntax in the future. The only thing that really
bothers me is that there is no good way to safely convert from an integral
type to an enum.
So yes, I'd be happy if there were an library based solution to this
problem similar to std::optional or std::variant, but that requires
introspection capabilities for enums
which seem like a more difficult (but also considerably more powerful)
language extension than just adding constructors to enums.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/389af479-800f-46de-b9f7-ba5206c5cff5%40isocpp.org.

------=_Part_108_950137090.1475680823517
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Am Mittwoch, 5. Oktober 2016 16:48:24 UTC+2 schrieb mihail=
n...@gmail.com:<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=
">I am not sure about an official proposal, but yes, something similar was =
suggested before, I have seen it on the web.<div><br></div><div>I personall=
y also think, enum needs some more love or introduction of a c++ alternativ=
e (like variant as an alternative to union).=C2=A0</div><div>For instance t=
here should be safe and easy way to use them as flags, =3D default operator=
s and what not.</div><div>Methods are also sometimes needed, both static an=
d instance, though this is doable as wrapper class of course, or free-stand=
ing functions of some namespace.</div><div><br></div></div></blockquote><di=
v><br>For flags there already is `std::bitset` which one can use with enume=
rators of some enum as indices into the bitset, so there is no need for `op=
erator|` and `operator&amp;`<br>for any enum by default (it would probably =
make things worse for enums which were never designed to be used this way).=
 I&#39;d even go so far to outright consider it bad<br>practice in C++ to u=
se enums as flags, so in my opinion it is rightfully inconvenient. I also d=
on&#39;t see the need for member functions, even more so seeing we might ge=
t <br>unified function call syntax in the future. The only thing that reall=
y bothers me is that there is no good way to safely convert from an integra=
l type to an enum.<br>So yes, I&#39;d be happy if there were an library bas=
ed solution to this problem similar to std::optional or std::variant, but t=
hat requires introspection capabilities for enums <br>which seem like a mor=
e difficult (but also considerably more powerful) language extension than j=
ust adding constructors to enums.<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/389af479-800f-46de-b9f7-ba5206c5cff5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/389af479-800f-46de-b9f7-ba5206c5cff5=
%40isocpp.org</a>.<br />

------=_Part_108_950137090.1475680823517--

------=_Part_107_831168724.1475680823517--

.


Author: Victor Dyachenko <victor.dyachenko@gmail.com>
Date: Thu, 6 Oct 2016 00:04:23 -0700 (PDT)
Raw View
------=_Part_75_1964598980.1475737463607
Content-Type: multipart/alternative;
 boundary="----=_Part_76_1820484173.1475737463607"

------=_Part_76_1820484173.1475737463607
Content-Type: text/plain; charset=UTF-8

On Wednesday, October 5, 2016 at 4:36:44 PM UTC+3, Manuel Bergler wrote:
>
> And finally one can wrap the enum values in a seperate class/struct which has a
> constructor that encapsulates the switch described in the alternative above.
> In most cases the enum will then be defined as a nested enum inside the class.
> This means one can no longer forward declare it. Additionally it discourages the
> use of scoped enums inside the class, as noone wants to write `Col::Col::red`
>
> Totally agree! It would be nice to have something like this:

struct color
{
    enum class values
    {
        red,
        ...
    };
    using values::*;
};
auto c = color::red;


>     enum class Color {
>        red,
>        yellow,
>        green;
>
>        Color(int i);
>     }
>
>     Color::Color(int i) {
>         switch (int i) {
>         case static_cast<int>(Col::red):
>             *this = Col::red;
>         case static_cast<int>(Col::yellow):
>             *this = Col::yellow;
>         case static_cast<int>(Col::green):
>             *this = Col::yellow;
>         default:
>             // set a sensible default/throw an exception
>         }
>     }
>
> How it better than


    Color toColor(int i) {
        switch (int i) {
        case static_cast<int>(Col::red):
            return Col::red;
        case static_cast<int>(Col::yellow):
            return Col::yellow;
        case static_cast<int>(Col::green):
            return Col::yellow;
        default:
            // set a sensible default/throw an exception
        }
    }

?

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9b9b3213-effd-454b-8f49-9e5f11fee378%40isocpp.org.

------=_Part_76_1820484173.1475737463607
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, October 5, 2016 at 4:36:44 PM UTC+3, Manuel =
Bergler wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><pre>And finally one can wrap the enum values in a seperate class/struct w=
hich has a<br>constructor that encapsulates the switch described in the alt=
ernative above.<br>In most cases the enum will then be defined as a nested =
enum inside the class.<br>This means one can no longer forward declare it. =
Additionally it discourages the<br>use of scoped enums inside the class, as=
 noone wants to write `Col::Col::red`<br></pre></div></blockquote><div>Tota=
lly agree! It would be nice to have something like this:<br><span style=3D"=
font-family: courier new,monospace;"><br>struct color<br>{<br>=C2=A0=C2=A0=
=C2=A0 enum class values<br>=C2=A0=C2=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 red,<br>=C2=A0=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 using values::*;<br>};<br>=
auto c =3D color::red;<br></span>=C2=A0</div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><pre>    enum class Color {<br>       red,<=
br>       yellow,<br>       green;<br>  <br>       Color(int i);<br>    }<b=
r><br>    Color::Color(int i) { <br>        switch (int i) {
        case static_cast&lt;int&gt;(Col::red):
            *this =3D Col::red;
        case static_cast&lt;int&gt;(Col::yellow):
            *this =3D Col::yellow;
        case static_cast&lt;int&gt;(Col::green):
            *this =3D Col::yellow;
        default:
            // set a sensible default/throw an exception
        }<br>    }<br></pre></div></blockquote><div>How it better than <br>=
<pre><br>    Color toColor(int i) { <br>        switch (int i) {
        case static_cast&lt;int&gt;(Col::red):
            return Col::red;
        case static_cast&lt;int&gt;(Col::yellow):
            return Col::yellow;
        case static_cast&lt;int&gt;(Col::green):
            return Col::yellow;
        default:
            // set a sensible default/throw an exception
        }<br>    }<br></pre>?<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/9b9b3213-effd-454b-8f49-9e5f11fee378%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9b9b3213-effd-454b-8f49-9e5f11fee378=
%40isocpp.org</a>.<br />

------=_Part_76_1820484173.1475737463607--

------=_Part_75_1964598980.1475737463607--

.


Author: mihailnajdenov@gmail.com
Date: Thu, 6 Oct 2016 00:11:23 -0700 (PDT)
Raw View
------=_Part_16_107836314.1475737883586
Content-Type: multipart/alternative;
 boundary="----=_Part_17_16433497.1475737883586"

------=_Part_17_16433497.1475737883586
Content-Type: text/plain; charset=UTF-8

bitset does not support named flags and I doubt it is designed to be used
to store non-mutually exclusive options. It is a container for bits. It has
its uses.
As for mixing and enum + bitset - this is even more clunky then a struct
wrapper or macro do define the operators (Qt way).

For such a simple idea there should be a simple tool.

It should be noted std itself also does not have or use an elegant solution
for named combinable options - it uses free standing values
(std::regex_constants::syntax_option_type)
This is not any better then C.

Lastly, C++ aims to improve established practices - enums as flags are used
for decades and there is not a clearly better alternative.
Either there should be a better alternative (new type) or improve the
existing ones

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/d99dbe8f-29ef-40d2-928d-f13475ed15a2%40isocpp.org.

------=_Part_17_16433497.1475737883586
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">bitset does not support named flags and I doubt it is desi=
gned to be used to store non-mutually exclusive options. It is a container =
for bits. It has its uses.=C2=A0<div>As for mixing and enum + bitset - this=
 is even more clunky then a struct wrapper or macro do define the operators=
 (Qt way).=C2=A0</div><div><br></div><div>For such a simple idea there shou=
ld be a simple tool.<br><div><br></div><div>It should be noted std itself a=
lso does not have or use an elegant solution for named combinable options -=
 it uses free standing values (std::regex_constants::syntax_option_type)</d=
iv></div><div>This is not any better then C.</div><div><br></div><div>Lastl=
y, C++ aims to improve established practices - enums as flags are used for =
decades and there is not a clearly better alternative.</div><div>Either the=
re should be a better alternative (new type) or improve the existing ones</=
div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/d99dbe8f-29ef-40d2-928d-f13475ed15a2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d99dbe8f-29ef-40d2-928d-f13475ed15a2=
%40isocpp.org</a>.<br />

------=_Part_17_16433497.1475737883586--

------=_Part_16_107836314.1475737883586--

.


Author: Manuel Bergler <berglerma@gmail.com>
Date: Thu, 6 Oct 2016 00:23:49 -0700 (PDT)
Raw View
------=_Part_230_36627476.1475738629672
Content-Type: multipart/alternative;
 boundary="----=_Part_231_889642534.1475738629672"

------=_Part_231_889642534.1475738629672
Content-Type: text/plain; charset=UTF-8

Am Donnerstag, 6. Oktober 2016 09:11:23 UTC+2 schrieb mihailn...@gmail.com:
>
> bitset does not support named flags and I doubt it is designed to be used
> to store non-mutually exclusive options. It is a container for bits. It has
> its uses.
> As for mixing and enum + bitset - this is even more clunky then a struct
> wrapper or macro do define the operators (Qt way).
>
>
For mutually exclusive flags I agree, enums are the way to go. But as I
understood it he wanted `operator|` and `operator&` so that you can use
enums as
non-exclusive flags. And this you can easily get with `std::bitset` and and
enum as an index into the bitset:

enum class Features : size_t {
    ColoredText,
    ColoredBorder,
    Scrollbar
}

std::bitset<3> features;
features.set(Feature::ColoredText);
features.set(Feature::Scrollbar);



For such a simple idea there should be a simple tool.
>
> It should be noted std itself also does not have or use an elegant
> solution for named combinable options - it uses free standing values
> (std::regex_constants::syntax_option_type)
> This is not any better then C.
>
> Lastly, C++ aims to improve established practices - enums as flags are
> used for decades and there is not a clearly better alternative.
> Either there should be a better alternative (new type) or improve the
> existing ones
>


 I believe the code above *is* a better alternative for the C style version
using plain enums:
enum Feature : uint_16 {
  ColoredText = 0x1,
  ColoredBorder = 0x2,
  Scrollbar = 0x4
}

auto feature = ColoredText | Scrollbar; // Bitwise OR in order to mean
ColoredText AND Scrollbar ?!


--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/720bc6a2-cf42-476c-b762-cdc57863fa1c%40isocpp.org.

------=_Part_231_889642534.1475738629672
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Am Donnerstag, 6. Oktober 2016 09:11:23 UTC+2 schrieb miha=
iln...@gmail.com:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">bitset does not support named flags and I doubt it is designed to be us=
ed to store non-mutually exclusive options. It is a container for bits. It =
has its uses.=C2=A0<div>As for mixing and enum + bitset - this is even more=
 clunky then a struct wrapper or macro do define the operators (Qt way).=C2=
=A0</div><div><br></div></div></blockquote><div><br>For mutually exclusive =
flags I agree, enums are the way to go. But as I understood it he wanted `o=
perator|` and `operator&amp;` so that you can use enums as <br>non-exclusiv=
e flags. And this you can easily get with `std::bitset` and and enum as an =
index into the bitset:<br><br><div style=3D"background-color: rgb(250, 250,=
 250); border-color: rgb(187, 187, 187); border-style: solid; border-width:=
 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"pret=
typrint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">enum</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Featu=
res</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> size_t </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">ColoredText</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">ColoredBorder</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">Scrollbar</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br><br>std</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">bitset</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&lt;</span><span style=3D"color: #066;" class=3D"st=
yled-by-prettify">3</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> features</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>fea=
tures</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">set</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Feature</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: =
#606;" class=3D"styled-by-prettify">ColoredText</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>features</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">set</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-pr=
ettify">Feature</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">::</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Scr=
ollbar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</=
span></div></code></div><br><br><br></div><blockquote class=3D"gmail_quote"=
 style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-=
left: 1ex;"><div dir=3D"ltr"><div></div><div>For such a simple idea there s=
hould be a simple tool.<br><div><br></div><div>It should be noted std itsel=
f also does not have or use an elegant solution for named combinable option=
s - it uses free standing values (std::regex_constants::syntax_<wbr>option_=
type)</div></div><div>This is not any better then C.</div><div><br></div></=
div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div></div><div>Lastly, C++ aims to improve established practices - enu=
ms as flags are used for decades and there is not a clearly better alternat=
ive.</div><div>Either there should be a better alternative (new type) or im=
prove the existing ones</div></div></blockquote><div><br><br>=C2=A0I believ=
e the code above <i>is</i> a better alternative for the C style version usi=
ng plain enums:<br><div style=3D"background-color: rgb(250, 250, 250); bord=
er-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; overf=
low-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by=
-prettify">enum</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Feat=
ure</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> uint_16 </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">ColoredText</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"sty=
led-by-prettify">0x1</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">ColoredBorder</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #066;" class=3D"styled-by-prettify">0x2</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"col=
or: #606;" class=3D"styled-by-prettify">Scrollbar</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">0x4</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br=
></span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> feature </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #606;" class=3D"styled-by-prettify">ColoredText</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">|</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"sty=
led-by-prettify">Scrollbar</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
 Bitwise OR in order to mean ColoredText AND Scrollbar ?!</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></di=
v><br><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/720bc6a2-cf42-476c-b762-cdc57863fa1c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/720bc6a2-cf42-476c-b762-cdc57863fa1c=
%40isocpp.org</a>.<br />

------=_Part_231_889642534.1475738629672--

------=_Part_230_36627476.1475738629672--

.


Author: Manuel Bergler <berglerma@gmail.com>
Date: Thu, 6 Oct 2016 00:40:01 -0700 (PDT)
Raw View
------=_Part_235_279556747.1475739602053
Content-Type: multipart/alternative;
 boundary="----=_Part_236_300742798.1475739602053"

------=_Part_236_300742798.1475739602053
Content-Type: text/plain; charset=UTF-8



Am Donnerstag, 6. Oktober 2016 09:04:23 UTC+2 schrieb Victor Dyachenko:
>
>     enum class Color {
>>        red,
>>        yellow,
>>        green;
>>
>>        Color(int i);
>>     }
>>
>>     Color::Color(int i) {
>>         switch (int i) {
>>         case static_cast<int>(Col::red):
>>             *this = Col::red;
>>         case static_cast<int>(Col::yellow):
>>             *this = Col::yellow;
>>         case static_cast<int>(Col::green):
>>             *this = Col::yellow;
>>         default:
>>             // set a sensible default/throw an exception
>>         }
>>     }
>>
>> How it better than
>
>
>     Color toColor(int i) {
>         switch (int i) {
>         case static_cast<int>(Col::red):
>             return Col::red;
>         case static_cast<int>(Col::yellow):
>             return Col::yellow;
>         case static_cast<int>(Col::green):
>             return Col::yellow;
>         default:
>             // set a sensible default/throw an exception
>         }
>     }
>
> ?
>

As I have written before, I believe compiler vendors could more easily
implement check that every enumerator can be constructed (in regular
switches over some integral value how is the compiler supposed to know what
you intended, in the constructor the intend of such a switch is clear). So
I hope to get a warning when I add a new enumerator and forget to add it in
the constructor.
Additionally,  the naming is consistent across different libraries, so you
can just write

    auto color =  Col{setting.color()}; // assuming settings are read from
some config file;

instead of having to look up the name of the conversion function (was it
camelCase, snake_case, in which namespace is the function) and then ending
up with

    auto Color = to_color(settings.color());

And personally I'm not really a fan of wrapping enum values inside a
struct/class, as it moves the boilerplate to where you interface with APIs
that expect the plain enum value and not the struct.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/28d6848d-6d00-4fca-8879-c8e1870d2f8e%40isocpp.org.

------=_Part_236_300742798.1475739602053
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>Am Donnerstag, 6. Oktober 2016 09:04:23 UTC+2 schr=
ieb Victor Dyachenko:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><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"><pre>    =
enum class Color {<br>       red,<br>       yellow,<br>       green;<br>  <=
br>       Color(int i);<br>    }<br><br>    Color::Color(int i) { <br>     =
   switch (int i) {
        case static_cast&lt;int&gt;(Col::red):
            *this =3D Col::red;
        case static_cast&lt;int&gt;(Col::yellow):
            *this =3D Col::yellow;
        case static_cast&lt;int&gt;(Col::green):
            *this =3D Col::yellow;
        default:
            // set a sensible default/throw an exception
        }<br>    }<br></pre></div></blockquote><div>How it better than <br>=
<pre><br>    Color toColor(int i) { <br>        switch (int i) {
        case static_cast&lt;int&gt;(Col::red):
            return Col::red;
        case static_cast&lt;int&gt;(Col::yellow):
            return Col::yellow;
        case static_cast&lt;int&gt;(Col::green):
            return Col::yellow;
        default:
            // set a sensible default/throw an exception
        }<br>    }<br></pre>?<br></div></div></blockquote><div>=C2=A0<br>As=
 I have written before, I believe compiler vendors could more easily implem=
ent check that every enumerator can be constructed (in regular switches ove=
r some integral value how is the compiler supposed to know what you intende=
d, in the constructor the intend of such a switch is clear). So I hope to g=
et a warning when I add a new enumerator and forget to add it in the constr=
uctor.<br>Additionally,=C2=A0 the naming is consistent across different lib=
raries, so you can just write<br><br>=C2=A0=C2=A0=C2=A0 auto color =3D=C2=
=A0 Col{setting.color()}; // assuming settings are read from some config fi=
le;<br><br>instead of having to look up the name of the conversion function=
 (was it camelCase, snake_case, in which namespace is the function) and the=
n ending up with<br><br>=C2=A0=C2=A0=C2=A0 auto Color =3D to_color(settings=
..color());<br><br>And personally I&#39;m not really a fan of wrapping enum =
values inside a struct/class, as it moves the boilerplate to where you inte=
rface with APIs that expect the plain enum value and not the struct.<br></d=
iv></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/28d6848d-6d00-4fca-8879-c8e1870d2f8e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/28d6848d-6d00-4fca-8879-c8e1870d2f8e=
%40isocpp.org</a>.<br />

------=_Part_236_300742798.1475739602053--

------=_Part_235_279556747.1475739602053--

.


Author: Ivan Kushnarenko <ivan.kushnar@gmail.com>
Date: Thu, 6 Oct 2016 08:12:12 -0700 (PDT)
Raw View
------=_Part_602_546652282.1475766732648
Content-Type: multipart/alternative;
 boundary="----=_Part_603_730633179.1475766732649"

------=_Part_603_730633179.1475766732649
Content-Type: text/plain; charset=UTF-8

tell the truth, i'm not familiar with compiler internals and how scoped
enums are realized,
but maybe it's possible to add the `final`  keyword to scoped enum, which
will mean that we can't cast integer to this enum if, integer value don't
coincide with underlying values of enum internal data
enum class FooEnum *final*
{
};

For example

enum class FooEnum : int {
    red = 0,
    green = 5
};

int j = 5;
FooEnum enum = static_cast<FooEnum>(j);//OK
int i = 6;
FooEnum enum = static_cast<FooEnum>(i);//throw exception



On Wednesday, October 5, 2016 at 4:36:44 PM UTC+3, Manuel Bergler wrote:
>
> Most of the time I use enums not as a "strong typedef" for integral types,
> but rather as a means to choose between a fixed number of alternatives.
> One example is the one in [dcl.enum]/10:
>     enum class Col { red, yellow, green };
>
> A common problem now arises if the color is e.g. selected by a user or
> retrieved from persistent storage, i.e. when there is the need for a
> conversion from an integral type to the enum and one needs to validate
> the input.
>
> For enums with fixed underlying type one technically can safely use a
> static_cast from the underlying type, but then the value is potentially
> one not defined by any of the enumerators. While on the surface this
> seems to really only apply to user input and not to persistent data, it
> can be a problem when removing old options so that suddenly some
> values in the persistent store are no longer enumerators in the enum, but
> still can be safely cast to the enum type. So in practice you end up
> having to keep the old enumerators and have to set the sensible defaults
> everywhere you switch based on the enum value, or you have to resort to
> variant 2:
>
> So an other alternative is to explicitly `switch` on the integral value:
>
>     switch (int i) {
>     case static_cast<int>(Col::red):
>         return Col::red;
>     case static_cast<int>(Col::yellow):
>         return Col::yellow;
>     case static_cast<int>(Col::green):
>         return Col::yellow;
>     default:
>         // return a sensible default/throw an exception
>     }
>
> This approach also has two major drawbacks:
>     - Most likely this `switch` is going to be encapsulated in a `to_Col`
>       function, but as naming conventions differ from library to library
>       the user most likely has to look it up (or is too lazy and ends up
>       just using `static_cast`)
>     - If one later adds another enumerator, the code will compile just fine,
>       and all compilers I've tested do not emit a warning either, as they
>       can't infer the intend and only see a switch over integers. This means
>       it is easy to end up with an enumerator that can never be retrieved
>       after it has been persisted.
>
> And finally one can wrap the enum values in a seperate class/struct which has a
> constructor that encapsulates the switch described in the alternative above.
> In most cases the enum will then be defined as a nested enum inside the class.
> This means one can no longer forward declare it. Additionally it discourages the
> use of scoped enums inside the class, as noone wants to write `Col::Col::red`
> (assuming `Color` is also the name for the wrapping class/struct), so suddenly
> the enumerator happily promotes to `int` again. Moreover, since this cannot be
> generalized with templates one has to write the same boilerplate code over and
> over again.
>
> So the solution that came to my mind is to allow the definition of constructors
> for enums. Then one can put the switch above into the constructor and compiler
> writers are possibly able to detect missing enumerators due to the added context.
> Additionally it makes the language more consistent, as every user defined type
> then could have constructors (one can already define a constructor for structs,
> classes and even unions). It immediately solves the naming problem present in
> alternative 2 above, and as far as I can tell does not have any impact on ADL/
> existing code without constructors defined for their enum.
>
> The syntax could look something like this:
>     enum class Color {
>        red,
>        yellow,
>        green;
>
>        Color(int i);
>     }
>
>     Color::Color(int i) {
>         switch (int i) {
>         case static_cast<int>(Col::red):
>             *this = Col::red;
>         case static_cast<int>(Col::yellow):
>             *this = Col::yellow;
>         case static_cast<int>(Col::green):
>             *this = Col::yellow;
>         default:
>             // set a sensible default/throw an exception
>         }
>     }
>
> Note that the semicolon after the last enumerator as well as the constructor
> declaration are supposed to be optional as to not break existing code.
>
> What do you think? Has there been a similar proposal before, and if so, for what
> reasons has it been rejected?
>
> Best
> Manuel
>
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/0dbc34ce-e6f8-4cb5-bfe5-b77308382ed6%40isocpp.org.

------=_Part_603_730633179.1475766732649
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">tell the truth, i&#39;m not familiar with compiler interna=
ls and how scoped enums are realized,<div>but maybe it&#39;s possible to ad=
d the `final` =C2=A0keyword to scoped enum, which will mean that we can&#39=
;t cast integer to this enum if, integer value don&#39;t coincide with unde=
rlying values of enum internal data</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"subp=
rettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">enum<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">FooEnum</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><b><span style=3D"color: #008=
;" class=3D"styled-by-prettify">final</span></b><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">};</span></div></code></div><div><br></div><div>For example</div>=
<div><br><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 style=3D"color: =
#008;" class=3D"styled-by-prettify">enum</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pre=
ttify">FooEnum</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 red </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" clas=
s=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 green </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prett=
ify">5</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> j </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" clas=
s=3D"styled-by-prettify">5</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>FooEnum</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">enum</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">static_cast</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">FooEnum</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&gt;(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">j</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">)</span><font color=3D"#880000"><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">//OK</span></font><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> i </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #066;" class=3D"styled-by-prettify">6</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #=
606;" class=3D"styled-by-prettify">FooEnum</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">enum</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">static_=
cast</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">FooEnum</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">i</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span><font color=3D"#8800=
00"><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #800;" class=3D"styled-by-prettify">//throw exception</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span>=
</font></div></code></div><br><br>On Wednesday, October 5, 2016 at 4:36:44 =
PM UTC+3, Manuel Bergler wrote:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><pre>Most of the time I use enums not as a &quot;strong t=
ypedef&quot; for integral types,
but rather as a means to choose between a fixed number of alternatives.
One example is the one in [dcl.enum]/10:
    enum class Col { red, yellow, green };

A common problem now arises if the color is e.g. selected by a user or
retrieved from persistent storage, i.e. when there is the need for a <br>co=
nversion from an integral type to the enum and one needs to validate<br>the=
 input.

For enums with fixed underlying type one technically can safely use a
static_cast from the underlying type, but then the value is potentially<br>=
one not defined by any of the enumerators. While on the surface this<br>see=
ms to really only apply to user input and not to persistent data, it<br>can=
 be a problem when removing old options so that suddenly some<br>values in =
the persistent store are no longer enumerators in the enum, but<br>still ca=
n be safely cast to the enum type. So in practice you end up<br>having to k=
eep the old enumerators and have to set the sensible defaults<br>everywhere=
 you switch based on the enum value, or you have to resort to<br>variant 2:=
<br><br>So an other alternative is to explicitly `switch` on the integral v=
alue:

    switch (int i) {
    case static_cast&lt;int&gt;(Col::red):
        return Col::red;
    case static_cast&lt;int&gt;(Col::yellow):
        return Col::yellow;
    case static_cast&lt;int&gt;(Col::green):
        return Col::yellow;
    default:
        // return a sensible default/throw an exception
    }

This approach also has two major drawbacks:
    - Most likely this `switch` is going to be encapsulated in a `to_Col`<b=
r>     =C2=A0function, but as naming conventions differ from library to lib=
rary<br>      the user most likely has to look it up (or is too lazy and en=
ds up<br>      just using `static_cast`)
    - If one later adds another enumerator, the code will compile just fine=
,
      and all compilers I&#39;ve tested do not emit a warning either, as th=
ey
      can&#39;t infer the intend and only see a switch over integers. This =
means<br>      it is easy to end up with an enumerator that can never be re=
trieved<br>      after it has been persisted.<br><br>And finally one can wr=
ap the enum values in a seperate class/struct which has a<br>constructor th=
at encapsulates the switch described in the alternative above.<br>In most c=
ases the enum will then be defined as a nested enum inside the class.<br>Th=
is means one can no longer forward declare it. Additionally it discourages =
the<br>use of scoped enums inside the class, as noone wants to write `Col::=
Col::red`<br>(assuming `Color` is also the name for the wrapping class/stru=
ct), so suddenly<br>the enumerator happily promotes to `int` again. Moreove=
r, since this cannot be <br>generalized with templates one has to write the=
 same boilerplate code over and<br>over again.<br><br>So the solution that =
came to my mind is to allow the definition of constructors
for enums. Then one can put the switch above into the constructor and compi=
ler
writers are possibly able to detect missing enumerators due to the added co=
ntext.
Additionally it makes the language more consistent, as every user defined t=
ype
then could have constructors (one can already define a constructor for stru=
cts,
classes and even unions). It immediately solves the naming problem present =
in<br>alternative 2 above, and as far as I can tell does not have any impac=
t on ADL/<br>existing code without constructors defined for their enum.<br>=
<br>The syntax could look something like this:<br>    enum class Color {<br=
>       red,<br>       yellow,<br>       green;<br>  <br>       Color(int i=
);<br>    }<br><br>    Color::Color(int i) { <br>        switch (int i) {
        case static_cast&lt;int&gt;(Col::red):
            *this =3D Col::red;
        case static_cast&lt;int&gt;(Col::yellow):
            *this =3D Col::yellow;
        case static_cast&lt;int&gt;(Col::green):
            *this =3D Col::yellow;
        default:
            // set a sensible default/throw an exception
        }<br>    }   <br><br>Note that the semicolon after the last enumera=
tor as well as the constructor <br>declaration are supposed to be optional =
as to not break existing code. <br><br>What do you think? Has there been a =
similar proposal before, and if so, for what<br>reasons has it been rejecte=
d?<br><br>Best<br>Manuel<br></pre></div></blockquote></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/0dbc34ce-e6f8-4cb5-bfe5-b77308382ed6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0dbc34ce-e6f8-4cb5-bfe5-b77308382ed6=
%40isocpp.org</a>.<br />

------=_Part_603_730633179.1475766732649--

------=_Part_602_546652282.1475766732648--

.


Author: Ivan Kush <ivan.kushnar@gmail.com>
Date: Thu, 6 Oct 2016 08:13:54 -0700 (PDT)
Raw View
------=_Part_923_1033490962.1475766834602
Content-Type: multipart/alternative;
 boundary="----=_Part_924_2125725264.1475766834602"

------=_Part_924_2125725264.1475766834602
Content-Type: text/plain; charset=UTF-8


tell the truth, i'm not familiar with compiler internals and how scoped
enums are realized,
but maybe it's possible to add the `final`  keyword to scoped enum, which
will mean that we can't cast integer to this enum if, integer value don't
coincide with underlying values of enum internal data
enum class FooEnum *final*
{
};

For example

enum class FooEnum *final *: int {
    red = 0,
    green = 5
};

int j = 5;
FooEnum enum = static_cast<FooEnum>(j);//OK
int i = 6;
FooEnum enum = static_cast<FooEnum>(i);//throw exception

On Wednesday, October 5, 2016 at 4:36:44 PM UTC+3, Manuel Bergler wrote:
>
> Most of the time I use enums not as a "strong typedef" for integral types,
> but rather as a means to choose between a fixed number of alternatives.
> One example is the one in [dcl.enum]/10:
>     enum class Col { red, yellow, green };
>
> A common problem now arises if the color is e.g. selected by a user or
> retrieved from persistent storage, i.e. when there is the need for a
> conversion from an integral type to the enum and one needs to validate
> the input.
>
> For enums with fixed underlying type one technically can safely use a
> static_cast from the underlying type, but then the value is potentially
> one not defined by any of the enumerators. While on the surface this
> seems to really only apply to user input and not to persistent data, it
> can be a problem when removing old options so that suddenly some
> values in the persistent store are no longer enumerators in the enum, but
> still can be safely cast to the enum type. So in practice you end up
> having to keep the old enumerators and have to set the sensible defaults
> everywhere you switch based on the enum value, or you have to resort to
> variant 2:
>
> So an other alternative is to explicitly `switch` on the integral value:
>
>     switch (int i) {
>     case static_cast<int>(Col::red):
>         return Col::red;
>     case static_cast<int>(Col::yellow):
>         return Col::yellow;
>     case static_cast<int>(Col::green):
>         return Col::yellow;
>     default:
>         // return a sensible default/throw an exception
>     }
>
> This approach also has two major drawbacks:
>     - Most likely this `switch` is going to be encapsulated in a `to_Col`
>       function, but as naming conventions differ from library to library
>       the user most likely has to look it up (or is too lazy and ends up
>       just using `static_cast`)
>     - If one later adds another enumerator, the code will compile just fine,
>       and all compilers I've tested do not emit a warning either, as they
>       can't infer the intend and only see a switch over integers. This means
>       it is easy to end up with an enumerator that can never be retrieved
>       after it has been persisted.
>
> And finally one can wrap the enum values in a seperate class/struct which has a
> constructor that encapsulates the switch described in the alternative above.
> In most cases the enum will then be defined as a nested enum inside the class.
> This means one can no longer forward declare it. Additionally it discourages the
> use of scoped enums inside the class, as noone wants to write `Col::Col::red`
> (assuming `Color` is also the name for the wrapping class/struct), so suddenly
> the enumerator happily promotes to `int` again. Moreover, since this cannot be
> generalized with templates one has to write the same boilerplate code over and
> over again.
>
> So the solution that came to my mind is to allow the definition of constructors
> for enums. Then one can put the switch above into the constructor and compiler
> writers are possibly able to detect missing enumerators due to the added context.
> Additionally it makes the language more consistent, as every user defined type
> then could have constructors (one can already define a constructor for structs,
> classes and even unions). It immediately solves the naming problem present in
> alternative 2 above, and as far as I can tell does not have any impact on ADL/
> existing code without constructors defined for their enum.
>
> The syntax could look something like this:
>     enum class Color {
>        red,
>        yellow,
>        green;
>
>        Color(int i);
>     }
>
>     Color::Color(int i) {
>         switch (int i) {
>         case static_cast<int>(Col::red):
>             *this = Col::red;
>         case static_cast<int>(Col::yellow):
>             *this = Col::yellow;
>         case static_cast<int>(Col::green):
>             *this = Col::yellow;
>         default:
>             // set a sensible default/throw an exception
>         }
>     }
>
> Note that the semicolon after the last enumerator as well as the constructor
> declaration are supposed to be optional as to not break existing code.
>
> What do you think? Has there been a similar proposal before, and if so, for what
> reasons has it been rejected?
>
> Best
> Manuel
>
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving 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/067f9894-a22d-49c9-a52c-8ec86e711818%40isocpp.org.

------=_Part_924_2125725264.1475766834602
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><br></div><input type=3D"text" tabindex=3D"-1" role=
=3D"presentation" style=3D"height: 1px; opacity: 0; width: 1px; z-index: -1=
; overflow: hidden;"><div><div style=3D"overflow: auto;"><div style=3D"max-=
height: 10000px;"><div dir=3D"ltr">tell the truth, i&#39;m not familiar wit=
h compiler internals and how scoped enums are realized,<div>but maybe it&#3=
9;s possible to add the `final` =C2=A0keyword to scoped enum, which will me=
an that we can&#39;t cast integer to this enum if, integer value don&#39;t =
coincide with underlying values of enum internal data</div><div style=3D"bo=
rder: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color=
: rgb(250, 250, 250);"><code><span style=3D"color: rgb(0, 0, 136);">enum</s=
pan><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color:=
 rgb(0, 0, 136);">class</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</=
span><span style=3D"color: rgb(102, 0, 102);">FooEnum</span><span style=3D"=
color: rgb(0, 0, 0);">=C2=A0</span><b><span style=3D"color: rgb(0, 0, 136);=
">final</span></b><span style=3D"color: rgb(0, 0, 0);"><br></span><span sty=
le=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);=
"><br></span><span style=3D"color: rgb(102, 102, 0);">};</span></code></div=
><div><br></div><div>For example</div><div><br><div style=3D"border: 1px so=
lid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 2=
50, 250);"><code><span style=3D"color: rgb(0, 0, 136);">enum</span><span st=
yle=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 1=
36);">class</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span s=
tyle=3D"color: rgb(102, 0, 102);">FooEnum</span><span style=3D"color: rgb(0=
, 0, 0);">=C2=A0<b>final=C2=A0</b></span><span style=3D"color: rgb(102, 102=
, 0);">:</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span styl=
e=3D"color: rgb(0, 0, 136);">int</span><span style=3D"color: rgb(0, 0, 0);"=
>=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">{</span><span style=
=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 red=C2=A0</span><span style=3D"=
color: rgb(102, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0, 0);">=
=C2=A0</span><span style=3D"color: rgb(0, 102, 102);">0</span><span style=
=3D"color: rgb(102, 102, 0);">,</span><span style=3D"color: rgb(0, 0, 0);">=
<br>=C2=A0 =C2=A0 green=C2=A0</span><span style=3D"color: rgb(102, 102, 0);=
">=3D</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=
=3D"color: rgb(0, 102, 102);">5</span><span style=3D"color: rgb(0, 0, 0);">=
<br></span><span style=3D"color: rgb(102, 102, 0);">};</span><span style=3D=
"color: rgb(0, 0, 0);"><br><br></span><span style=3D"color: rgb(0, 0, 136);=
">int</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0j=C2=A0</span><span =
style=3D"color: rgb(102, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0=
, 0);">=C2=A0</span><span style=3D"color: rgb(0, 102, 102);">5</span><span =
style=3D"color: rgb(102, 102, 0);">;</span><span style=3D"color: rgb(0, 0, =
0);"><br></span><span style=3D"color: rgb(102, 0, 102);">FooEnum</span><spa=
n style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, =
0, 136);">enum</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><spa=
n style=3D"color: rgb(102, 102, 0);">=3D</span><span style=3D"color: rgb(0,=
 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">static_cast</s=
pan><span style=3D"color: rgb(102, 102, 0);">&lt;</span><span style=3D"colo=
r: rgb(102, 0, 102);">FooEnum</span><span style=3D"color: rgb(102, 102, 0);=
">&gt;(</span><span style=3D"color: rgb(0, 0, 0);">j</span><span style=3D"c=
olor: rgb(102, 102, 0);">)</span><font color=3D"#880000"><span style=3D"col=
or: rgb(102, 102, 0);">;</span>//OK</font><span style=3D"color: rgb(0, 0, 0=
);"><br></span><span style=3D"color: rgb(0, 0, 136);">int</span><span style=
=3D"color: rgb(0, 0, 0);">=C2=A0i=C2=A0</span><span style=3D"color: rgb(102=
, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><sp=
an style=3D"color: rgb(0, 102, 102);">6</span><span style=3D"color: rgb(102=
, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span s=
tyle=3D"color: rgb(102, 0, 102);">FooEnum</span><span style=3D"color: rgb(0=
, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">enum</span><s=
pan style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(1=
02, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><=
span style=3D"color: rgb(0, 0, 136);">static_cast</span><span style=3D"colo=
r: rgb(102, 102, 0);">&lt;</span><span style=3D"color: rgb(102, 0, 102);">F=
ooEnum</span><span style=3D"color: rgb(102, 102, 0);">&gt;(</span><span sty=
le=3D"color: rgb(0, 0, 0);">i</span><span style=3D"color: rgb(102, 102, 0);=
">)</span><font color=3D"#880000"><span style=3D"color: rgb(102, 102, 0);">=
;</span>//<wbr>throw exception<span style=3D"color: rgb(0, 0, 0);"><br></sp=
an></font></code></div></div></div></div></div></div><br>On Wednesday, Octo=
ber 5, 2016 at 4:36:44 PM UTC+3, Manuel Bergler wrote:<blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><pre>Most of the time I use enums =
not as a &quot;strong typedef&quot; for integral types,
but rather as a means to choose between a fixed number of alternatives.
One example is the one in [dcl.enum]/10:
    enum class Col { red, yellow, green };

A common problem now arises if the color is e.g. selected by a user or
retrieved from persistent storage, i.e. when there is the need for a <br>co=
nversion from an integral type to the enum and one needs to validate<br>the=
 input.

For enums with fixed underlying type one technically can safely use a
static_cast from the underlying type, but then the value is potentially<br>=
one not defined by any of the enumerators. While on the surface this<br>see=
ms to really only apply to user input and not to persistent data, it<br>can=
 be a problem when removing old options so that suddenly some<br>values in =
the persistent store are no longer enumerators in the enum, but<br>still ca=
n be safely cast to the enum type. So in practice you end up<br>having to k=
eep the old enumerators and have to set the sensible defaults<br>everywhere=
 you switch based on the enum value, or you have to resort to<br>variant 2:=
<br><br>So an other alternative is to explicitly `switch` on the integral v=
alue:

    switch (int i) {
    case static_cast&lt;int&gt;(Col::red):
        return Col::red;
    case static_cast&lt;int&gt;(Col::yellow):
        return Col::yellow;
    case static_cast&lt;int&gt;(Col::green):
        return Col::yellow;
    default:
        // return a sensible default/throw an exception
    }

This approach also has two major drawbacks:
    - Most likely this `switch` is going to be encapsulated in a `to_Col`<b=
r>     =C2=A0function, but as naming conventions differ from library to lib=
rary<br>      the user most likely has to look it up (or is too lazy and en=
ds up<br>      just using `static_cast`)
    - If one later adds another enumerator, the code will compile just fine=
,
      and all compilers I&#39;ve tested do not emit a warning either, as th=
ey
      can&#39;t infer the intend and only see a switch over integers. This =
means<br>      it is easy to end up with an enumerator that can never be re=
trieved<br>      after it has been persisted.<br><br>And finally one can wr=
ap the enum values in a seperate class/struct which has a<br>constructor th=
at encapsulates the switch described in the alternative above.<br>In most c=
ases the enum will then be defined as a nested enum inside the class.<br>Th=
is means one can no longer forward declare it. Additionally it discourages =
the<br>use of scoped enums inside the class, as noone wants to write `Col::=
Col::red`<br>(assuming `Color` is also the name for the wrapping class/stru=
ct), so suddenly<br>the enumerator happily promotes to `int` again. Moreove=
r, since this cannot be <br>generalized with templates one has to write the=
 same boilerplate code over and<br>over again.<br><br>So the solution that =
came to my mind is to allow the definition of constructors
for enums. Then one can put the switch above into the constructor and compi=
ler
writers are possibly able to detect missing enumerators due to the added co=
ntext.
Additionally it makes the language more consistent, as every user defined t=
ype
then could have constructors (one can already define a constructor for stru=
cts,
classes and even unions). It immediately solves the naming problem present =
in<br>alternative 2 above, and as far as I can tell does not have any impac=
t on ADL/<br>existing code without constructors defined for their enum.<br>=
<br>The syntax could look something like this:<br>    enum class Color {<br=
>       red,<br>       yellow,<br>       green;<br>  <br>       Color(int i=
);<br>    }<br><br>    Color::Color(int i) { <br>        switch (int i) {
        case static_cast&lt;int&gt;(Col::red):
            *this =3D Col::red;
        case static_cast&lt;int&gt;(Col::yellow):
            *this =3D Col::yellow;
        case static_cast&lt;int&gt;(Col::green):
            *this =3D Col::yellow;
        default:
            // set a sensible default/throw an exception
        }<br>    }   <br><br>Note that the semicolon after the last enumera=
tor as well as the constructor <br>declaration are supposed to be optional =
as to not break existing code. <br><br>What do you think? Has there been a =
similar proposal before, and if so, for what<br>reasons has it been rejecte=
d?<br><br>Best<br>Manuel<br></pre></div></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</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/067f9894-a22d-49c9-a52c-8ec86e711818%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/067f9894-a22d-49c9-a52c-8ec86e711818=
%40isocpp.org</a>.<br />

------=_Part_924_2125725264.1475766834602--

------=_Part_923_1033490962.1475766834602--

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Wed, 12 Oct 2016 10:20:25 -0400
Raw View
(Apologies if this posts twice; the original appears to have gotten lost.)

On 2016-10-05 09:36, Manuel Bergler wrote:
> What do you think? Has there been a similar proposal before, and if so, for what
> reasons has it been rejected?

I'm pretty sure I've mentioned it before, but I don't know if there has
been a concrete proposal yet. Personally, I'd like to see the ability to
add *members* to an enum... including constructors.

For example:

  enum class foo
  {
    // values...
    foo() : *this(DEFAULT_VALUE) {}
    foo(int i) { ...; *this = ...; }
    operator int() const { return *this; } // implicit conversion
    operator char const*() const { ... }
    operator++() { ... }
  }

--
Matthew

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/ntlgr6%243tk%244%40blaine.gmane.org.

.