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
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)