Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

enum initialization

134 views
Skip to first unread message

JiiPee

unread,
Nov 9, 2017, 2:41:47 PM11/9/17
to
Is the a way to initialize enum values so that the end result would be:

enum class MyOpt {opt1=1, opt2=2, opt3=4, opt4=8}; // etc....multiplied by 2

Yes I can do it manually, but I would like to do it automatically maybe
with a function or something (reducing human error).

Or the only way to do it is to hardcode like that?

I need this in my flags system where I need values 1,2,4,8,16,...

James R. Kuyper

unread,
Nov 9, 2017, 3:07:56 PM11/9/17
to
On 2017-11-09 14:41, JiiPee wrote:
> Is the a way to initialize enum values so that the end result would be:
>
> enum class MyOpt {opt1=1, opt2=2, opt3=4, opt4=8}; // etc....multiplied by 2
> Yes I can do it manually, but I would like to do it automatically maybe

This is about as close as you can get to doing it automatically:

enum class MyOpt {opt1=1, opt2, opt3=opt2*2, opt4=opt3*2};

Alf P. Steinbach

unread,
Nov 9, 2017, 3:20:34 PM11/9/17
to
Two possible alternatives:

* Define `operator|` that adds the necessary `1<<n`.
* Use a `std::bitset`.

Cheers & hth.,

- Alf


JiiPee

unread,
Nov 9, 2017, 3:23:44 PM11/9/17
to
Thanks, but just thinking another thing: is is a good idea at all using
enums as (option) flags? I read some say online that should use
constants instead.

Ian Collins

unread,
Nov 9, 2017, 3:28:47 PM11/9/17
to
On 11/10/2017 09:23 AM, JiiPee wrote:
> Thanks, but just thinking another thing: is is a good idea at all using
> enums as (option) flags? I read some say online that should use
> constants instead.

The arguments are less clear now that with have typed enums! Before
C++11 a good case could be made for constants given enums always had an
underlying type of int. Now we can specify the type, I think enums are
a better choice.

--
Ian.

Paavo Helde

unread,
Nov 9, 2017, 6:27:43 PM11/9/17
to
On 9.11.2017 22:23, JiiPee wrote:
> Thanks, but just thinking another thing: is is a good idea at all using
> enums as (option) flags? I read some say online that should use
> constants instead.

In my experience, enums are much better than static constant integer
data members in a class. The latter sometimes require a separate
definition outside of the class, which is a hassle. And "sometimes"
means depending on the usage of the constant, the compiler, the compiler
version and the compiler optimization flags, making this approach pretty
fragile.

Actually it is very easy to define an enum with bit flag values:

enum flags: std::uint8 {
A = (1<<0),
B = (1<<1),
C = (1<<2),
// ...
};

Also, the bitflags are typically combined, and with the enum approach
the result is still legally representable in the same enum type, making
this more encapsulated (especially with 'enum class'). With separate
integer constants there is no separate type and the compiler does not
even warn you if you try to combine incompatible constants.

A drawback of bitflag enums is that one also needs to define several
one-liners like operator|, operator& for each such enum type for using
them smoothly. I believe the new meta-language features will make this a
bit easier in the future.

hth
Paavo





Message has been deleted

Xiao Liang

unread,
Nov 9, 2017, 9:29:01 PM11/9/17
to
Use macro:

enum class MyOpt {
#define OPT(n) opt ## n = 1 << n
OPT(0),
OPT(1),
OPT(2),
OPT(3)
#undef OPT
};

Or if you have complex initializer:

#define OPT(n) opt ## n = opt_value(n)
constexpr int opt_value(int n) {
if (n == 0) {
return 1;
}
return 2 * opt_value(n - 1);
}

Öö Tiib

unread,
Nov 9, 2017, 11:18:20 PM11/9/17
to
If you there are lot of flags (more than 16 and growing) then
life has shown that using enum may complicate your future. Use
std::bitset as such flag system and keep the enum as index of
a flag in it (IOW defaults 0,1,2,3 ...).

When there are less flags that unlikely will grow over time then
do not overthink it. Either use explicit decimals (1, 2, 4, 8,
16, 32, ...) or hexadecimal (0x01, 0x02, 0x04, 0x08, 0x10,
0x20, ...) or bit shifts (1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4,
1 << 5, ...). It is purely aesthetic preference since every of
those will work fine.

Scott Lurndal

unread,
Nov 10, 2017, 8:45:15 AM11/10/17
to
Paavo Helde <myfir...@osa.pri.ee> writes:
>On 9.11.2017 22:23, JiiPee wrote:
>> Thanks, but just thinking another thing: is is a good idea at all using
>> enums as (option) flags? I read some say online that should use
>> constants instead.
>
>In my experience, enums are much better than static constant integer
>data members in a class. The latter sometimes require a separate
>definition outside of the class, which is a hassle. And "sometimes"
>means depending on the usage of the constant, the compiler, the compiler
>version and the compiler optimization flags, making this approach pretty
>fragile.

