enum class foo : bool {}

1,211 views
Skip to first unread message

Avi Kivity

unread,
Nov 30, 2016, 3:45:04 AM11/30/16
to std-pr...@isocpp.org
The trick of declaring type-safe integral types using `enum class
my_int_type : int {}` seems to be quite popular. I propose extending it
to bool:


enum class foo : bool {};


foo x = foo::true; // ok

x = false; // error


foo f1(), f2();

foo y = f1() || f2();


enum class bar : bool {};

enum class baz : bool {};


template <foo a, bar b, baz c> a_template_with_many_options { ... }

using with_my_options = a_template_with_many_options<foo::true,
bar::false, baz::true>;
// more readable than a_template_with_many_options<true,
false, true>;


Such a construct (enum class with no members, derived from bool) would
have logical operators &&/||/! automatically defined, as well as
explicit conversions to regular bool. I think it could help projects
suffering from flag proliferation.

Dawid Pilarski

unread,
Nov 30, 2016, 4:15:07 AM11/30/16
to std-pr...@isocpp.org
I think this is inconsistent with what currently `enum class my_int_type : int {}' means. It's proper meaning is, that the enum will be of same size as integer (with no concrete enum labels specified). This has got nothing to do with inheritance.

In your case specified enum will 'inherit' enums from the boolean type (true, false).

Also one would have to consider what will :

 enum class bar : bool {A,B,C,D}; mean? What is the meaning of true and false then?

I think better approach is to simply declare:

enum class my_int_type : int {DISABLED, ENABLED}; which is exactly same in meaning, but does not introduce any strange syntax, that introduces some inconsistency in standard.



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8414e09f-34eb-870f-83f8-df2f75757c28%40scylladb.com.

D. B.

unread,
Nov 30, 2016, 4:18:02 AM11/30/16
to std-pr...@isocpp.org
I think what you really want is strong typedefs. In which case, I couldn't agree more. Making a concession to get some odd syntax that restricts the ability to bool only would be a massive own goal.

Avi Kivity

unread,
Nov 30, 2016, 5:41:03 AM11/30/16
to std-pr...@isocpp.org
On 11/30/2016 11:15 AM, Dawid Pilarski wrote:
I think this is inconsistent with what currently `enum class my_int_type : int {}' means. It's proper meaning is, that the enum will be of same size as integer (with no concrete enum labels specified). This has got nothing to do with inheritance.


You are missing a special case of enum class : some_type; the one where no members are specified.


For example there was a proposal to define std::byte as enum class : uint8_t {}; with the meaning of introducing a new type that has the same underlying implementation as uint8_t, but does not implicitly convert.




In your case specified enum will 'inherit' enums from the boolean type (true, false).

Also one would have to consider what will :

 enum class bar : bool {A,B,C,D}; mean? What is the meaning of true and false then?

I am not proposing to change the case where members are specified at all.  Just an enum class, based on bool, without any members.



I think better approach is to simply declare:

enum class my_int_type : int {DISABLED, ENABLED}; which is exactly same in meaning, but does not introduce any strange syntax, that introduces some inconsistency in standard.

This approach requires the user to define &&, ||, !, and bool conversion (the last is not allowed, IIUC).


2016-11-30 9:45 GMT+01:00 Avi Kivity <a...@scylladb.com>:
The trick of declaring type-safe integral types using `enum class my_int_type : int {}` seems to be quite popular.  I propose extending it to bool:


   enum class foo : bool {};


   foo x = foo::true;    // ok

   x = false;   // error


   foo f1(), f2();

   foo y = f1() || f2();


   enum class bar : bool {};

   enum class baz : bool {};


   template <foo a, bar b, baz c> a_template_with_many_options { ... }

   using with_my_options = a_template_with_many_options<foo::true, bar::false, baz::true>;
         // more readable than a_template_with_many_options<true, false, true>;


Such a construct (enum class with no members, derived from bool) would have logical operators &&/||/! automatically defined, as well as explicit conversions to regular bool.  I think it could help projects suffering from flag proliferation.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8414e09f-34eb-870f-83f8-df2f75757c28%40scylladb.com.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Avi Kivity

