241

Treating enums as flags works nicely in C# via the [Flags] attribute, but what's the best way to do this in C++?

For example, I'd like to write:

enum AnimalFlags
{
    HasClaws = 1,
    CanFly =2,
    EatsFish = 4,
    Endangered = 8
};

seahawk.flags = CanFly | EatsFish | Endangered;

However, I get compiler errors regarding int/enum conversions. Is there a nicer way to express this than just blunt casting? Preferably, I don't want to rely on constructs from 3rd party libraries such as boost or Qt.

EDIT: As indicated in the answers, I can avoid the compiler error by declaring seahawk.flags as int. However, I'd like to have some mechanism to enforce type safety, so someone can't write seahawk.flags = HasMaximizeButton.

Tony the Pony
  • 40,327
  • 71
  • 187
  • 281
  • As far as I know in Visual C++ 2013 the `[Flags]` attribute works just fine i.e.: `[Flags] enum class FlagBits{ Ready = 1, ReadMode = 2, WriteMode = 4, EOF = 8, Disabled = 16};` – rivanov Jul 21 '14 at 02:34
  • @rivanov, No it doesn't work with C++ (2015 also). Did you mean C# ? – Ajay Mar 08 '16 at 11:50
  • 8
    @rivanov, The [Flags] attribute works only with the .Net Framework in C++CLI, the native C++ does not support such attributes. – Zoltan Tirinda Apr 02 '16 at 07:11
  • 1
    Any update to the answers since `enum class` exists? – Sandburg Dec 15 '21 at 10:57

30 Answers30

306

The "correct" way is to define bit operators for the enum, as:

enum AnimalFlags
{
    HasClaws   = 1,
    CanFly     = 2,
    EatsFish   = 4,
    Endangered = 8
};

inline AnimalFlags operator|(AnimalFlags a, AnimalFlags b)
{
    return static_cast<AnimalFlags>(static_cast<int>(a) | static_cast<int>(b));
}

Etc. rest of the bit operators. Modify as needed if the enum range exceeds int range.

