Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you use bitwise operators with enum classes without casting?

Tags:

c++

enum-class

I like to use enum classes, but I use them as flags sometimes and I have to constantly cast to int if I want to use a bitwise operator. Is there a way to do this without casting? I don't think you can define the operators for them?

If I have functions that take an enum class, do I have to do this?

enum class Flags { FLAG1, FLAG2, FLAG3};

void setFlags(Flags flags){}

int main()
{
      setFlags((Flags)((int)Flags::FLAG1 | (int)Flags::FLAG2 | (int)Flags::FLAG3));
}
like image 597
Zebrafish Avatar asked Jun 25 '26 04:06

Zebrafish


2 Answers

The class after the enum specifies that an enumeration is strongly typed and that its enumerators are scoped. Beware, enum class has only assignment, initialization and comparisons defined by default. Nevertheless, an enumeration is user-defined type, as such, you can define operators for it.


If you don't want to explicitly qualify enumerator names and want enumerator values to be ints (without the need for an explicit conversion), you can remove the class from enum class to get "plain" enum. Enumerators are exported to the surrounding scope to evade name collisions, you can wrap with namespace.

#include <iostream>

namespace Flags {
    enum : int 
    {
        bit_1 = 0x1,
        bit_2 = 0x2
    };
}

int main()
{
    int num = 11;
    if (num & Flags::bit_1)
        std::cout << "lsb is on!\n";
    else 
        std::cout << "lsb is off!\n";
    return 0;
}

References:

  • A Tour of C++ Second edition by Bjarne Stroustrup
like image 64
Tony Tannous Avatar answered Jun 26 '26 20:06

Tony Tannous


If you don't want to overload operators on scoped enums yourself, why not using one of libraries that do that for you.

For example:

  • enum-flags
  • magic-enum

I have created such library myself - bitflags (it's not the best but does what I want) where you can create your flags by just specifying the following:

BEGIN_BITFLAGS(Flags)
    FLAG(none)
    FLAG(flag_a)
    FLAG(flag_b)
    FLAG(flag_c)
END_BITFLAGS(Flags)

and then you can do:

int main() {
    Flags flags = Flags::flag_a | Flags::flag_b;

    if (flags & Flags::flag_a) {
        std::cout << "flag_a is set" << std::endl;
    } else {
        std::cout << "flag_a is not set" << std::endl;
    }

    flags.toggle(Flags::flag_a);

    // ...

    return 0;
}

Notice that you don't need to specify the type for your flags because the minimum size type is being used automatically, and, furthermore, you don't need to specify values of your flags. They are assigned automatically too.

like image 28
NutCracker Avatar answered Jun 26 '26 20:06

NutCracker



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!