It's only fragile if one doesn't _always_ add the separate definition
as a rule.

Prior to typed enums, static const members were the only way to specify
unsigned 64-bit constants due to the default int type for enums.

Unfortunatly, some of us are unable to take advantage of C++11 and
beyond due to circumstances outside of our control and must live with
static const members.

Mr Flibble

unread,
Nov 10, 2017, 9:08:00 AM11/10/17
to
Egregious.

opt2=opt1*2

/Flibble

Öö Tiib

unread,
Nov 10, 2017, 9:13:14 AM11/10/17
to
On Friday, 10 November 2017 15:45:15 UTC+2, Scott Lurndal wrote:
>
> Unfortunatly, some of us are unable to take advantage of C++11 and
> beyond due to circumstances outside of our control and must live with
> static const members.

Unfortunately there always will be new platform vendors who make
some sort of Crap++ compiler instead of standard one and then
call it C++ and even ask money for it. For example from Arduino or
Texas Instruments one will get such trash.

James R. Kuyper

unread,
Nov 10, 2017, 10:03:41 AM11/10/17
to
I'm simply taking advantage of the default, which is that opt2=opt1+1,
which in this case is exactly the same as opt2=opt1*2. I expect any
reader of my code to be familiar with that default. Perhaps I'm setting
my expectations too high?

Scott Lurndal

unread,
Nov 10, 2017, 10:09:45 AM11/10/17
to
In our case, it is dependence upon third-party object libraries that
require certain versions of gcc that don't fully support C++11 and
beyond.

That's ok with me; the only features from C++11+ that I'd be
interested in are typed enums and static_assert.

Gareth Owen

unread,
Nov 10, 2017, 12:01:07 PM11/10/17
to
"James R. Kuyper" <james...@verizon.net> writes:

> I'm simply taking advantage of the default, which is that opt2=opt1+1,
> which in this case is exactly the same as opt2=opt1*2. I expect any
> reader of my code to be familiar with that default.

So you've a potential cost (someone not understanding the default -
slightly less comprehensible code), and literally no benefit at besides
far less typing than it took to explain it.

If you're using a pattern, breaking the pattern for *no* *good* *reason*
is a poor idea. People like patterns, and people understand patterns.

Jorgen Grahn

unread,
Nov 11, 2017, 3:54:33 AM11/11/17
to
On Fri, 2017-11-10, Gareth Owen wrote:
> "James R. Kuyper" <james...@verizon.net> writes:
>
>> I'm simply taking advantage of the default, which is that opt2=opt1+1,
>> which in this case is exactly the same as opt2=opt1*2. I expect any
>> reader of my code to be familiar with that default.

> So you've a potential cost (someone not understanding the default -
> slightly less comprehensible code), and literally no benefit at besides
> far less typing than it took to explain it.

People /do/ understand the default. Writing superfluous text is
stupid (I've been told to write "unsigned int" instead of just
"unsigned" for this reason.)

> If you're using a pattern, breaking the pattern for *no* *good* *reason*
> is a poor idea. People like patterns, and people understand patterns.

But /that/ is the real reason I agree, and wouldn't write the enum
that way.

In fact, I wouldn't do anything fancy at all and just write:

foo = 1,
bar = 2,
baz = 4,
bat = 8,
xxx = 16,
...

I'd also stop and think if I need such an enum in the first place.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Gareth Owen

unread,
Nov 11, 2017, 5:21:39 AM11/11/17
to
Jorgen Grahn <grahn...@snipabacken.se> writes:

> In fact, I wouldn't do anything fancy at all and just write:
>
> foo = 1,
> bar = 2,
> baz = 4,
> bat = 8,
> xxx = 16,

I'm totally fine with that. It's

foo = 1,
bar,
baz = 4,
bat = 8,
xxx = 16,

that's gratuitously difficult to parse.

Mr Flibble

unread,
Nov 11, 2017, 10:19:59 AM11/11/17
to
Why decimal? I think the following is a better pattern:

foo = 0b000001,
bar = 0b000010,
baz = 0b000100,
bat = 0b001000,
xxx = 0b010000,
/Flibble

Gareth Owen

unread,
Nov 11, 2017, 2:26:42 PM11/11/17
to
Mr Flibble <flibbleREM...@i42.co.uk> writes:

> Why decimal? I think the following is a better pattern:
>
> foo = 0b000001,
> bar = 0b000010,
> baz = 0b000100,
> bat = 0b001000,
> xxx = 0b010000,
> /Flibble

Thats pretty clear if your compiler supports C++14 -

foo = 0001,
bar = 0002,
baz = 0004,
bat = 0010,
xxx = 0020,

works similarly diagonally if it doesn't

Mr Flibble

unread,
Nov 11, 2017, 3:30:30 PM11/11/17
to
Octal? Sneaky.

/Flibble


Juha Nieminen