eidolon
  • 3,223
  • 2
  • 16
  • 5
  • 50
    ^ this. The only question is how to automate/templatize the operator definitions so you don't have to be constantly defining them every time you add a new enum. – eodabash Apr 08 '11 at 03:07
  • 15
    Also, is the cast from an arbitrary int back to the enum type valid, even if the int value does not correspond to any of the enum's identifiers? – Ingo Schalk-Schupp Dec 30 '13 at 20:47
  • 1
    I can use it like `a = (a | flag)` but not like `a |= flag` what should I do about that ? – Zaffy Apr 03 '14 at 15:07
  • 4
    @Zaffy, maybe you could redefine the "|=" operator? – rivanov Jul 21 '14 at 02:09
  • This doesn't really make sense - if you have HasClaws | EatsFish, the result has decimal value 5, so what is static_cast(5) supposed to give you? – Hoobajoob Mar 13 '15 at 16:35
  • 18
    This is complete nonsense. Which member of `AnimalFlags` is represented by the expression `HasClaws | CanFly`? This is _not_ what `enum`s are for. Use integers and constants. – Lightness Races in Orbit Mar 27 '15 at 17:49
  • 42
    @LightnessRacesinOrbit: That's not correct. The domain of an enum type is the domain of its underlying type - it's only that certain ones have been given a name. And to answer your question: The member "`(HasClaws | CanFly)`". – Xeo Mar 27 '15 at 18:03
  • 4
    @Xeo: Just because it's legal doesn't mean it's a good idea. Enumerations are for enumerating. That's why they're called enumerations. It's sad that C++ allows this ("It is possible to define an enumeration that has values not defined by any of its enumerators") but I suspect it's for compatibility with existing, legacy, terrible, C software. – Lightness Races in Orbit Mar 27 '15 at 18:29
  • 2
    Also add `&`, `&=` and `~` operators. And relevant `&=`, and `*` (multiplication). Ground-bound are selected by `(animal &~CanFly)`. Losing flight is `animal &=~CanFly`. Defining whether animal can fly without changing other properties (for `bool getFlightAbility()`) is `animal = (animal &~CanFly) | (CanFly*getFlightAbility())`. Is it really worth the headaches? – SF. Jun 23 '15 at 10:53
  • Actually it's pretty common to have enums map multiple labels to the same integer. Example: `enum color {red = 0, green = 1, blue = 2, yellow = 3, last_color=3 };` I also can't fathom any compatibility issues. Consider `int i = 17; color x = (color) i`. It's legal by the C standard, and the runtime code doesn't know (or care) whether any labels point to 17 or not. If this doesn't work on some compiler I'd love to know about that. Also, in the example given earlier, try it with Visual Studio. For me the watch window actually shows the value as "HasClass | CanFly". – Kevin Holt Oct 28 '15 at 22:55
  • 1
    A safer approach would be to define a class that just wraps an int, then do the operator overloads on that, so only valid values can be ORed into the int. That way, you get the type checking and performance, but the compiler won't try to optimize out "impossible" values. – uliwitness Nov 28 '15 at 12:37
  • When I implement `operator&` like this `return (msgboxflags) ((int) a & (int) b);` and I write `if (flags & msgboxflags::CHECKED)`, it tells me "expression must have type `bool` (or be convertible to `bool`)". – lost_in_the_source Dec 06 '15 at 15:46
  • Do you HAVE to use powers of 2? because I tend to assign my enums to consecutive numbers, is that bad practice, and if so, why? Edit: I'm in C, not C++ so it may change things. – MarcusJ Sep 09 '16 at 04:38
  • 7
    @MarcusJ: restricting your values to powers of 2 permits you to use your enums as bit-flags. Thus if you get a 3 you know it both `HasClaws`( = 1) and `CanFly`(= 2). If instead you just assign the values 1 through 4 straight through and you get a 3, it might be a single `EatsFish`, or again a combination of `HasClaws` and `CanFly`. If your enumeration denotes exclusive states only then consecutive values are fine, but a combination of flags needs the values to be bit-exclusive. – Christian Severin Nov 17 '16 at 15:54
  • 1
    @Hoobajoob It makes perfect sense. The enum provides you with the bricks. How you combine these bricks is up to you. You may or may not have support for `HasClaws | EatsFish`. One can even use this in a factory pattern where, depending on whether the combination is valid or not, a specific instance of an Animal is returned. – rbaleksandar Feb 05 '17 at 14:44
  • 4
    @Xeo: FWIW, I have changed my mind on enum domains in the intervening years ^_^ although I'm still not entirely sold on using these for bitmask constants rather than a bunch of constants in a namespace, scoped enums get us close enough to make it worthwhile on balance. – Lightness Races in Orbit Dec 17 '18 at 16:09
  • @LightnessRacesinOrbit: It makes no sense to have a constant to say HasClawCanFlyEatsFishEndangered. And if you used 22 out of 32 flags, the name would be insanely long or you give it an arbitrary name where you need a dictionary to explain what it means. Not only that, you can still define the enum value 52156 if you want. You are not losing anything. Bitwise enum flags is the most basic way to pack multiple Booleans in one value. And of course, we shouldn't abuse it and should only pack Booleans together when it makes sense. – BoBoDev Jan 04 '19 at 18:08
  • @BoBoDev I think we agree. I wasn't suggesting having a constant for every possible combination of the individual options. I was suggesting having constants as direct replacements, one-to-one, for the enumerators. But I don't consider this to be a big deal any more – Lightness Races in Orbit Jan 04 '19 at 19:34
  • 1
    @KevinHolt • That's actually UB as per the standard. The compiler can trust that the highest value mask is `0b11` so only 0 - 3 are allowed. (You could throw in a `teal=32`, which would then make your example legit and not UB.) The compiler may use that meta-knowledge to make allowed optimizations which may cause 17 to do some amusing and puzzling things. Of course hilarity and hijinks ensue. – Eljay Feb 01 '19 at 20:33
  • 2
    (To clarify @Eljay's point, as of C++17, the result of casting an integer/floating-point/enumeration value `V` to any enum type `E`, where `E`'s underlying type is unspecified and `V` is out of `E`'s range, is undefined behaviour (it was unspecified pre-C++17). Here, `E`'s range is defined by the smallest bitfield that can hold all of `E`'s enumerators; e.g., given `enum E { A = 1, B = 2, C = 4, };`, `E`'s range is `0..7`. This prevents arbitrary assignment, but is explicitly designed to not affect "bitflag" enums.) – Justin Time - Reinstate Monica Sep 25 '19 at 17:49
  • You could also write the numbers as binary literals to make it more clear that it is a flag. – pooya13 Dec 10 '20 at 00:32
  • 1
    Since C++11 there is std::underlying_type, which is a nice solution for the "if the enum range exceeds int range" problem and thus allows you to generalize the problem (e.g. build a macro to automatically implement all of them. – Thalhammer Mar 07 '21 at 12:58
  • 2
    This seems like a bad idea. Eventually someone is going to write an "exhaustive" `switch` for this, and the compiler won't warn you about the fact that you haven't checked for `HasClaws | CanFly` etc. – Timmmm Oct 07 '21 at 12:03
164

Note (also a bit off topic): Another way to make unique flags can be done using a bit shift. I, myself, find this easier to read.

enum Flags
{
    A = 1 << 0, // binary 0001
    B = 1 << 1, // binary 0010
    C = 1 << 2, // binary 0100
    D = 1 << 3  // binary 1000
};

It can hold values up to an int so that is, most of the time, 32 flags which is clearly reflected in the shift amount.

SebastianK
  • 3,582
  • 3
  • 30
  • 48
WoutervD
  • 2,139
  • 2
  • 13
  • 13
  • How is that not equivalent to simply using 1, 2, 4 and 8? – Karu Apr 23 '12 at 23:35
  • 8
    Could you please delete the last comma (3,) and add a colon after } to make the code easy to copy and paste? Thanks – Katu Apr 08 '14 at 07:55
  • 15
    No mention of hexidecimal? Blasphemy! – Pharap Aug 24 '14 at 09:40
  • @Michael, programmers tend to use zero-indexed numbers, so wouldn't it be 1? 0 == don't understand, 1 == understand Why waste a bit on programmers who don't understand binary? – Jamie Jul 07 '15 at 17:46
  • 1
    @Jamie, cardinals always start with 1, only ordinals may start with 0 or 1, depending on who you are talking to. – Michael Jul 07 '15 at 19:51
  • 4
    @Michael, that's true! In an enum, you usually reserve 0 for BLAH_NONE. :-) Thanks for jarring that memory! – Jamie Jul 08 '15 at 00:16
  • 1
    Also a very good way to avoid accidentally overlapping bits between flags if you're not totally up to speed on your powers of two :) – Steazy Aug 06 '16 at 01:37
  • 1
    `enum Foo { A, B, C, D=C*2, E=D*2 }` is also equivalent, but probably not a very good way to do it? – bur Nov 09 '18 at 17:17
  • 7
    @Katu • the superfluous comma on the final enumeration is allowed by the standard. I don't like it, but I already know what Stroustrup would tell me... "You don't like it? Well feel free to create your own language. I did." – Eljay Feb 01 '19 at 20:36
  • @Eljay - that is useful to know (I didn't) and is useful if you later `//` comment out an option (though only if you do not store the composite value beyond the lifetime of a single application run!!!) - can you give a reference for that as I feel sure I have come across an odd (maybe older C++## standard) compiler that didn't like it... – SlySven Apr 05 '20 at 18:53
  • @SlySven • You can see the optional trailing comma here: [dcl.enum](http://eel.is/c++draft/dcl.enum). The HTML was generated from the working draft. – Eljay Apr 05 '20 at 19:29
  • Of course that does not solve the question regarding OR-ing flags. – Daniel K. Feb 10 '22 at 14:17
  • 1
    You could also write `A = 0b0001, B = 0b0010, C = 0b0100, D = 0b1000`. This would be even easier. – Arkadii Apr 10 '23 at 21:26
77

Note if you are working in Windows environment, there is a DEFINE_ENUM_FLAG_OPERATORS macro defined in winnt.h that does the job for you. So in this case, you can do this:

enum AnimalFlags
{
    HasClaws = 1,
    CanFly =2,
    EatsFish = 4,
    Endangered = 8
};
DEFINE_ENUM_FLAG_OPERATORS(AnimalFlags)

seahawk.flags = CanFly | EatsFish | Endangered;
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • 11
    It's worth mentioning that `DEFINE_ENUM_FLAG_OPERATORS` macro also works for C++11 `enum class` macros, providing a full solution to typed flags. – rodrigocfd Oct 22 '20 at 02:50
66

For lazy people like me, here is templated solution to copy&paste:

template<class T> inline T operator~ (T a) { return (T)~(int)a; }
template<class T> inline T operator| (T a, T b) { return (T)((int)a | (int)b); }
template<class T> inline T operator& (T a, T b) { return (T)((int)a & (int)b); }
template<class T> inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); }
template<class T> inline T& operator|= (T& a, T b) { return (T&)((int&)a |= (int)b); }
template<class T> inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); }
template<class T> inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); }
user720594
  • 1,022
  • 8
  • 8
  • 17
    This is a very nice solution, just be careful that it will merrily provide bitwise operations for any type. I am using something similar, but with the addition of traits identifying the types to which I want it to apply combined with a little enable_if magic. – Rai Oct 28 '14 at 10:32
  • @Rai: you can always put it in a namespace and `using` it where appropriate, just like `rel_ops`. – Yakov Galka Apr 10 '16 at 16:57
  • 1
    @ybungalobill, but you'll still have the same problem with the operations applying to any type in the using's scope, which presumably would match the enum? I think traits are most likely necessary. – Rai Apr 10 '16 at 19:08
  • 46
    Don't use this code. It opens the door for ANY class to be operated by mistake. Also code is using old style cast which will not pass through GCC strict compilation http://shitalshah.com/p/how-to-enable-and-use-gcc-strict-mode-compilation/. – Shital Shah May 30 '16 at 08:54
  • 1
    Yeah, don't use this code. I'm pretty sure that the casting to int is undefined behaviour when the enum value is not as large as an int or truncation of a value when the enum value is larger than an int. – Brad Spencer Oct 10 '17 at 15:32
  • Not laziness but efficiency. Sometimes also efficacy. Why repeat yourself when you could include it in a DRY manner. – mwpowellhtx Nov 09 '18 at 20:29
  • Why not to use macro instead? In the way ``#define MAKE_ENUM_FLAGGED(EnumT, UnderNumT) \ inline EnumT operator~ (EnumT a) { return (EnumT)~(UnderNumT)a; } \ ...`` – master_clown May 07 '19 at 21:58
  • 4
    Note that this should use `std::underlying_type` instead of `int`, unless it's guaranteed to always be used with `enum class`es that don't specify an underlying type (`enum class` defaults to `int` for its underlying type, normal `enum` defaults to "whatever works, but it's _probably_ `int` unless the enumerators are too big for `int`"). – Justin Time - Reinstate Monica Sep 25 '19 at 17:57
  • 6
    You can use SFINAE `enable_if` with `is_enum` to enable these operators only on enums. – Calmarius Nov 28 '19 at 15:35
  • 1
    Note: This (implicitly) uses `reinterpret_cast` to convert `SomeEnum&` to `SomeInt&` [which is forbidden in standard C++](https://stackoverflow.com/questions/19476818/is-it-safe-to-reinterpret-cast-an-enum-class-variable-to-a-reference-of-the-unde), so check if your target compiler supports it before use. – c z Jul 22 '20 at 09:21
  • This is a good start. Combine this operator set with WebDancer's robust implementation partial in a header file. – Alan Baljeu Aug 20 '20 at 16:28
49

What type is the seahawk.flags variable?

In standard C++, enumerations are not type-safe. They are effectively integers.

AnimalFlags should NOT be the type of your variable. Your variable should be int and the error will go away.

Putting hexadecimal values like some other people suggested is not needed. It makes no difference.

The enum values ARE of type int by default. So you can surely bitwise OR combine them and put them together and store the result in an int.

The enum type is a restricted subset of int whose value is one of its enumerated values. Hence, when you make some new value outside of that range, you can't assign it without casting to a variable of your enum type.

You can also change the enum value types if you'd like, but there is no point for this question.

EDIT: The poster said they were concerned with type safety and they don't want a value that should not exist inside the int type.

But it would be type unsafe to put a value outside of AnimalFlags's range inside a variable of type AnimalFlags.

There is a safe way to check for out of range values though inside the int type...

int iFlags = HasClaws | CanFly;
//InvalidAnimalFlagMaxValue-1 gives you a value of all the bits 
// smaller than itself set to 1
//This check makes sure that no other bits are set.
assert(iFlags & ~(InvalidAnimalFlagMaxValue-1) == 0);

enum AnimalFlags {
    HasClaws = 1,
    CanFly =2,
    EatsFish = 4,
    Endangered = 8,

    // put new enum values above here
    InvalidAnimalFlagMaxValue = 16
};

The above doesn't stop you from putting an invalid flag from a different enum that has the value 1,2,4, or 8 though.

If you want absolute type safety then you could simply create a std::set and store each flag inside there. It is not space efficient, but it is type safe and gives you the same ability as a bitflag int does.

C++0x note: Strongly typed enums

In C++0x you can finally have type safe enum values....

enum class AnimalFlags {
    CanFly = 2,
    HasClaws = 4
};

if(CanFly == 2) { }//Compiling error
Nick Brown
  • 120
  • 6
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 5
    The enum values aren't integers, but they very easily convert to integers. The type of `HasClaws | CanFly` is some integer type, but the type of `HasClaws` is `AnimalFlags`, not an integer type. – Karu Apr 23 '12 at 23:33
  • 1
    Ah, but what if we define the correct range of the enum to be not just the individual flag values but also their bitwise combinations. Then eidolon's answer is correct, and maintains that only combinations of the correct flag enum can be passed as that type. – Scott Aug 12 '13 at 02:40
  • 3
    @Scott: It's worth noting that that the C++ standard defines the valid range of values of an enum instance that way. "for an enumeration where emin is the smallest enumerator and emax is the largest, the values of the enumeration are the values in the range bmin to bmax , defined as follows: Let K be 1 for a two’s complement representation and 0 for a ones’ complement or sign-magnitude representation. bmax is the smallest value greater than or equal to `max(|emin| − K, |emax|)` and equal to `(1u< – Ben Voigt Jun 24 '16 at 18:23
  • For those who (like me) just want something practical that allows enum values to be bitwise manipulated and doesn't look too ugly with templates and type casting, this is a good solution; just define variables to be type `int`. – Eric Sokolowsky Jan 24 '19 at 15:37
  • Also note that in C++, regular `enum` doesn't technically default to `int` as its underlying type (either pre-C++11 (IIRC), or post-C++11 when no underlying type is specified), although `enum class` _does_. Instead, the underlying type defaults to something large enough to represent all the enumerators, with the only real hard rule that it's only larger than `int` if it explicitly _needs_ to be. Basically, the underlying type is specified as (paraphrased) "whatever works, but it's _probably_ `int` unless the enumerators are too big for `int`". – Justin Time - Reinstate Monica Sep 25 '19 at 18:02
36

I find the currently accepted answer by eidolon too dangerous. The compiler's optimizer might make assumptions about possible values in the enum and you might get garbage back with invalid values. And usually nobody wants to define all possible permutations in flags enums.

As Brian R. Bondy states below, if you're using C++11 (which everyone should, it's that good) you can now do this more easily with enum class:

