Reputation: 207
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?
Upvotes: 6
Views: 448
Reputation: 41100
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);
Upvotes: 2