I have a question about the different forms of enums 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.
1: 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
2: 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
3: namespaced 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
4: namespaced 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 enums or namespaced constexprs?