Вопрос

Это для Слияние Препроцессорные эксперты:

Как я могу объявить enum Со списком некоторых идентификаторов и позже во время оператора выключателя проверьте, был ли идентификатор был включен в список?

Пример того, что мне нужно:

typedef enum { e1, e2, e3, e4, e5, e6 } e;

e x;
switch (x) {
#if DECLARED_IN_ENUM (e1)
  case e1 : ...
#endif
  /* etc. */
}

Я подумал об использовании последовательности повышения и расширяя ее в списке разделенного запятыми в списке enum, но как я могу проверить позже, если последовательность содержит определенный токен?

РЕДАКТИРОВАТЬ: Что я смог связать с Boost:

#define e1 e1
#define e2 e2
#define e3 e3
#define e4 e4
#define e5 e5
#define e6 e6
#define E (e1)(e2)(e3)(e4)(e5)(e6)

typedef enum { BOOST_PP_SEQ_ENUM(E) } e;

e x;
switch (x) {
#if defined (e1)
  case e1 : ...
#endif
  /* etc. */
}

Это не очень красиво, и я бы предпочел что-то вроде:

#define E (e1)(e2)(e3)(e4)(e5)(e6)

typedef enum { BOOST_PP_SEQ_ENUM(E) } e;

e x;
switch (x) {
#if BOOST_PP_SEQ_CONTAINS (e1,E)
  case e1 : ...
#endif
  /* etc. */
}

Но как мог BOOST_PP_SEQ_CONTAINS быть реализованным?

Это было полезно?

Решение

Я не думаю BOOST_PP_SEQ_CONTAINS может быть реализован. Требуется, что вы сможете сравнить две последовательности предварительной обработки токенов, которые вы не можете сделать.

Однако, если вы переставляете свою логику немного, вы можете получить что-то ближе к тому, что вы хотите. Во-первых, нам нужна пара помощников макросов для использования с BOOST_PP_SEQ_FOR_EACH:

#include <boost/preprocessor.hpp>

// General purpose macros:
#define EXPAND_ENUM_CASE_2(text1, text2) text1 ## text2
#define EXPAND_ENUM_CASE(r, data, elem) \
    case elem : EXPAND_ENUM_CASE_2(data ## _ ## CASE ## _ , elem)

Мы можем определить список перечислений и перечисление так же, как у вас есть в исходном вопросе:

#define WORKDAY_ENUMERATORS (Monday)(Tuesday)(Wednesday)(Thursday)

enum Workday { BOOST_PP_SEQ_ENUM(WORKDAY_ENUMERATORS) }; 

Как видите, я покинул пятницу из списка, потому что никто на самом деле не работает в пятницу. Давайте рассмотрим в качестве примера функции, которая возвращает какой-то текст, описывающий день недели.

Вместо того, чтобы тестировать, включен ли перечисление в список, мы определяем случаи для каждого из значений с использованием MACROS:

#define WORKDAY_CASE_Monday    { return "Mondays suck";                     }
#define WORKDAY_CASE_Tuesday   { return "Tuesdays are better than Mondays"; }
#define WORKDAY_CASE_Wednesday { return "Hooray for humpday!";              }
#define WORKDAY_CASE_Thursday  { return "Thursdays are okay";               }
#define WORKDAY_CASE_Friday    { return "No one really works on Friday";    }

Затем мы генерируем правильные заявления о случаях для списка с помощью WORKDAY_ENUMERATORS и объединение перечисленных перечислений с WORKDAY_CASE_ приставка:

const char* get_day_text(Workday d)
{    
    switch (d)
    {
        BOOST_PP_SEQ_FOR_EACH(EXPAND_ENUM_CASE, WORKDAY, WORKDAY_ENUMERATORS)
    }
    return "WTF?!  That's not a workday!";
}

Если день не был включен в WORKDAY_ENUMERATORS Список, ни один случай не будет сгенерирован для него.

Потому что мы должны быть вежливы, когда мы используем препроцессор, мы тогда неотъемлемся на макрос, которые мы использовали:

#undef WORKDAY_CASE_Monday
#undef WORKDAY_CASE_Tuesday
#undef WORKDAY_CASE_Wednesday
#undef WORKDAY_CASE_Thursday
#undef WORKDAY_CASE_Friday

Я думаю, что это уродливый, но это один из способов получить почти результаты, которые вы ищете.

Другие советы

Вы не можете. Cre Preprocessor не «понимает» язык программирования C, он просто оно токенезирует его. Это не знает, что означает «enum» на самом деле. Компилятор обрабатывает это.

Если вы хотите проверить что-то в препроцессоре, то вам придется предоставить препроцессорные макросы для него.

Редактировать: Извините, пропустил, что вы намерены использовать Boost.PreProcessor. Я не знаю, могут ли это обеспечить необходимые макросы или нет, как только вы что-то привлечь что-то из повышения в определении вашего Enum.

Просто не используйте enum. Отказ Это не служит полезной цели. Объявить все свои константы с #define, и использовать #ifdef.

Один подход - иметь большой большой файл #define или «.h», который охватывает все ваши будни (файл .h имеет преимущество, которое вам не нужно заканчивать все, что нравится с обратной косой) и включает в себя всю соответствующую информацию для них в макросах. Затем #define Генераторный макрос сделать что-то, вызывающую большой макрос (или #include заголовок), # andedef генераторный макрос и определить его, чтобы сделать что-то еще, снова вызвать большой макрос и т. Д. В этом сценарии, один вариант Генератор макрос генерирует что-то вроде «Case Enum_foo: func_foo (); break;". Затем вы можете написать весь соответствующий код для соответствующих функций Func_ *, и их будут называться соответствующими.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top