• Forum
  • Lounge
  • Elegant Way to Use Enum Classes as Flags

 
Elegant Way to Use Enum Classes as Flags?

Aug 11, 2015 at 5:39am
I'm trying to figure out a way to use the scoped enumeration feature defined in C++11.

In my project, I have something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum class InputElementName
{
    BINORMAL,
    BLENDINDICES,
    BLENDWEIGHT,
    COLOR,
    NORMAL,
    POSITION,
    POSITIONT,
    PSIZE,
    TANGENT,
    TEXCOORD,
    COLOR,
    FOG,
    TESSFACTOR,
};


I want to use it in a manner such as this:
1
2
3
4
5
RBE::InputElementDescription input_elements[] =
{
    { RBE::InputElementName::POSITION, 0, RBE::Format::RGBA_F32, 0, 0,  RBE::InputElementClass::VERTEX, 0 },
    { RBE::InputElementName::COLOR,    0, RBE::Format::RGBA_F32, 0, 16, RBE::InputElementClass::VERTEX, 0 }
};


I'm trying to use this as a sort of more verbose way to use flags, and also to remove littering of namespaces by not using them. Unfortunately, C++11 doesn't allow a lot of operations you could perform with non-enum flag types, so I have to try to find a (hopefully not very hacky) way around this. Maybe I could use a template-based solution to get around this? (I'd prefer not to use a macro for this, as they just pollute global namespace, which is exactly the type of thing I'm trying to avoid)

I guess the simplest way to do this all would be to do something like:
1
2
3
4
5
6
7
struct InputElementName
{
    enum
    {
        BINORMAL, // Etc
    };
};
But that's pretty ugly and it can't actually be used as a type.

Thanks in advance.
Last edited on Aug 11, 2015 at 6:00am
Aug 11, 2015 at 7:20am
If you're going to use old-style flags and OR them together, you should probably just use old-style enums too.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace InputElementName
{
    enum type //so you can use InputElementName::type
    {
        BINORMAL     = 0b1,
        BLENDINDICES = 0b10,
        BLENDWEIGHT  = 0b100,
        COLOR        = 0b1000,
        NORMAL       = 0b10000,
        POSITION     = 0b100000,
        POSITIONT    = 0b1000000,
        PSIZE        = 0b10000000,
        TANGENT      = 0b100000000,
        TEXCOORD     = 0b1000000000,
//      COLOR        = 0b10000000000, //defined again??
        FOG          = 0b100000000000,
        TESSFACTOR   = 0b1000000000000,
    };
}
Sure, there's no type safety, but you're ORing together flags...?

In an ideal world I'd use a std::set of an enum struct type, but I'm worried about efficiency. You could do some template metaprogramming though...
Last edited on Aug 11, 2015 at 7:25am
Aug 11, 2015 at 7:23am
THis is only if enum values can be mixed together.
Last edited on Aug 11, 2015 at 7:23am
Aug 11, 2015 at 10:53am
Bleh, I just realized that I'm talking about the wrong enumeration. I really meant something like this:
1
2
3
4
5
6
7
8
9
enum class UsageFlags
{
    STATIC   = 0x00000001,
    DYNAMIC  = 0x00000002,
    
    UNORDERED_ACCESS   = 0x0008,
    BYTE_ADDRESS_BUFFER = 0x0020
    // Etc
};

and:
vb = rbe->CreateVertexBuffer(RBE::UsageFlags::DYNAMIC, sizeof(VertexPC) * 3);
Unfortunately it's being defined as a type that's local to a class, so I can't create a namespace in there. I assume my only option is the struct + enum workaround?
Last edited on Aug 11, 2015 at 10:56am
Aug 11, 2015 at 11:03am
1
2
3
4
5
6
7
8
9
10
class RBE {
public:
    struct UsageFlags {
        enum type {
            STATIC =1,
            DYNAMIC,
            UNORDERED_ADDRESS =8
        };
    };
};
Last edited on Aug 11, 2015 at 11:04am
Aug 11, 2015 at 4:32pm
Yeah, that's what I ended up doing, but I just cleaned it up with some macros (but is using macros really "cleaning it?" Lol). Now it's something like:

1
2
3
4
5
6
7
8
9
10
11
12
#define BEGIN_FLAG_TYPE(x) struct x { enum Type{ 
#define END_FLAG_TYPE };};

BEGIN_FLAG_TYPE(UsageFlags)
    STATIC              = 0x00000001,
    DYNAMIC             = 0x00000002,
    
    UNORDERED_ACCESS    = 0x00000008,
    
    BYTE_ADDRESS_BUFFER = 0x00000002,
    // Etc
END_FLAG_TYPE


Thanks guys!
Last edited on Aug 11, 2015 at 5:03pm
Topic archived. No new replies allowed.