Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine enums c++

Tags:

c++

enums

c++11

In my project, I have several enum declarations alike this one;

enum Comparison
{
    LT,     // "<"
    GT,     // ">"
    EQ,     // "=="
    LTEQ,   // "<="
    GTEQ,   // ">="
    NEQ     // "!="
};
enum Arithmetic
{
    ADD,    // "+"
    SUB,    // "-"
    MUL,    // "*"
    DIV,    // "/"
    MOD,    // "%"
};

And I'd like to combine several of these, into a single combined enum, such that;

  • All elements (from the sub-enums) are present in the combined enum.
  • All elements have a unique value (obviously).
  • All elements have consistent value in the combined enum, and the original.

Like this:

enum Comparison
{
    LT,     // "<"
    GT,     // ">"
    EQ,     // "=="
    LTEQ,   // "<="
    GTEQ,   // ">="
    NEQ     // "!="

    ADD,    // "+"
    SUB,    // "-"
    MUL,    // "*"
    DIV,    // "/"
    MOD,    // "%"
};

Also what I'd like to be able to do, is to 'cast' the combined enum, to one of the original ones, given the value in the combined enum only (should be trivial assuming the values are consistent).

An alternative to enum, is a class based solution, where the classes implement the operator int() operator.

Note; I do believe the operator int() is somehow the way to go.

like image 794
Skeen Avatar asked Aug 20 '13 20:08

Skeen


2 Answers

What I've commonly seen is this:

enum OperationType {
    Comparison = 0x100,
    Arithmetic = 0x200
};        

enum ComparisonType
{
    LT = Comparison,     // "<"
    GT,     // ">"
    EQ,     // "=="
    LTEQ,   // "<="
    GTEQ,   // ">="
    NEQ     // "!="
};
enum ArithmeticType
{
    ADD = Arithmetic,    // "+"
    SUB,    // "-"
    MUL,    // "*"
    DIV,    // "/"
    MOD,    // "%"
};

Which gives you a little more flexibility than simple chaining, because now you can add comparisons without disrupting your Arithmetics, and the Arithmetics and Comparisons don't need to know about eachother. It also becomes trivial to get the type of an enum:

constexpr OperationType getOperationType(unsigned value)
{return static_cast<OperationType>(value&0xFF00);}
like image 69
Mooing Duck Avatar answered Sep 27 '22 17:09

Mooing Duck


A common (but not exceptionally elegant) way to chain enum together (for example if child classes need to extend a unique set) is to have each enum provide a "last" value and use it to start the next:

enum Comparison
{
    LT,     // "<"
    ...
    NEQ,    // "!="
    LastComparison
};

enum Logical
{
    AND = LastComparison,
    OR,
    ...
    LastLogical
};
like image 35
Ben Jackson Avatar answered Sep 27 '22 17:09

Ben Jackson