Detect when multiple enum items map to same value

后端 未结 8 2174
猫巷女王i
猫巷女王i 2020-11-28 13:44

Is there a compile-time way to detect / prevent duplicate values within a C/C++ enumeration?

The catch is that there are multiple items which are initialize

8条回答
  •  臣服心动
    2020-11-28 13:51

    Here's a solution using X macro without Boost. First define the X macro and its helper macros. I'm using this solution to portably make 2 overloads for the X macro so that you can define the enum with or without an explicit value. If you're using GCC or Clang then it can be made shorter

    #define COUNT_X_ARGS_IMPL2(_1, _2, count, ...) count
    #define COUNT_X_ARGS_IMPL(args) COUNT_X_ARGS_IMPL2 args
    #define COUNT_X_ARGS(...) COUNT_X_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
    
    /* Pick the right X macro to invoke. */
    #define X_CHOOSE_HELPER2(count) X##count
    #define X_CHOOSE_HELPER1(count) X_CHOOSE_HELPER2(count)
    #define X_CHOOSE_HELPER(count)  X_CHOOSE_HELPER1(count)
    
    /* The actual macro. */
    #define X_GLUE(x, y) x y
    #define X(...) X_GLUE(X_CHOOSE_HELPER(COUNT_X_ARGS(__VA_ARGS__)), (__VA_ARGS__))
    

    Then define the macro and check it

    #define BASE1_VAL    (5)
    #define BASE2_VAL    (7)
    
    // Enum values
    #define MY_ENUM             \
    X(MsgFoo1A, BASE1_VAL)      \
    X(MsgFoo1B)                 \
    X(MsgFoo1C)                 \
    X(MsgFoo1D)                 \
    X(MsgFoo1E)                 \
    X(MsgFoo2A, BASE2_VAL)      \
    X(MsgFoo2B)
    
    // Define the enum
    #define X1(enum_name)               enum_name,
    #define X2(enum_name, enum_value)   enum_name = enum_value,
    enum foo
    {
        MY_ENUM
    };
    #undef X1
    #undef X2
    
    // Check duplicates
    #define X1(enum_name)               case enum_name: break;
    #define X2(enum_name, enum_value)   case enum_name: break;
    static void check_enum_duplicate()
    {
        switch(0)
        {
            MY_ENUM
        }
    }
    #undef X1
    #undef X2
    

    Use it

    int main()
    {
    // Do something with the whole enum
    #define X1(enum_name)               printf("%s = %d\n", #enum_name, enum_name);
    #define X2(enum_name, enum_value)   printf("%s = %d\n", #enum_name, enum_value);
        // Print the whole enum
        MY_ENUM
    #undef X1
    #undef X2
    }
    

提交回复
热议问题