mercredi 4 octobre 2017

Define enum element value using an operation on another enum values

Here is what I need to do: define, inside a class, two enumerations, the second having elements defined using elements values from the first.

So something like this:

class MyClass
{
    public:
        enum class Elem {
            A=1, B=2, C=4, D=8
        };
        enum class Group {
            first = Elem::A | Elem::B,
            second = Elem::A | Elem::C,
            //...
        }; <-- compilation error
};

However, this does not compile due to the fact that | is not defined by default for enum classes.

I tried to define the | operator for Elem enum, outside of the MyClass class (after the class body), but the operator is then not known at the time the Group enum is defined.

So I then tried the following, i.e. defining a constexpr function inside the class:

class MyClass
{
    public:
        enum class Elem {
            A=1, B=2, C=4, D=8
        };

        constexpr static unsigned int merge(
            std::initializer_list<MyClass::Elem> list)
        {
            //Test only: should be an '|' on all list elements
            return 1;
        }

        enum class Group {
            first = merge({Elem::A,Elem::B}),
            second = merge({Elem::A,Elem::C}),
            /*...*/
        };
};

But I get the following error:

error: static constexpr unsigned int merge(std::initializer_list list) called in a constant expression

I understood from here and there that the merge method is considered declared and usable only after the class has been fully declared.

The last solution I can think of is using macros like this:

#define MERGE2ELEMS( a, b ) static_cast<unsigned int>(a) | static_cast<unsigned int>(b)
#define MERGE3ELEMS( a, b, c ) static_cast<unsigned int>(a) | MERGE2ELEMS( b, c )
#define MERGE4ELEMS( a, b, c, d ) static_cast<unsigned int>(a) | MERGE3ELEMS( b, c, d )
#define MERGE5ELEMS( a, b, c, d, e ) static_cast<unsigned int>(a) | MERGE4ELEMS( b, c, d, e )
...

But I need to be able to merge up to 20 Elems and writing 20 macros like this does not seem to be a suitable solution.

What would be the way to go here?

Aucun commentaire:

Enregistrer un commentaire