I am trying to build a X macro that would allow to generate an enum with a bunch of useful functions like .toString()
for instance. The version I got can be implemented like this:
#define MAKE_ENUM \
ENUM_NAME( LanguageId ) \
ENUM_TYPE( unsigned int ) \
ENUM_ENTRY( English, 0 )\
ENUM_ENTRY( French ) \
ENUM_ENTRY( German ) \
ENUM_ENTRY( Italian ) \
ENUM_ENTRY( Spanish ) \
ENUM_ENTRY( Polish ) \
ENUM_ENTRY( Korean, 128 ) \
ENUM_ENTRY( ChineseTraditional, 129 ) \
ENUM_ENTRY( ChineseSimplified, 130 ) \
ENUM_ENTRY( Japanese, 131 )
#include "GenericToolbox.MakeEnum.h"
#undef MAKE_ENUM
The deploying of the X macro MAKE_ENUM
is done under the header GenericToolbox.MakeEnum.h
.
This version works so far as expected. However I want ENUM_TYPE
to be an optional argument, therefore sometimes it wouldn't be set by the user and the enum would be defined as the default int
.
For that I need to figure out if the unfolding of the MAKE_ENUM is empty. The version I came up with is such:
#define TEMP_EXPAND(x) x
#define TEMP_SELECT_THIRD(_1,_2,num,...) num
#define TEMP_IS_NOT_EMPTY_IMPL(...) TEMP_EXPAND(TEMP_SELECT_THIRD(__VA_ARGS__,1,0))
#define TEMP_ARGS_DUMMY( ... ) dummy,##__VA_ARGS__
#define TEMP_IS_NOT_EMPTY( val ) TEMP_IS_NOT_EMPTY_IMPL(TEMP_ARGS_DUMMY( val ))
// [...]
#define ENUM_TYPE(type_) type_ // MAKE_ENUM will only return type_ if it exists
#if TEMP_IS_NOT_EMPTY( MAKE_ENUM ) == 1
typedef MAKE_ENUM EnumType;
#else
typedef int EnumType;
#endif
// [...]
The issue is that it seems the TEMP_IS_NOT_EMPTY
macro only works with Clang but not GCC. Do you have any idea why? And would there be a viable workaround?
To clarify the issue, I've added a test withing the code:
#define MAKE_ENUM_EMPTY
#if TEMP_IS_NOT_EMPTY( MAKE_ENUM_EMPTY ) == 1
// NOT empty
#warning "TEMP_IS_NOT_EMPTY does not work correctly for empty macro"
#else
// empty
#endif
#define MAKE_ENUM_NOT_EMPTY unsigned int
#if TEMP_IS_NOT_EMPTY( MAKE_ENUM_NOT_EMPTY ) == 1
// NOT empty
#else
// empty
#warning "TEMP_IS_NOT_EMPTY does not work correctly for NOT empty macro"
#endif
With GCC I get the warning message: #warning "TEMP_IS_NOT_EMPTY does not work correctly for empty macro"
Cheers!
Check out the following design:
#define ENUM_NAME LanguageId
#define ENUM_TYPE unsigned int
#define ENUM_FIELDS \
ENUM_ENTRY( English, 0 )\
ENUM_ENTRY( French ) \
ENUM_ENTRY( German ) \
ENUM_ENTRY( Italian ) \
ENUM_ENTRY( Spanish ) \
ENUM_ENTRY( Polish ) \
ENUM_ENTRY( Korean, 128 ) \
ENUM_ENTRY( ChineseTraditional, 129 ) \
ENUM_ENTRY( ChineseSimplified, 130 ) \
ENUM_ENTRY( Japanese, 131 )
#include "GenericToolbox.MakeEnum.h"
Then:
// "GenericToolbox.MakeEnum.h"
#ifndef ENUM_TYPE
// default:
#define ENUM_TYPE int
#endif
typedef ENUM_TYPE ENUM_NAME;
// process ENUM_FIELDS ...
#undef ENUM_TYPE
#undef ENUM_FIELDS
#undef ENUM_NAME
Fun fact: this is the design that STC library is using.