Iterating over non-incremental Enum

前端 未结 15 2023
长发绾君心
长发绾君心 2021-01-31 15:42

Before you ask, I\'ve looked and looked for this on SO, and cannot find a solid answer.

I need to be able to dynamically iterate over an enum that has non-incre

15条回答
  •  忘了有多久
    2021-01-31 16:02

    Somewhat clearer (???) with a bit of boost preprocessing.

    You define your enums by a sequence

    #define CAPI_SUBTYPE_E_Sequence \
        (CAPI_SUBTYPE_NULL)(0)  \
        (CAPI_SUBTYPE_DIAG_DFD)(1) ...
    

    then you can automate (through macros) the declaration of the enum,

    DECL_ENUM(CAPI_SUBTYPE_E) ;
    

    the table that indexes it

    DECL_ENUM_TABLE(CAPI_SUBTYPE_E);
    

    the number of enums / size of the table

    ENUM_SIZE(CAPI_SUBTYPE_E)
    

    and access to it:

    ITER_ENUM_i(i,CAPI_SUBTYPE_E)
    

    Here is the full text.

    #include 
    
    // define your enum as (name)(value) sequence
    #define CAPI_SUBTYPE_E_Sequence \
        (CAPI_SUBTYPE_NULL)(0)  /* Null subtype. */ \
        (CAPI_SUBTYPE_DIAG_DFD)(1) /* Data Flow diag. */ \
        (CAPI_SUBTYPE_DIAG_ERD)(2)  /* Entity-Relationship diag. */ \
        (CAPI_SUBTYPE_DIAG_DSD)(5) /* Data Structure diag. */ \
        (CAPI_SUBTYPE_DD_ALL)(13) /* DD Entries (All). */
    
    //  # enums
    #define ENUM_SIZE(name) \
        BOOST_PP_DIV(BOOST_PP_SEQ_SIZE(BOOST_PP_CAT(name,_Sequence)),2)
    
    #define ENUM_NAME_N(N,seq) BOOST_PP_SEQ_ELEM(BOOST_PP_MUL(N,2),seq)
    #define ENUM_VALUE_N(N,seq) BOOST_PP_SEQ_ELEM(BOOST_PP_INC(BOOST_PP_MUL(N,2)),seq) 
    
    // declare Nth enum
    #define DECL_ENUM_N(Z,N,seq) \
        BOOST_PP_COMMA_IF(N)   ENUM_NAME_N(N,seq) =  ENUM_VALUE_N(N,seq)
    
    // declare whole enum
    #define DECL_ENUM(name) \
        typedef enum { \
           BOOST_PP_REPEAT( ENUM_SIZE(name) , DECL_ENUM_N , BOOST_PP_CAT(name,_Sequence) ) \
           } name 
    
    DECL_ENUM(CAPI_SUBTYPE_E) ;
    
    // declare Nth enum value
    #define DECL_ENUM_TABLE_N(Z,N,seq) \
        BOOST_PP_COMMA_IF(N)   ENUM_NAME_N(N,seq)
    
    // declare table
    #define DECL_ENUM_TABLE(name) \
        static const name BOOST_PP_CAT(name,_Table) [ENUM_SIZE(name)] = { \
           BOOST_PP_REPEAT( ENUM_SIZE(name) , DECL_ENUM_TABLE_N , BOOST_PP_CAT(name,_Sequence) ) \
           } 
    
    DECL_ENUM_TABLE(CAPI_SUBTYPE_E);
    
    #define ITER_ENUM_i(i,name)  BOOST_PP_CAT(name,_Table) [i] 
    
    // demo 
    // outputs :  [0:0] [1:1] [2:2] [3:5] [4:13]
    #include 
    
    int main() {
        for (int i=0; i
    #include  
    
          #define CHECK_ENUM_N(Z,N,seq) \
          BOOST_PP_IF( N , \
          BOOST_STATIC_ASSERT_MSG( \
                ENUM_VALUE_N(BOOST_PP_DEC(N),seq) < ENUM_VALUE_N(N,seq) , \
                   BOOST_PP_STRINGIZE( ENUM_NAME_N(BOOST_PP_DEC(N),seq) ) " not < " BOOST_PP_STRINGIZE( ENUM_NAME_N(N,seq) ) ) \
                   , ) ;
    
    #define CHECK_ENUM(name) \
        namespace { void BOOST_PP_CAT(check_enum_,name) () { \
        BOOST_PP_REPEAT( ENUM_SIZE(name) , CHECK_ENUM_N , BOOST_PP_CAT(name,_Sequence) )  } }
    
    // enum OK
    CHECK_ENUM(CAPI_SUBTYPE_E)
    
    #define Bad_Enum_Sequence \
        (one)(1)\
        (five)(5)\
        (seven)(7)\
        (three)(3)
    
    // enum not OK : enum_iter.cpp(81): error C2338: seven not < three
    CHECK_ENUM(Bad_Enum)
    

提交回复
热议问题