unread,
Nov 30, 2016, 5:41:57 AM11/30/16
to std-pr...@isocpp.org
We already have strong typedefs, their syntax is "enum class new_type :
old_type {};"


D. B.

unread,
Nov 30, 2016, 6:00:42 AM11/30/16
to std-pr...@isocpp.org
On Wed, Nov 30, 2016 at 10:41 AM, Avi Kivity <a...@scylladb.com> wrote:

We already have strong typedefs, their syntax is "enum class new_type : old_type {};"


Um, no? I don't see what you mean. Using enum class seems hopelessly limited, being constrained only to integral types and requiring named enumerators (or horrible casts everywhere).

The definition of "strong typedef" that I'm familiar with is about declaring a new alias to an existing type - which would use the same representation but perform compile-time checking that what's given was really declared as the strong typedef, not the original type. Thus ensuring we really mean what we write.

For instance:
 
using explicit Money = double; // [Initiate syntax bikeshed]

Money g_my_fortune{1'000'000.00};

void debit_my_account(Money const amount)
{
    g_my_fortune -= amount;
}

Money const actual_money = 20.00;
debit_my_account(actual_money); // OK

double const some_arbitrary_value = std::numeric_limits<double>::max(); // oh no! what a terrible mistake!!
debit_my_account(some_arbitrary_value); // phew! compile-time error.

I know we can approximate this pretty well with user-defined literals, but it might still be nice to see the above variant, assuming it could be done without too much hassle.

Avi Kivity

unread,
Nov 30, 2016, 6:13:10 AM11/30/16
to std-pr...@isocpp.org



On 11/30/2016 01:00 PM, D. B. wrote:
On Wed, Nov 30, 2016 at 10:41 AM, Avi Kivity <a...@scylladb.com> wrote:

We already have strong typedefs, their syntax is "enum class new_type : old_type {};"


Um, no? I don't see what you mean. Using enum class seems hopelessly limited, being constrained only to integral types and requiring named enumerators (or horrible casts everywhere).


D. B.

unread,
Nov 30, 2016, 6:17:35 AM11/30/16
to std-pr...@isocpp.org
...thus proving my point. std::byte can be initialised from an integer literal but otherwise doesn't act like or interact with one, requiring manual reimplementation of any desired operators. What I'm talking about is something that is represented by, and acts like, the underlying/referred type, but simply can't be interchanged with it at call sites, etc.

I really don't see the point of std::byte anyway, but that's an aside.

Dawid Pilarski

unread,
Nov 30, 2016, 6:18:28 AM11/30/16
to std-pr...@isocpp.org
This is not strong typedef at all. Simply try to do this with any class or struct. It will fail. This is enum class without labels and not a typedef at all. It may behave so for some types, though (integer ones).
I do not see any bad sides of implementing std::byte in this way. Still you are trying to achieve something different.

True, that it will not behave as bool in bool contexts, but strong typedefs would do this.

enum class newType:int;

without {} braces is just early declaration of the version
enum class newType:int{}



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Avi Kivity

unread,
Nov 30, 2016, 6:33:46 AM11/30/16
to std-pr...@isocpp.org
Please re-read my original proposal, I think you're reacting to
something completely different.


Dawid Pilarski

unread,
Nov 30, 2016, 9:42:58 AM11/30/16
to std-pr...@isocpp.org
"We already have strong typedefs, their syntax is "enum class new_type : old_type {};"

This is not a strong typedef.

Please note, that allowing syntax:

enum class type : int{A,B,C,D};

and not allowing:

enum class typeB : bool{A, B, C, D};

is very inconsistent. Inconsistency grows with total difference with semantics of such declaration.

Also

enum class typeB : bool; without labels is strong inconsistency in terms of semantics, because

enum class typeA : int; //here I mean forward declaration of the enum class. Here I can do forward declaration, because size is known.
enum class typeB : bool; //here I am declaring new type. No possible way of forward declaration (because this syntax is already used to declare new type)

mixing forward declaration syntax with declaration of completely new type for me seems very dangerous.

