I have a question about the different forms of enum
s and enum class
's, specifically to specify a large number of (scoped!) constants.
I was wondering if there is a way to declare a scoped enum, which is implicitly convertable to an integer. A usecase for this would be to specify register adresses and to be able to access them with something like MY_REGISTERS::FOO
.
Here are the options that I know of and have encountered, please imagine a function with the signature void do_something(uint32_t bla)
exists.
enum class
Enum class is scoped, but not implicitly convertable to an integer. I find it important that I don't have to static_cast
it to an integer so this doesn't seem like the right fit.
enum class Foo : uint32_t
{
BAR = 0x0000,
BAZ = 0x0001
};
do_something(Foo::BAR) // Illegal, I'd have to `static_cast` here
enum
A regular C styled enum is implicitly convertable to an integer, but is not scoped (and pollutes the namespace it's in). Here is an example of why I find this undesirable for my usecase:
enum Foo : uint32_t
{
BAR = 0x0000,
BAZ = 0x0001
}
do_something(Foo::BAR) // Legal, and what I am looking for
do_something(BAR) // Legal, whilst I don't want this to be possible
enum
This works, but if I encountered this somewhere, I'd raise an eyebrow. Something tells me there may be a better way
namespace Foo
{
enum dontcare : uint32_t
{
BAR = 0x0000,
BAZ = 0x0001
};
}
do_something(Foo::BAR) // Legal, and what I am looking for
do_something(BAR) // Illegal, just like I want it to be
static constexpr
Although this does what I want, I again (just like with the namespaced enum
) feel like there must be a better way.
namespace Foo
{
static constexpr uint32_t BAR = 0x0000,
static constexpr uint32_t BAZ = 0x0001
}
do_something(Foo::BAR) // Legal, and what I am looking for
do_something(BAR) // Illegal, just like I want it to be
So, all in all, is there a better way for this or will I have to stick to either namespaced enum
s or namespaced constexpr
s?
Strongly typed enums can NOT be converted to integers without an explicit cast. Weak enums can, however, as they will be automatically implicitly cast. So, if you'd like automatic implicit conversion to an int, consider using a C-style weak enum instead (see more on this in the "Going further" section below).
Overview. Scoped enums (enum class/struct) are strongly typed enumerations introduced in C++11. They address several shortcomings of the old C-style (C++98) enums, mainly associated with type-safety and name collisions.
The strongly-typed enumerations have to follow stronger rules: The enumerators can only be accessed in the scope of the enumeration. The enumerators don't implicitly convert to int. The enumerators aren't imported in the enclosing scope. The type of the enumerators is by default int.
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.
You can hack your own scoped enum by mixing a struct
with a nested anonymous enum (Edit: I guess the enum itself doesn't have to be anonymous):
struct Foo{
enum: uint32_t
{
BAR = 0x0000,
BAZ = 0x0001
};
};
It's not a scoped enum as per C++11 semantics ([dcl.enum]), but it's at least an enum that is scoped to the Foo
class. And it's usable like how you want without polluting the global namespace:
do_something(Foo::BAR);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With