Препроцессор C ++ добавляет слово, если условие

Я пишу библиотеку, которая использует препроцессор метапрограммирования Boost.Preprocessor. Один макрос выглядит примерно так:

#define MY_MACRO(my_type) return some_function<my_type>()

Теперь проблема в том, что мне нужно удалить return если my_type является void, Я проверил Boost.Preprocessor, но не увидел ничего, что могло бы мне помочь. Как мне это сделать? Что-то вроде:

#define MY_MACRO(my_type) BOOST_PP_IF(\
TYPE_EQUALS(my_type,void),return,BOOST_PP_EMPTY()) some_function<my_type>()

2

Решение

К сожалению, в препроцессоре boost нет простого способа сравнить два токена. Конечно, для вашего случая вам может понадобиться простое обнаружение. Это должно работать на препроцессорах C99:

#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define PROBE(x) x, 1,

#define IS_VOID(x) CHECK(BOOST_PP_CAT(IS_VOID_, x))
#define IS_VOID_void PROBE(~)

Тем не менее, это не сработает для скобок, для переменных данных (таких как типы с запятыми в них) или указателей. Вот те, которые работают и не работают:

IS_VOID(int) // 0
IS_VOID(void) // 1
IS_VOID((void)) // Compile error
IS_VOID(std::map<int, int>) // Compile error
IS_VOID(void*) // Returns 1, but should return 0

Вы можете попытаться обойти все эти случаи или использовать более общий макрос сравнения (например, Вот):

#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x)
#define IS_PAREN_PROBE(...) PROBE(~)

#define IS_COMPARABLE(x) IS_PAREN( CAT(COMPARE_, x) (()) )

#define NOT_EQUAL(x, y) \
IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y)) ) \
( \
PRIMITIVE_COMPARE, \
1 EAT \
))(x, y)

#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y))

#define COMPARE_void(x) x
#define IS_VOID(x) EQUAL(x, void)

Который может быть обновлен для использования компонентов препроцессора boost. Это должно работать для большего количества случаев, но все еще не будет работать с круглыми скобками (что может не быть проблемой).

Наконец, это просто сравнение на текстовом уровне, поэтому, если у пользователя есть typedefed void, он неверно вернет false:

typedef void my_void;
IS_VOID(my_void) // Returns 0

Если вы используете метод обнаружения, вы можете позволить пользователю расширить его для определенных пользователем пустот, например, так:

#define IS_VOID(x) CHECK(BOOST_PP_CAT(IS_VOID_, x))
#define IS_VOID_void PROBE(~)
// User-defined void
#define IS_VOID_my_void PROBE(~)
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]