Using same syntax for different purposes in different context might be surprising for the programmer, and using same syntax, which semantics differ for particular type is just overkill.
Indeed strong typedefs are the solution, but strongly typed enums are not strong typedefs at all as already mentioned.


2016-11-30 12:33 GMT+01:00 Avi Kivity <a...@scylladb.com>:
Please re-read my original proposal, I think you're reacting to something completely different.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Nicol Bolas

unread,
Nov 30, 2016, 10:53:47 AM11/30/16
to ISO C++ Standard - Future Proposals
We should not (further) encourage the (ab)use of `enum class` as a poor-man's strong typedef. By continuing to do so, we effectively dilute the need for real strong typedefs, thus ensuring that we'll never get them.

Nevin Liber

unread,
Nov 30, 2016, 3:15:58 PM11/30/16
to std-pr...@isocpp.org

On Wed, Nov 30, 2016 at 8:42 AM, Dawid Pilarski <dawid...@gmail.com> wrote:
enum class type : int{A,B,C,D};

and not allowing:

enum class typeB : bool{A, B, C, D};

is very inconsistent.

Given that bool only has two values, what values are C & D supposed to represent?
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com>  +1-847-691-1404

Ville Voutilainen

unread,
Nov 30, 2016, 3:19:52 PM11/30/16
to ISO C++ Standard - Future Proposals
On 30 November 2016 at 22:15, Nevin Liber <ne...@eviloverlord.com> wrote:
>
> On Wed, Nov 30, 2016 at 8:42 AM, Dawid Pilarski <dawid...@gmail.com>
> wrote:
>>
>> enum class type : int{A,B,C,D};
>>
>> and not allowing:
>>
>> enum class typeB : bool{A, B, C, D};
>>
>> is very inconsistent.
>
>
> Given that bool only has two values, what values are C & D supposed to
> represent?

Well, I can write
enum class typeB : bool{TRUE = true, FALSE=false, ONE=true, ZERO=false};
today, so C is ONE=true and D is ZERO=false. ;)

Avi Kivity

unread,
Dec 3, 2016, 8:02:45 AM12/3/16
to std-pr...@isocpp.org
On 11/30/2016 04:42 PM, Dawid Pilarski wrote:
"We already have strong typedefs, their syntax is "enum class new_type : old_type {};"

This is not a strong typedef.


The designers of std::byte seemed to think that it is.  It doesn't implicitly convert to to uint8_t or its friends, and they don't convert back.


Please note, that allowing syntax:

enum class type : int{A,B,C,D};

and not allowing:

enum class typeB : bool{A, B, C, D};

is very inconsistent. Inconsistency grows with total difference with semantics of such declaration.


I did not propose forbidding "enum class : bool { A, B, C, D };".  My proposal made no comment about it, at all.


Also

enum class typeB : bool; without labels is strong inconsistency in terms of semantics, because


I also make no comment about "enum class typeB : bool;"

The proposal only mentioned

    enum class typeB : bool {};

which does not conflict with anything.


enum class typeA : int; //here I mean forward declaration of the enum class. Here I can do forward declaration, because size is known.
enum class typeB : bool; //here I am declaring new type. No possible way of forward declaration (because this syntax is already used to declare new type)

mixing forward declaration syntax with declaration of completely new type for me seems very dangerous.

Using same syntax for different purposes in different context might be surprising for the programmer, and using same syntax, which semantics differ for particular type is just overkill.
Indeed strong typedefs are the solution, but strongly typed enums are not strong typedefs at all as already mentioned.





2016-11-30 12:33 GMT+01:00 Avi Kivity <a...@scylladb.com>:
Please re-read my original proposal, I think you're reacting to something completely different.


--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/ccb56376-962b-ea9d-718e-710e2fc7300d%40scylladb.com.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Avi Kivity

unread,
Dec 4, 2016, 4:20:37 AM12/4/16
to std-pr...@isocpp.org

Fair enough.


On 11/30/2016 05:53 PM, Nicol Bolas wrote:
We should not (further) encourage the (ab)use of `enum class` as a poor-man's strong typedef. By continuing to do so, we effectively dilute the need for real strong typedefs, thus ensuring that we'll never get them.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Reply all
Reply to author
Forward
0 new messages