enum class ObjectType : uint32_t
{
    ANIMAL = (1 << 0),
    VEGETABLE = (1 << 1),
    MINERAL = (1 << 2)
};


constexpr enum ObjectType operator |( const enum ObjectType selfValue, const enum ObjectType inValue )
{
    return (enum ObjectType)(uint32_t(selfValue) | uint32_t(inValue));
}

// ... add more operators here. 

This ensures a stable size and value range by specifying a type for the enum, inhibits automatic downcasting of enums to ints etc. by using enum class, and uses constexpr to ensure the code for the operators gets inlined and thus just as fast as regular numbers.

For people stuck with pre-11 C++ dialects

If I was stuck with a compiler that doesn't support C++11, I'd go with wrapping an int-type in a class that then permits only use of bitwise operators and the types from that enum to set its values:

template<class ENUM,class UNDERLYING=typename std::underlying_type<ENUM>::type>
class SafeEnum
{
public:
    SafeEnum() : mFlags(0) {}
    SafeEnum( ENUM singleFlag ) : mFlags(singleFlag) {}
    SafeEnum( const SafeEnum& original ) : mFlags(original.mFlags) {}

    SafeEnum&   operator |=( ENUM addValue )    { mFlags |= addValue; return *this; }
    SafeEnum    operator |( ENUM addValue )     { SafeEnum  result(*this); result |= addValue; return result; }
    SafeEnum&   operator &=( ENUM maskValue )   { mFlags &= maskValue; return *this; }
    SafeEnum    operator &( ENUM maskValue )    { SafeEnum  result(*this); result &= maskValue; return result; }
    SafeEnum    operator ~()    { SafeEnum  result(*this); result.mFlags = ~result.mFlags; return result; }
    explicit operator bool()                    { return mFlags != 0; }

protected:
    UNDERLYING  mFlags;
};

You can define this pretty much like a regular enum + typedef:

enum TFlags_
{
    EFlagsNone  = 0,
    EFlagOne    = (1 << 0),
    EFlagTwo    = (1 << 1),
    EFlagThree  = (1 << 2),
    EFlagFour   = (1 << 3)
};

typedef SafeEnum<enum TFlags_>  TFlags;

And usage is similar as well:

TFlags      myFlags;

myFlags |= EFlagTwo;
myFlags |= EFlagThree;

if( myFlags & EFlagTwo )
    std::cout << "flag 2 is set" << std::endl;
if( (myFlags & EFlagFour) == EFlagsNone )
    std::cout << "flag 4 is not set" << std::endl;

