McMuffinton
McMuffinton

Reputation: 207

C++ scoped enums that are implicitly convertable to integers

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?

Upvotes: 6

Views: 448

Answers (1)

AndyG
AndyG

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
    };
};

Live Demo

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

Related Questions