unread,
Nov 13, 2017, 4:47:45 AM11/13/17
to
JiiPee <n...@notvalid.com> wrote:
> Thanks, but just thinking another thing: is is a good idea at all using
> enums as (option) flags? I read some say online that should use
> constants instead.

Constants of what type, exactly?

The good thing about enums is that they can be made strongly typed.
If you wanted to make an integral constant "strongly typed" (ie. you
want to be able to, for example, declare a function that takes a value
of that type and nothing else), you'll need to write your own class
which, while possible, is more work.

Jorgen Grahn

unread,
Nov 14, 2017, 6:51:27 AM11/14/17
to
On Thu, 2017-11-09, JiiPee wrote:
> Thanks, but just thinking another thing: is is a good idea at all using
> enums as (option) flags? I read some say online that should use
> constants instead.

More interestingly, is it a good idea to use "(option) flags"?

I guess you mean those things you or together to enable or disable
features of a function you're calling. But I don't see those getting
used a lot, except in the POSIX APIs, which are a bit special.
I don't find myself writing a lot of such code.

Paavo Helde

unread,
Nov 14, 2017, 8:16:58 AM11/14/17
to
On 14.11.2017 13:51, Jorgen Grahn wrote:
> On Thu, 2017-11-09, JiiPee wrote:
>> Thanks, but just thinking another thing: is is a good idea at all using
>> enums as (option) flags? I read some say online that should use
>> constants instead.
>
> More interestingly, is it a good idea to use "(option) flags"?
>
> I guess you mean those things you or together to enable or disable
> features of a function you're calling. But I don't see those getting
> used a lot, except in the POSIX APIs, which are a bit special.
> I don't find myself writing a lot of such code.

By some reason, I do. In my current project I have for example 20 enums
with bit flag values. A typical such enum contains about ten values,
some do more.

I guess I could use some struct or class with lots of bool members
instead, but this would just waste more memory, with no substantial
benefit as far as I can see.

Cheers
Paavo


Jorgen Grahn

unread,
Nov 14, 2017, 11:17:08 AM11/14/17
to
No, that wouldn't be a big improvement. It would give you a good place
(the constructor) to check that the combination of flags makes sense,
but that's about it I think.

Better ones would be to use several different functions or a template,
when the choice of options is a compile-time decision. Or passing in
a functor which selects some aspect of the function's behavior. Both
of these get rid of "if (option) ... else ..." in the implementation.

I can't say for sure I do this a lot, and that that's why I don't
define option flags. To be honest I think it may have more to do with
that I try to avoid writing general and flexible code.

Öö Tiib

unread,
Nov 14, 2017, 4:42:22 PM11/14/17
to
On Tuesday, 14 November 2017 13:51:27 UTC+2, Jorgen Grahn wrote:
> On Thu, 2017-11-09, JiiPee wrote:
> > Thanks, but just thinking another thing: is is a good idea at all using
> > enums as (option) flags? I read some say online that should use
> > constants instead.
>
> More interestingly, is it a good idea to use "(option) flags"?
>
> I guess you mean those things you or together to enable or disable
> features of a function you're calling. But I don't see those getting
> used a lot, except in the POSIX APIs, which are a bit special.
> I don't find myself writing a lot of such code.

That can be because the problem domain you deal with does not need
flags.

For me the idea of "flags" is often same as the idea of discrete
"set". When the objects that can be (members or elements) in set is
rather limited then it is more efficient to represent presence (or
absence) of an element in set as a flag.

Just imagine std::set<uint8_t>. It is on most cases terribly
inefficient compared to std::bitset<256> that takes fixed 32 bytes,
and without trees and dynamic allocations provides effectively
exactly same functionality.

Jorgen Grahn

unread,
Nov 15, 2017, 8:57:53 AM11/15/17
to
On Tue, 2017-11-14, Öö Tiib wrote:
> On Tuesday, 14 November 2017 13:51:27 UTC+2, Jorgen Grahn wrote:
>> On Thu, 2017-11-09, JiiPee wrote:
>> > Thanks, but just thinking another thing: is is a good idea at all using
>> > enums as (option) flags? I read some say online that should use
>> > constants instead.
>>
>> More interestingly, is it a good idea to use "(option) flags"?
>>
>> I guess you mean those things you or together to enable or disable
>> features of a function you're calling. But I don't see those getting
>> used a lot, except in the POSIX APIs, which are a bit special.
>> I don't find myself writing a lot of such code.
>
> That can be because the problem domain you deal with does not need
> flags.

Yes (I elaborated a bit in a later posting) or maybe we solve the same
problems in drastically different ways.

It would be interesting to learn which is the main reason people
disagree on design issues.

> For me the idea of "flags" is often same as the idea of discrete
> "set". When the objects that can be (members or elements) in set is
> rather limited then it is more efficient to represent presence (or
> absence) of an element in set as a flag.
>
> Just imagine std::set<uint8_t>. It is on most cases terribly
> inefficient compared to std::bitset<256> that takes fixed 32 bytes,
> and without trees and dynamic allocations provides effectively
> exactly same functionality.

0 new messages