And you can also override the underlying type for binary-stable enums (like C++11's enum foo : type) using the second template parameter, i.e. typedef SafeEnum<enum TFlags_,uint8_t> TFlags;.

I marked the operator bool override with C++11's explicit keyword to prevent it from resulting in int conversions, as those could cause sets of flags to end up collapsed into 0 or 1 when writing them out. If you can't use C++11, leave that overload out and rewrite the first conditional in the example usage as (myFlags & EFlagTwo) == EFlagTwo.

uliwitness
  • 8,532
  • 36
  • 58
  • 1
    As a note, I would recommend that the example operator defined at the start use `std::underlying_type` instead of hard-coding a specific type, or that the underlying type be provided and used as a type alias instead of directly. That way, changes to the underlying type will propagate automagically, instead of having to be done manually. – Justin Time - Reinstate Monica Sep 25 '19 at 18:07
  • 1
    The standard doesn't allow "The compiler's optimizer [to] make assumptions about possible values in the enum" – Clément Aug 07 '20 at 16:07
  • Curious about the repetition of the "enum" keyword in the C++11 example of the overloaded operator. Is this functionally different than `constexpr ObjectType operator |( const ObjectType selfValue, const ObjectType inValue )` (which seems to compile just fine)? – jrr Dec 30 '20 at 19:07
  • Doesn't make a difference for the purposes in this case. Just a habit I picked up because some of our headers are shared between C and C++, and `enum` in C doesn't implicitly create a typedef for the `enum` like `enum` and `class` in C++ do, so there you _need_ the `enum`, – uliwitness Jan 08 '21 at 11:40
20

Easiest way to do this as shown here, using the standard library class bitset.

To emulate the C# feature in a type-safe way, you'd have to write a template wrapper around the bitset, replacing the int arguments with an enum given as a type parameter to the template. Something like:

    template <class T, int N>
class FlagSet
{

    bitset<N> bits;

    FlagSet(T enumVal)
    {
        bits.set(enumVal);
    }

    // etc.
};

enum MyFlags
{
    FLAG_ONE,
    FLAG_TWO
};

FlagSet<MyFlags, 2> myFlag;
soru
  • 5,464
  • 26
  • 30
  • 4
    Look at this for more complete code: http://codereview.stackexchange.com/questions/96146/c-flagset-typesafe-usage-of-enumeration-as-bitset-bitmask – Shital Shah May 30 '16 at 09:13
16

In my opinion none of the answers so far are ideal. To be ideal I would expect the solution:

  1. Support the ==,!=,=,&,&=,|,|= and ~ operators in the conventional sense (i.e. a & b)
  2. Be type safe i.e. not permit non-enumerated values such as literals or integer types to be assigned (except for bitwise combinations of enumerated values) or allow an enum variable to be assigned to an integer type
  3. Permit expressions such as if (a & b)...
  4. Not require evil macros, implementation specific features or other hacks

Most of the solutions thus far fall over on points 2 or 3. WebDancer's is the closes in my opinion but fails at point 3 and needs to be repeated for every enum.

My proposed solution is a generalized version of WebDancer's that also addresses point 3:

#include <cstdint>
#include <type_traits>

template<typename T, typename = typename std::enable_if<std::is_enum<T>::value, T>::type>
class auto_bool
{
    T val_;
public:
    constexpr auto_bool(T val) : val_(val) {}
    constexpr operator T() const { return val_; }
    constexpr explicit operator bool() const
    {
        return static_cast<std::underlying_type_t<T>>(val_) != 0;
    }
};

template <typename T, typename = typename std::enable_if<std::is_enum<T>::value, T>::type>
constexpr auto_bool<T> operator&(T lhs, T rhs)
{
    return static_cast<T>(
        static_cast<typename std::underlying_type<T>::type>(lhs) &
        static_cast<typename std::underlying_type<T>::type>(rhs));
}

template <typename T, typename = typename std::enable_if<std::is_enum<T>::value, T>::type>
constexpr T operator|(T lhs, T rhs)
{
    return static_cast<T>(
        static_cast<typename std::underlying_type<T>::type>(lhs) |
        static_cast<typename std::underlying_type<T>::type>(rhs));
}

enum class AnimalFlags : uint8_t 
{
    HasClaws = 1,
    CanFly = 2,
    EatsFish = 4,
    Endangered = 8
};

enum class PlantFlags : uint8_t
{
    HasLeaves = 1,
    HasFlowers = 2,
    HasFruit = 4,
    HasThorns = 8
};

int main()
{
    AnimalFlags seahawk = AnimalFlags::CanFly;        // Compiles, as expected
    AnimalFlags lion = AnimalFlags::HasClaws;         // Compiles, as expected
    PlantFlags rose = PlantFlags::HasFlowers;         // Compiles, as expected
//  rose = 1;                                         // Won't compile, as expected
    if (seahawk != lion) {}                           // Compiles, as expected
//  if (seahawk == rose) {}                           // Won't compile, as expected
//  seahawk = PlantFlags::HasThorns;                  // Won't compile, as expected
    seahawk = seahawk | AnimalFlags::EatsFish;        // Compiles, as expected
    lion = AnimalFlags::HasClaws |                    // Compiles, as expected
           AnimalFlags::Endangered;
//  int eagle = AnimalFlags::CanFly |                 // Won't compile, as expected
//              AnimalFlags::HasClaws;
//  int has_claws = seahawk & AnimalFlags::CanFly;    // Won't compile, as expected
    if (seahawk & AnimalFlags::CanFly) {}             // Compiles, as expected
    seahawk = seahawk & AnimalFlags::CanFly;          // Compiles, as expected

    return 0;
}

This creates overloads of the necessary operators but uses SFINAE to limit them to enumerated types. Note that in the interests of brevity I haven't defined all of the operators but the only one that is any different is the &. The operators are currently global (i.e. apply to all enumerated types) but this could be reduced either by placing the overloads in a namespace (what I do), or by adding additional SFINAE conditions (perhaps using particular underlying types, or specially created type aliases). The underlying_type_t is a C++14 feature but it seems to be well supported and is easy to emulate for C++11 with a simple template<typename T> using underlying_type_t = underlying_type<T>::type;

Edit: I incorporated the change suggested by Vladimir Afinello. Tested with GCC 10, CLANG 13 and Visual Studio 2022.

Trevor
  • 311
  • 2
  • 6
  • While your proposed solution works great, it also introduces this pattern for enums that are not meant to be treated as flags. That is probably the reason for the use of (evil) macros like DEFINE_ENUM_FLAG_OPERATORS from Microsoft. – WebDancer Mar 15 '18 at 13:10
  • @WebDancer, you are of course correct, but then I already said that in my answer. I also suggested two ways of addressing the issue -- putting it in a namespace or using a more restrictive SFINAE condition. – Trevor Mar 16 '18 at 18:45
  • My point is unless you make a _really_ narrow namespace (e.g. namespace AllMyFlagEnums) or have a SFINAE condition that in some way selects only a few exact enums the code is broken in my mind. Rather than risking this, I copy&paste a "textual template" where I just replace then enum name, and sometimes the "evil" macros. I wish there was a better way. – WebDancer Mar 19 '18 at 08:51
  • Firstly, it will only cause a problem if elsewhere in your code you need to do one of the things it is intended to stop e.g. assign a literal, integer or an element from another enum. Otherwise the modified enum behaves like a regular enum e.g. the elements do not necessarily need to be powers of two and assignment, comparison and bitwise operations work as normal. If you really must assign literals or mix enums you can still explicitly cast, with the added advantage that your intent will be clearer. So chances are there wouldn't be a need to reduce the scope. – Trevor Mar 19 '18 at 10:51
  • Secondly, if even if you do need to reduce the scope, the namespace may not need to be narrow - although that will depend on what you are doing. If you are working on a library then perhaps you already have your code that depends on the enums in a namespace, then the enum code just goes in the same namespace. If you require the enum behavior for a class (perhaps you want to use the enums as method arguments or member variables of the class) then put the enum code in the class for the same effect. Bottom line is you don't need to wrap a namespace around just the enums - although you could. – Trevor Mar 19 '18 at 11:01
  • Using a namespace was just an example on how to easily reduce the scope properly, but maybe not a real solution for most. My point is that we do want and need to reduce the scope such that ONLY the flag enums actually get the added functionality. We do have enums that looks like flags (i.e. power of two values only) but which should not be used as such. We have found and fixed numerous bugs in our applications by changing the enums to be really strict about this, and probably prevented many more. – WebDancer Mar 20 '18 at 09:23
  • 1
    I've been using your approach for years until I recently realized it doesn't work with GCC. Should be written like that: template::value, T>::type> – Vladimir Afinello Oct 16 '22 at 12:29
  • @VladimirAfinello is correct. Answer updated. – Trevor Oct 17 '22 at 13:43
  • |= does not compile. ex. lion |= AnimalFlags::Endangered; – Josh Sanders Feb 23 '23 at 20:36
13

Only syntactic sugar. No additional metadata.

namespace UserRole // grupy
{ 
    constexpr uint8_t dea = 1;
    constexpr uint8_t red = 2;
    constexpr uint8_t stu = 4;
    constexpr uint8_t kie = 8;
    constexpr uint8_t adm = 16;
    constexpr uint8_t mas = 32;
}

Flag operators on integral type just works.

vSzemkel
  • 624
  • 5
  • 11
  • 2
    IMHO this is the best answer. Clean and simple, easy client syntax. I would just use "constexpr int" rather than "constexpr uint8_t", but the concept is the same. – yoyo May 23 '19 at 18:17
  • That takes care of namespace pollution, but you've lost strong typing for `UserRole`. – Robin Davies Jun 02 '23 at 13:07
12

The C++ standard explicitly talks about this, see section "17.5.2.1.3 Bitmask types":

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf

Given this "template" you get:

enum AnimalFlags : unsigned int
{
    HasClaws = 1,
    CanFly = 2,
    EatsFish = 4,
    Endangered = 8
};

constexpr AnimalFlags operator|(AnimalFlags X, AnimalFlags Y) {
    return static_cast<AnimalFlags>(
        static_cast<unsigned int>(X) | static_cast<unsigned int>(Y));
}

AnimalFlags& operator|=(AnimalFlags& X, AnimalFlags Y) {
    X = X | Y; return X;
}

And similar for the other operators. Also note the "constexpr", it is needed if you want the compiler to be able to execute the operators compile time.

If you are using C++/CLI and want to able assign to enum members of ref classes you need to use tracking references instead:

AnimalFlags% operator|=(AnimalFlags% X, AnimalFlags Y) {
    X = X | Y; return X;
}

NOTE: This sample is not complete, see section "17.5.2.1.3 Bitmask types" for a complete set of operators.

WebDancer
  • 333
  • 3
  • 8
7

I use the following macro:

#define ENUM_FLAG_OPERATORS(T)                                                                                                                                            \
    inline T operator~ (T a) { return static_cast<T>( ~static_cast<std::underlying_type<T>::type>(a) ); }                                                                       \
    inline T operator| (T a, T b) { return static_cast<T>( static_cast<std::underlying_type<T>::type>(a) | static_cast<std::underlying_type<T>::type>(b) ); }                   \
    inline T operator& (T a, T b) { return static_cast<T>( static_cast<std::underlying_type<T>::type>(a) & static_cast<std::underlying_type<T>::type>(b) ); }                   \
    inline T operator^ (T a, T b) { return static_cast<T>( static_cast<std::underlying_type<T>::type>(a) ^ static_cast<std::underlying_type<T>::type>(b) ); }                   \
    inline T& operator|= (T& a, T b) { return reinterpret_cast<T&>( reinterpret_cast<std::underlying_type<T>::type&>(a) |= static_cast<std::underlying_type<T>::type>(b) ); }   \
    inline T& operator&= (T& a, T b) { return reinterpret_cast<T&>( reinterpret_cast<std::underlying_type<T>::type&>(a) &= static_cast<std::underlying_type<T>::type>(b) ); }   \
    inline T& operator^= (T& a, T b) { return reinterpret_cast<T&>( reinterpret_cast<std::underlying_type<T>::type&>(a) ^= static_cast<std::underlying_type<T>::type>(b) ); }

It is similar to the ones mentioned above but has several improvements:

  • It is type safe (it does not suppose that the underlying type is an int)
  • It does not require to specify manually the underlying type (as opposed to @LunarEclipse 's answer)

It does need to include type_traits:

#include <type_traits>
oierlauzi
  • 167
  • 2
  • 7
  • Note: As per my comment above, `reinterpret_cast(INT&)` [is forbidden in standard C++](https://stackoverflow.com/questions/19476818/is-it-safe-to-reinterpret-cast-an-enum-class-variable-to-a-reference-of-the-unde), so check if your target compiler supports it before use. – c z Jul 22 '20 at 09:24
6

I found myself asking the same question and came up with a generic C++11 based solution, similar to soru's:

template <typename TENUM>
class FlagSet {

private:
    using TUNDER = typename std::underlying_type<TENUM>::type;
    std::bitset<std::numeric_limits<TUNDER>::max()> m_flags;

public:
    FlagSet() = default;

    template <typename... ARGS>
    FlagSet(TENUM f, ARGS... args) : FlagSet(args...)
    {   
        set(f);
    }   
    FlagSet& set(TENUM f)
    {   
        m_flags.set(static_cast<TUNDER>(f));
        return *this;
    }   
    bool test(TENUM f)
    {   
        return m_flags.test(static_cast<TUNDER>(f));
    }   
    FlagSet& operator|=(TENUM f)
    {   
        return set(f);
    }   
};

The interface can be improved to taste. Then it can be used like so:

FlagSet<Flags> flags{Flags::FLAG_A, Flags::FLAG_C};
flags |= Flags::FLAG_D;
Omair
  • 814
  • 1
  • 10
  • 19
  • 2
    Look at this for better and more complete code: http://codereview.stackexchange.com/questions/96146/c-flagset-typesafe-usage-of-enumeration-as-bitset-bitmask – Shital Shah May 30 '16 at 09:12
  • 5
    Except for my use of numeric_limits, the code is almost the same. I guess it is a common way to have a type-safe enum class. I would argue that using numeric_limits is better than putting a SENTINEL at the end of every enum. – Omair May 30 '16 at 10:30
  • 1
    That's a _huge_ bitset! (potentially...) – Lightness Races in Orbit Dec 12 '19 at 12:40
5

If your compiler doesn't support strongly typed enums yet, you can give a look to the following article from the c++ source:

From the abstract:

This article presents a solution to the problem of constraining bit operations to
allow only safe and legitimate ones, and turn all invalid bit manipulations into compile-time errors. Best of all, the syntax of bit operations remains unchanged, and the code working with bits does not need to be modified, except possibly to fix errors that had as yet remained undetected.

orlp
  • 112,504
  • 36
  • 218
  • 315
Francesco
  • 3,200
  • 1
  • 34
  • 46
4

Here's an option for bitmasks if you don't actually have a use for the individual enum values (ex. you don't need to switch off of them)... and if you aren't worried about maintaining binary compatibility ie: you don't care where your bits live... which you probably are. Also you'd better not be too concerned with scoping and access control. Hmmm, enums have some nice properties for bit-fields... wonder if anyone has ever tried that :)

struct AnimalProperties
{
    bool HasClaws : 1;
    bool CanFly : 1;
    bool EatsFish : 1;
    bool Endangered : 1;
};

union AnimalDescription
{
    AnimalProperties Properties;
    int Flags;
};

void TestUnionFlags()
{
    AnimalDescription propertiesA;
    propertiesA.Properties.CanFly = true;

    AnimalDescription propertiesB = propertiesA;
    propertiesB.Properties.EatsFish = true;

    if( propertiesA.Flags == propertiesB.Flags )
    {
        cout << "Life is terrible :(";
    }
    else
    {
        cout << "Life is great!";
    }

    AnimalDescription propertiesC = propertiesA;
    if( propertiesA.Flags == propertiesC.Flags )
    {
        cout << "Life is great!";
    }
    else
    {
        cout << "Life is terrible :(";
    }
}

We can see that life is great, we have our discrete values, and we have a nice int to & and | to our hearts content, which still has context of what its bits mean. Everything is consistent and predictable... for me... as long as I keep using Microsoft's VC++ compiler w/ Update 3 on Win10 x64 and don't touch my compiler flags :)

Even though everything is great... we have some context as to the meaning of flags now, since its in a union w/ the bitfield in the terrible real world where your program may be be responsible for more than a single discrete task you could still accidentally (quite easily) smash two flags fields of different unions together (say, AnimalProperties and ObjectProperties, since they're both ints), mixing up all yours bits, which is a horrible bug to trace down... and how I know many people on this post don't work with bitmasks very often, since building them is easy and maintaining them is hard.

class AnimalDefinition {
public:
    static AnimalDefinition *GetAnimalDefinition( AnimalFlags flags );   //A little too obvious for my taste... NEXT!
    static AnimalDefinition *GetAnimalDefinition( AnimalProperties properties );   //Oh I see how to use this! BORING, NEXT!
    static AnimalDefinition *GetAnimalDefinition( int flags ); //hmm, wish I could see how to construct a valid "flags" int without CrossFingers+Ctrl+Shift+F("Animal*"). Maybe just hard-code 16 or something?

    AnimalFlags animalFlags;  //Well this is *way* too hard to break unintentionally, screw this!
    int flags; //PERFECT! Nothing will ever go wrong here... 
    //wait, what values are used for this particular flags field? Is this AnimalFlags or ObjectFlags? Or is it RuntimePlatformFlags? Does it matter? Where's the documentation? 
    //Well luckily anyone in the code base and get confused and destroy the whole program! At least I don't need to static_cast anymore, phew!

    private:
    AnimalDescription m_description; //Oh I know what this is. All of the mystery and excitement of life has been stolen away :(
}

So then you make your union declaration private to prevent direct access to "Flags", and have to add getters/setters and operator overloads, then make a macro for all that, and you're basically right back where you started when you tried to do this with an Enum.

Unfortunately if you want your code to be portable, I don't think there is any way to either A) guarantee the bit layout or B) determine the bit layout at compile time (so you can track it and at least correct for changes across versions/platforms etc) Offset in a struct with bit fields

At runtime you can play tricks w/ setting the the fields and XORing the flags to see which bits did change, sounds pretty crappy to me though verses having a 100% consistent, platform independent, and completely deterministic solution ie: an ENUM.

TL;DR: Don't listen to the haters. C++ is not English. Just because the literal definition of an abbreviated keyword inherited from C might not fit your usage doesn't mean you shouldn't use it when the C and C++ definition of the keyword absolutely includes your use case. You can also use structs to model things other than structures, and classes for things other than school and social caste. You may use float for values which are grounded. You may use char for variables which are neither un-burnt nor a person in a novel, play, or movie. Any programmer who goes to the dictionary to determine the meaning of a keyword before the language spec is a... well I'll hold my tongue there.

If you do want your code modeled after spoken language you'd be best off writing in Objective-C, which incidentally also uses enums heavily for bitfields.

Community
  • 1
  • 1
Steazy
  • 383
  • 3
  • 12
4

I'd like to elaborate on Uliwitness answer, fixing his code for C++98 and using the Safe Bool idiom, for lack of the std::underlying_type<> template and the explicit keyword in C++ versions below C++11.

I also modified it so that the enum values can be sequential without any explicit assignment, so you can have

enum AnimalFlags_
{
    HasClaws,
    CanFly,
    EatsFish,
    Endangered
};
typedef FlagsEnum<AnimalFlags_> AnimalFlags;

seahawk.flags = AnimalFlags() | CanFly | EatsFish | Endangered;

You can then get the raw flags value with

seahawk.flags.value();

Here's the code.

template <typename EnumType, typename Underlying = int>
class FlagsEnum
{
    typedef Underlying FlagsEnum::* RestrictedBool;

public:
    FlagsEnum() : m_flags(Underlying()) {}

    FlagsEnum(EnumType singleFlag):
        m_flags(1 << singleFlag)
    {}

    FlagsEnum(const FlagsEnum& original):
        m_flags(original.m_flags)
    {}

    FlagsEnum& operator |=(const FlagsEnum& f) {
        m_flags |= f.m_flags;
        return *this;
    }

    FlagsEnum& operator &=(const FlagsEnum& f) {
        m_flags &= f.m_flags;
        return *this;
    }

    friend FlagsEnum operator |(const FlagsEnum& f1, const FlagsEnum& f2) {
        return FlagsEnum(f1) |= f2;
    }

    friend FlagsEnum operator &(const FlagsEnum& f1, const FlagsEnum& f2) {
        return FlagsEnum(f1) &= f2;
    }

    FlagsEnum operator ~() const {
        FlagsEnum result(*this);
        result.m_flags = ~result.m_flags;
        return result;
    }

    operator RestrictedBool() const {
        return m_flags ? &FlagsEnum::m_flags : 0;
    }

    Underlying value() const {
        return m_flags;
    }

protected:
    Underlying  m_flags;
};
Community
  • 1
  • 1
Fabio A.
  • 2,517
  • 26
  • 35
4

Currently there is no language support for enum flags, Meta classes might inherently add this feature if it would ever be part of the c++ standard.

My solution would be to create enum-only instantiated template functions adding support for type-safe bitwise operations for enum class using its underlying type:

File: EnumClassBitwise.h

#pragma once
#ifndef _ENUM_CLASS_BITWISE_H_
#define _ENUM_CLASS_BITWISE_H_

#include <type_traits>

//unary ~operator    
template <typename Enum, typename std::enable_if_t<std::is_enum<Enum>::value, int> = 0>
constexpr inline Enum& operator~ (Enum& val)
{
    val = static_cast<Enum>(~static_cast<std::underlying_type_t<Enum>>(val));
    return val;
}

// & operator
template <typename Enum, typename std::enable_if_t<std::is_enum<Enum>::value, int> = 0>
constexpr inline Enum operator& (Enum lhs, Enum rhs)
{
    return static_cast<Enum>(static_cast<std::underlying_type_t<Enum>>(lhs) & static_cast<std::underlying_type_t<Enum>>(rhs));
}

// &= operator
template <typename Enum, typename std::enable_if_t<std::is_enum<Enum>::value, int> = 0>
constexpr inline Enum operator&= (Enum& lhs, Enum rhs)
{
    lhs = static_cast<Enum>(static_cast<std::underlying_type_t<Enum>>(lhs) & static_cast<std::underlying_type_t<Enum>>(rhs));
    return lhs;
}

//| operator

template <typename Enum, typename std::enable_if_t<std::is_enum<Enum>::value, int> = 0>
constexpr inline Enum operator| (Enum lhs, Enum rhs)
{
    return static_cast<Enum>(static_cast<std::underlying_type_t<Enum>>(lhs) | static_cast<std::underlying_type_t<Enum>>(rhs));
}
//|= operator

template <typename Enum, typename std::enable_if_t<std::is_enum<Enum>::value, int> = 0>
constexpr inline Enum& operator|= (Enum& lhs, Enum rhs)
{
    lhs = static_cast<Enum>(static_cast<std::underlying_type_t<Enum>>(lhs) | static_cast<std::underlying_type_t<Enum>>(rhs));
    return lhs;
}

#endif // _ENUM_CLASS_BITWISE_H_

For convenience and for reducing mistakes, you might want to wrap your bit flags operations for enums and for integers as well:

File: BitFlags.h

#pragma once
#ifndef _BIT_FLAGS_H_
#define _BIT_FLAGS_H_

#include "EnumClassBitwise.h"

 template<typename T>
 class BitFlags
 {
 public:

     constexpr inline BitFlags() = default;
     constexpr inline BitFlags(T value) { mValue = value; }
     constexpr inline BitFlags operator| (T rhs) const { return mValue | rhs; }
     constexpr inline BitFlags operator& (T rhs) const { return mValue & rhs; }
     constexpr inline BitFlags operator~ () const { return ~mValue; }
     constexpr inline operator T() const { return mValue; }
     constexpr inline BitFlags& operator|=(T rhs) { mValue |= rhs; return *this; }
     constexpr inline BitFlags& operator&=(T rhs) { mValue &= rhs; return *this; }
     constexpr inline bool test(T rhs) const { return (mValue & rhs) == rhs; }
     constexpr inline void set(T rhs) { mValue |= rhs; }
     constexpr inline void clear(T rhs) { mValue &= ~rhs; }

 private:
     T mValue;
 };
#endif //#define _BIT_FLAGS_H_

Possible usage:

#include <cstdint>
#include <BitFlags.h>
void main()
{
    enum class Options : uint32_t
    { 
          NoOption = 0 << 0
        , Option1  = 1 << 0
        , Option2  = 1 << 1
        , Option3  = 1 << 2
        , Option4  = 1 << 3
    };

    const uint32_t Option1 = 1 << 0;
    const uint32_t Option2 = 1 << 1;
    const uint32_t Option3 = 1 << 2;
    const uint32_t Option4 = 1 << 3;

   //Enum BitFlags
    BitFlags<Options> optionsEnum(Options::NoOption);
    optionsEnum.set(Options::Option1 | Options::Option3);

   //Standard integer BitFlags
    BitFlags<uint32_t> optionsUint32(0);
    optionsUint32.set(Option1 | Option3); 

    return 0;
}
Nicker
  • 61
  • 2
3

@Xaqq has provided a really nice type-safe way to use enum flags here by a flag_set class.

I published the code in GitHub, usage is as follows:

#include "flag_set.hpp"

enum class AnimalFlags : uint8_t {
    HAS_CLAWS,
    CAN_FLY,
    EATS_FISH,
    ENDANGERED,
    _
};

int main()
{
    flag_set<AnimalFlags> seahawkFlags(AnimalFlags::HAS_CLAWS
                                       | AnimalFlags::EATS_FISH
                                       | AnimalFlags::ENDANGERED);

    if (seahawkFlags & AnimalFlags::ENDANGERED)
        cout << "Seahawk is endangered";
}
mrts
  • 16,697
  • 8
  • 89
  • 72
3

Another macro solution, but unlike the existing answers this does not use reinterpret_cast (or a C-cast) to cast between Enum& and Int&, which is forbidden in standard C++ (see this post).

#define MAKE_FLAGS_ENUM(TEnum, TUnder)                                                                                             \
TEnum  operator~  ( TEnum  a          ) { return static_cast<TEnum> (~static_cast<TUnder> (a)                           ); }  \
TEnum  operator|  ( TEnum  a, TEnum b ) { return static_cast<TEnum> ( static_cast<TUnder> (a) |  static_cast<TUnder>(b) ); }  \
TEnum  operator&  ( TEnum  a, TEnum b ) { return static_cast<TEnum> ( static_cast<TUnder> (a) &  static_cast<TUnder>(b) ); }  \
TEnum  operator^  ( TEnum  a, TEnum b ) { return static_cast<TEnum> ( static_cast<TUnder> (a) ^  static_cast<TUnder>(b) ); }  \
TEnum& operator|= ( TEnum& a, TEnum b ) { a = static_cast<TEnum>(static_cast<TUnder>(a) | static_cast<TUnder>(b) ); return a; }  \
TEnum& operator&= ( TEnum& a, TEnum b ) { a = static_cast<TEnum>(static_cast<TUnder>(a) & static_cast<TUnder>(b) ); return a; }  \
TEnum& operator^= ( TEnum& a, TEnum b ) { a = static_cast<TEnum>(static_cast<TUnder>(a) ^ static_cast<TUnder>(b) ); return a; }

Losing the reinterpret_cast means we can't rely on the x |= y syntax any more, but by expanding these into their x = x | y forms we no longer need it.

Note: You can use std::underlying_type to obtain TUnder, I've not included it for brevity.

c z
  • 7,726
  • 3
  • 46
  • 59
3

Copy-pasteable "evil" macro based on some of the other answers in this thread:

#include <type_traits>

/*
 * Macro to allow enum values to be combined and evaluated as flags.
 *  * Based on:
 *  - DEFINE_ENUM_FLAG_OPERATORS from <winnt.h>
 *  - https://stackoverflow.com/a/63031334/1624459
 */
#define MAKE_ENUM_FLAGS(TEnum)                                                      \
    inline TEnum operator~(TEnum a) {                                               \
        using TUnder = typename std::underlying_type_t<TEnum>;                      \
        return static_cast<TEnum>(~static_cast<TUnder>(a));                         \
    }                                                                               \
    inline TEnum operator|(TEnum a, TEnum b) {                                      \
        using TUnder = typename std::underlying_type_t<TEnum>;                      \
        return static_cast<TEnum>(static_cast<TUnder>(a) | static_cast<TUnder>(b)); \
    }                                                                               \
    inline TEnum operator&(TEnum a, TEnum b) {                                      \
        using TUnder = typename std::underlying_type_t<TEnum>;                      \
        return static_cast<TEnum>(static_cast<TUnder>(a) & static_cast<TUnder>(b)); \
    }                                                                               \
    inline TEnum operator^(TEnum a, TEnum b) {                                      \
        using TUnder = typename std::underlying_type_t<TEnum>;                      \
        return static_cast<TEnum>(static_cast<TUnder>(a) ^ static_cast<TUnder>(b)); \
    }                                                                               \
    inline TEnum& operator|=(TEnum& a, TEnum b) {                                   \
        using TUnder = typename std::underlying_type_t<TEnum>;                      \
        a = static_cast<TEnum>(static_cast<TUnder>(a) | static_cast<TUnder>(b));    \
        return a;                                                                   \
    }                                                                               \
    inline TEnum& operator&=(TEnum& a, TEnum b) {                                   \
        using TUnder = typename std::underlying_type_t<TEnum>;                      \
        a = static_cast<TEnum>(static_cast<TUnder>(a) & static_cast<TUnder>(b));    \
        return a;                                                                   \
    }                                                                               \
    inline TEnum& operator^=(TEnum& a, TEnum b) {                                   \
        using TUnder = typename std::underlying_type_t<TEnum>;                      \
        a = static_cast<TEnum>(static_cast<TUnder>(a) ^ static_cast<TUnder>(b));    \
        return a;                                                                   \
    }

Usage

enum class Passability : std::uint8_t {
    Clear      = 0,
    GroundUnit = 1 << 1,
    FlyingUnit = 1 << 2,
    Building   = 1 << 3,
    Tree       = 1 << 4,
    Mountain   = 1 << 5,
    Blocked    = 1 << 6,
    Water      = 1 << 7,
    Coastline  = 1 << 8
};

MAKE_ENUM_FLAGS(Passability)

Advantages

  • Only applies to chosen enums when used explicitly.
  • No use of illegal reinterpret_cast.
  • No need to specify the underlying type.

Notes

  • Replace std::underlying_type_t<TEnum> with std::underlying_type<TEnum>::type if using C++ <14.
Dan
  • 1,198
  • 4
  • 17
  • 34
2

You are confusing objects and collections of objects. Specifically, you are confusing binary flags with sets of binary flags. A proper solution would look like this:

// These are individual flags
enum AnimalFlag // Flag, not Flags
{
    HasClaws = 0,
    CanFly,
    EatsFish,
    Endangered
};

class AnimalFlagSet
{
    int m_Flags;

  public:

    AnimalFlagSet() : m_Flags(0) { }

    void Set( AnimalFlag flag ) { m_Flags |= (1 << flag); }

    void Clear( AnimalFlag flag ) { m_Flags &= ~ (1 << flag); }

    bool Get( AnimalFlag flag ) const { return (m_Flags >> flag) & 1; }

};
Michael
  • 5,775
  • 2
  • 34
  • 53
2

Here is my solution without needing any bunch of overloading or casting:

namespace EFoobar
{
    enum
    {
        FB_A    = 0x1,
        FB_B    = 0x2,
        FB_C    = 0x4,
    };
    typedef long Flags;
}

void Foobar(EFoobar::Flags flags)
{
    if (flags & EFoobar::FB_A)
        // do sth
        ;
    if (flags & EFoobar::FB_B)
        // do sth
        ;
}

void ExampleUsage()
{
    Foobar(EFoobar::FB_A | EFoobar::FB_B);
    EFoobar::Flags otherflags = 0;
    otherflags|= EFoobar::FB_B;
    otherflags&= ~EFoobar::FB_B;
    Foobar(otherflags);
}

I think it's ok, because we identify (non strongly typed) enums and ints anyway.

Just as a (longer) side note, if you

  • want to use strongly typed enums and
  • don't need heavy bit fiddling with your flags
  • performance is not an issue

I would come up with this:

#include <set>

enum class EFoobarFlags
{
    FB_A = 1,
    FB_B,
    FB_C,
};

void Foobar(const std::set<EFoobarFlags>& flags)
{
    if (flags.find(EFoobarFlags::FB_A) != flags.end())
        // do sth
        ;
    if (flags.find(EFoobarFlags::FB_B) != flags.end())
        // do sth
        ;
}

void ExampleUsage()
{
    Foobar({EFoobarFlags::FB_A, EFoobarFlags::FB_B});
    std::set<EFoobarFlags> otherflags{};
    otherflags.insert(EFoobarFlags::FB_B);
    otherflags.erase(EFoobarFlags::FB_B);
    Foobar(otherflags);
}

using C++11 initializer lists and enum class.

yau
  • 537
  • 6
  • 14
  • By the way, I rather wouldn't recommend enums for flags at all. Simple reason: combinations of flags aren't elements of the enum again. So this seems quite unsuitable. Alternatively I would use a `using Flags = unsigned long` inside a namespace or struct containing the flag values themselves as `/*static*/ const Flags XY = 0x01` and so on. – yau Aug 10 '16 at 18:49
2

Here's a lazy C++11 solution that doesn't change the default behavior of enums. It also works for enum struct and enum class, and is constexpr.

#include <type_traits>

template<class T = void> struct enum_traits {};

template<> struct enum_traits<void> {
    struct _allow_bitops {
        static constexpr bool allow_bitops = true;
    };
    using allow_bitops = _allow_bitops;

    template<class T, class R = T>
    using t = typename std::enable_if<std::is_enum<T>::value and
        enum_traits<T>::allow_bitops, R>::type;

    template<class T>
    using u = typename std::underlying_type<T>::type;
};

template<class T>
constexpr enum_traits<>::t<T> operator~(T a) {
    return static_cast<T>(~static_cast<enum_traits<>::u<T>>(a));
}
template<class T>
constexpr enum_traits<>::t<T> operator|(T a, T b) {
    return static_cast<T>(
        static_cast<enum_traits<>::u<T>>(a) |
        static_cast<enum_traits<>::u<T>>(b));
}
template<class T>
constexpr enum_traits<>::t<T> operator&(T a, T b) {
    return static_cast<T>(
        static_cast<enum_traits<>::u<T>>(a) &
        static_cast<enum_traits<>::u<T>>(b));
}
template<class T>
constexpr enum_traits<>::t<T> operator^(T a, T b) {
    return static_cast<T>(
        static_cast<enum_traits<>::u<T>>(a) ^
        static_cast<enum_traits<>::u<T>>(b));
}
template<class T>
constexpr enum_traits<>::t<T, T&> operator|=(T& a, T b) {
    a = a | b;
    return a;
}
template<class T>
constexpr enum_traits<>::t<T, T&> operator&=(T& a, T b) {
    a = a & b;
    return a;
}
template<class T>
constexpr enum_traits<>::t<T, T&> operator^=(T& a, T b) {
    a = a ^ b;
    return a;
}

To enable bitwise operators for an enum:

enum class my_enum {
    Flag1 = 1 << 0,
    Flag2 = 1 << 1,
    Flag3 = 1 << 2,
    // ...
};

// The magic happens here
template<> struct enum_traits<my_enum> :
    enum_traits<>::allow_bitops {};

constexpr my_enum foo = my_enum::Flag1 | my_enum::Flag2 | my_enum::Flag3;
ShadowFan-X
  • 131
  • 1
  • 2
  • I like this solution, however it fails when one of those operators is manually overloaded within a namespace for another type, and within that very namespace the operators for the enum are attempted to be used: the manually defined overload within the namespace hides the globally defined ones, and therefore compilation will fail because of the arguments type mismatch. To be fair, this is a problem with any globally defined function that has to "fight for resolution" with a namespace-defined one. The only solution I see, is to define the bitops operators at the same level as the enums. – Fabio A. Nov 25 '21 at 12:18
2

C++20 Type-Safe Enum Operators

TL;DR

template<typename T>
requires std::is_enum_v<T> and
         requires (std::underlying_type_t<T> x) {
             { x | x } -> std::same_as<std::underlying_type_t<T>>;
             T(x);
         }
T operator|(T left, T right)
{
    using U = std::underlying_type_t<T>;
    return T( U(left) | U(right) );
}

template<typename T>
requires std::is_enum_v<T> and
         requires (std::underlying_type_t<T> x) {
             { x | x } -> std::same_as<std::underlying_type_t<T>>;
             T(x);
         }
T operator&(T left, T right)
{
    using U = std::underlying_type_t<T>;
    return T( U(left) & U(right) );
}

template<typename T>
requires std::is_enum_v<T> and requires (T x) { { x | x } -> std::same_as<T>; }
T & operator|=(T &left, T right)
{
    return left = left | right;
}

template<typename T>
requires std::is_enum_v<T> and requires (T x) { { x & x } -> std::same_as<T>; }
T & operator&=(T &left, T right)
{
    return left = left & right;
}

Rationale

With type trait std::is_enum we can test some type T for whether it is an enumeration type. This includes both unscoped and scoped enums (i.e. enum and enum class). With type trait std::underlying_type we can get the underlying type of an enum. With C++20 concepts and constraints it is quite easy to then provide overloads for bitwise operations.

Scoped vs. Unscoped

If the operations should only be overloaded for either scoped or unscoped enums, std::is_scoped_enum can be used to extend the template constraints accordingly.

C++23

With C++23 we get std::to_underlying to convert an enum value to its underlying type more easily.

Move Semantics & Perfect Forwarding

Should you get in the bizarre situation that your underlying type has different semantics for copy vs. move or it does not provide a copy c'tor, then you should do perfect forwarding of the operands with std::forward.

1

As above(Kai) or do the following. Really enums are "Enumerations", what you want to do is have a set, therefore you should really use stl::set

enum AnimalFlags
{
    HasClaws = 1,
    CanFly =2,
    EatsFish = 4,
    Endangered = 8
};

int main(void)
{
    AnimalFlags seahawk;
    //seahawk= CanFly | EatsFish | Endangered;
    seahawk= static_cast<AnimalFlags>(CanFly | EatsFish | Endangered);
}
Spacen Jasset
  • 938
  • 2
  • 11
  • 21
1

Maybe like NS_OPTIONS of Objective-C.

#define ENUM(T1, T2) \
enum class T1 : T2; \
inline T1 operator~ (T1 a) { return (T1)~(int)a; } \
inline T1 operator| (T1 a, T1 b) { return static_cast<T1>((static_cast<T2>(a) | static_cast<T2>(b))); } \
inline T1 operator& (T1 a, T1 b) { return static_cast<T1>((static_cast<T2>(a) & static_cast<T2>(b))); } \
inline T1 operator^ (T1 a, T1 b) { return static_cast<T1>((static_cast<T2>(a) ^ static_cast<T2>(b))); } \
inline T1& operator|= (T1& a, T1 b) { return reinterpret_cast<T1&>((reinterpret_cast<T2&>(a) |= static_cast<T2>(b))); } \
inline T1& operator&= (T1& a, T1 b) { return reinterpret_cast<T1&>((reinterpret_cast<T2&>(a) &= static_cast<T2>(b))); } \
inline T1& operator^= (T1& a, T1 b) { return reinterpret_cast<T1&>((reinterpret_cast<T2&>(a) ^= static_cast<T2>(b))); } \
enum class T1 : T2

ENUM(Options, short) {
    FIRST  = 1 << 0,
    SECOND = 1 << 1,
    THIRD  = 1 << 2,
    FOURTH = 1 << 3
};

auto options = Options::FIRST | Options::SECOND;
options |= Options::THIRD;
if ((options & Options::SECOND) == Options::SECOND)
    cout << "Contains second option." << endl;
if ((options & Options::THIRD) == Options::THIRD)
    cout << "Contains third option." << endl;
return 0;

// Output:
// Contains second option. 
// Contains third option.
  • Can you explain why your answer is the best fit? There are several other answers that have answered this question, so please include some information to differentiate yours. – trevorp Aug 31 '18 at 19:38
0
(int&)seahawk.flags = CanFly | EatsFish | Endangered;
  1. seahawk.flags is casted from enum AnimalFlags& to int&
  2. the result of CanFly | EatsFish | Endangered is int typed.
  3. the result of int is written to seahawk.flags as int&

Disclaimer: C++ enforces you not to do this way and write overloads for | operator. You should know what are you doing. Be the C++ your tool, not your jealous god.

OZone
  • 1
  • 1
  • Have you tested this solution? Can you explain what ` (int&)` is supposed to be doing here? Can casts be used on the left-hand-side of an assignment? – zkoza Mar 31 '21 at 22:42
  • Explain or at least point out bitwise OR – n-smits Apr 01 '21 at 01:06
  • @zkoza, have you? Yes, they can. Make yourself familiar with the l-value references and how do operators in C++ work. – OZone May 11 '23 at 21:07
0

You can use struct as follow:

struct UiFlags2 {
    static const int
    FULLSCREEN = 0x00000004,               //api 16
    HIDE_NAVIGATION = 0x00000002,          //api 14
    LAYOUT_HIDE_NAVIGATION = 0x00000200,   //api 16
    LAYOUT_FULLSCREEN = 0x00000400,        //api 16
    LAYOUT_STABLE = 0x00000100,            //api 16
    IMMERSIVE_STICKY = 0x00001000;         //api 19
};

and use as this:

int flags = UiFlags2::FULLSCREEN | UiFlags2::HIDE_NAVIGATION;

So you don't need to int casting and it is directly usable.
Also it is scope separated like enum class

S.M.Mousavi
  • 5,013
  • 7
  • 44
  • 59
0

I prefer using magic_enum as it helps automate converting strings to enums and vice versa. It is a header-only library which is written in C++17 standard.

magic_enum already has template functions for enum bitwise operators. See documentation.

Usage:

#include <magic_enum.hpp>

enum Flag { ... };

Flag flag{};
Flag value{};

using namespace magic_enum::bitwise_operators;
flag |= value;
Burak
  • 2,251
  • 1
  • 16
  • 33
0

I think we can simplify the solution by avoiding the use of bitsets and doing it by creating a templated class with a member variable of the type underlying the enumerator and then overriding operators (&=,|=).

Here's my code:

template <typename _Enum> class EnumFlags final
{
    static_assert(std::is_enum_v<_Enum>,"EnumFlags can only be specialized for enum types!");

    using UnderlyingType = std::underlying_type_t<_Enum>;

    static_assert(std::is_unsigned_v<UnderlyingType>,"EnumFlags requires underlying enum type to be unsigned");

private:
    UnderlyingType m_flags = 0;

public:
    EnumFlags() = default;
    EnumFlags(EnumFlags &&) = default;
    EnumFlags(const EnumFlags &) = default;

public:
    [[nodiscard("")]] constexpr void operator&=(_Enum _enum) noexcept
    {
        m_flags &= (UnderlyingType)_enum;
    }

    [[nodiscard("")]] constexpr void operator|=(_Enum _enum) noexcept
    {
        m_flags |= (UnderlyingType)_enum;
    }

    [[nodiscard("")]] constexpr void operator^=(_Enum _enum) noexcept
    {
        m_flags ^= (UnderlyingType)_enum;
    }

    [[nodiscard("")]] constexpr bool operator&(_Enum _enum) noexcept
    {
        return m_flags & (UnderlyingType)_enum;
    }

public:
    [[nodiscard("")]] UnderlyingType GetFlags() const noexcept
    {
        return (UnderlyingType)m_flags;
    }
};

I hope this solution bounds the flexibility and ease of use from the previous answers, good development!

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
0

Not really an answer but I would like to highlight that for those who has issues with implementing 64-bit bitfields, you should add a "ull" to the 1 in the bit shift operation.

enum BitField : uint64_t
{
    FIELD_1 = 1ull << 0,
    FIELD_2 = 1ull << 1,
    FIELD_3 = 1ull << 2,
    FIELD_4 = 1ull << 3,
    FIELD_5 = 1ull << 4,

    FIELD_U32_MAX = 1ull << 30,

    FIELD_U64_MAX = 1ull << 63,
};

this circumvents the error of 64-bit enums being limited to 32-bits.