Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

enum class with scoping but without having to cast to underlying type

Tags:

c++

c++11

I have this:

enum class Categories : uint32_t {
    C6 = 0x00000020,
    C7 = 0x00000040,
    C8 = 0x00000080,
    ...
};

I chose an enum class because it is great for scoping. But the downside is that when I need to use the categories as mask bits for bitwise operations I need to cast them to uint32_t first.

Example:

uint32_t masterCat = ((uint32_t)MyClass::Categories::C6) | ((uint32_t)MyClass::Categories::C7);

Is there a way I can get the same scoping benefit, without having to cast before using each time ? If I use a regular enum, then I lose the scoping benefit :(

Example:

uint32_t masterCat = (MyClass::Categories::C6) | (MyClass::Categories::C7);

like image 812
Rahul Iyer Avatar asked Dec 01 '21 04:12

Rahul Iyer


People also ask

What is a scoped enum?

A scoped enum looks exactly as a traditional enum except that the keyword class (or struct – the two keywords are interchangeable in this context) appears between the keyword enum and the enum name, as shown in the following example: enum class Color //C++11 scoped enum.

Do enums wrap around?

No. enum s are not designed to "wrap around" in the way you describe by default.

Can you cast int to enum C++?

C++ Explicit type conversions Enum conversions static_cast can convert from an integer or floating point type to an enumeration type (whether scoped or unscoped), and vice versa. It can also convert between enumeration types.

Is enum C++?

What Is C++ Enum? In C++ programming, enum or enumeration is a data type consisting of named values like elements, members, etc., that represent integral constants. It provides a way to define and group integral constants. It also makes the code easy to maintain and less complex.

What is the class after the enum in C++?

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.

What are scoped enums and how to use them?

Scope enums have many advantages over standard enums. Anthony Williams shows how to use them as bitmasks. C++ 11 introduced a new feature in the form of scoped enumerations , also referred to as enum classes , since they are introduced with the double keyword enum class (though enum struct is also permissible, to identical effect).

What is enumeration in C++11?

C++11 has introduced enum classes (also called scoped enumerations ), that makes enumerations both strongly typed and strongly scoped. Class enum doesn’t allow implicit conversion to int, and also doesn’t compare enumerators from different enumerations. To define enum class we use class keyword after enum keyword.

What is enum type in Java?

Enums or Enumerated type (enumeration) is a user-defined data type that can be assigned some limited values. These values are defined by the programmer at the time of declaring the enumerated type. Need for Enum Class over Enum Type: Below are some of the reasons as to what are the limitations of Enum Type and why we need Enum Class to cover them.


2 Answers

Split the enum class into an enum and a class (or struct for convenience).

struct Categories {
    enum : uint32_t {
        C6 = 0x00000020,
        C7 = 0x00000040,
        C8 = 0x00000080,
    };
};

Since the enum is an embedded type, you need to specify Categories to access it, as in Categories::C6.

If this is inside another class, such as

class MyClass {
  public:
    struct Categories {
        enum : uint32_t {
            C6 = 0x00000020,
            C7 = 0x00000040,
            C8 = 0x00000080,
        };
    };
};

then you can use MyClass::Categories::C6 to refer to one of the enumerates, but neither MyClass::C6 nor C6 will work.

like image 140
JaMiT Avatar answered Nov 14 '22 21:11

JaMiT


If you want to use bitwise and still forbid conversion to its underlying type, then you might add functions, so cast is done only once, on purpose:

enum class Categories : std::uint32_t {
    C6 = 0x00000020,
    C7 = 0x00000040,
    C8 = 0x00000080,
    //...
};

constexpr /*Categories*/ std::uint32_t operator | (Categories lhs, Categories rhs)
{
    return /*Categories*/(std::uint32_t(lhs) | std::uint32_t(rhs));
}
// operator& ...
like image 27
Jarod42 Avatar answered Nov 14 '22 21:11

Jarod42