[ОБНОВЛЕНИЕ: 2018.05.03]
CAVEAT : Не все компиляторы реализуют спецификацию C ++ 11 одинаково.
Приведенный ниже код работает в компиляторе, на котором я тестировал, тогда как многие комментаторы использовали другой компилятор.
Цитата из ответа Шафика Ягмура по адресу: Вычисление длины строки C во время компиляции. Это действительно constexpr?
Выражения констант не гарантируются при компиляции
время, у нас есть только ненормативная цитата из проекта стандарта C ++
раздел 5.19 Постоянные выражения, которые говорят это, хотя:
[...]> [Примечание: константные выражения можно вычислять во время
перевод. - Конечная заметка]
Это слово can
имеет все значение в мире.
Итак, YMMV для этого (или любого) ответа, включающего constexpr
, в зависимости от интерпретации спецификацией автора компилятора.
[ОБНОВЛЕНО 2016.01.31]
Поскольку некоторым не понравился мой предыдущий ответ, потому что он позволил избежать всего аспекта compile time string compare
ОП, выполнив задачу без необходимости сравнения строк, вот более подробный ответ.
Ты не можешь! Не в C98 или C99. Даже в С11. Никакое количество манипуляций с MACRO не изменит этого.
Определение const-expression
, используемое в #if
, не допускает строки.
Он разрешает символы, поэтому, если вы ограничиваете себя символами, вы можете использовать это:
#define JACK 'J'
#define QUEEN 'Q'
#define CHOICE JACK // or QUEEN, your choice
#if 'J' == CHOICE
#define USER "jack"
#define USER_VS "queen"
#elif 'Q' == CHOICE
#define USER "queen"
#define USER_VS "jack"
#else
#define USER "anonymous1"
#define USER_VS "anonymous2"
#endif
#pragma message "USER IS " USER
#pragma message "USER_VS IS " USER_VS
Можно! В С ++ 11. Если вы определяете вспомогательную функцию времени компиляции для сравнения.
// compares two strings in compile time constant fashion
constexpr int c_strcmp( char const* lhs, char const* rhs )
{
return (('\0' == lhs[0]) && ('\0' == rhs[0])) ? 0
: (lhs[0] != rhs[0]) ? (lhs[0] - rhs[0])
: c_strcmp( lhs+1, rhs+1 );
}
// some compilers may require ((int)lhs[0] - (int)rhs[0])
#define JACK "jack"
#define QUEEN "queen"
#define USER JACK // or QUEEN, your choice
#if 0 == c_strcmp( USER, JACK )
#define USER_VS QUEEN
#elif 0 == c_strcmp( USER, QUEEN )
#define USER_VS JACK
#else
#define USER_VS "unknown"
#endif
#pragma message "USER IS " USER
#pragma message "USER_VS IS " USER_VS
Итак, в конечном итоге вам придется изменить способ достижения конечной строковой величины для USER
и USER_VS
.
Вы не можете выполнять сравнение строк времени компиляции в C99, но вы можете выбирать строки во время компиляции.
Если вам действительно нужно сравнивать время компиляции, вам нужно перейти на C ++ 11 или более новые варианты, которые позволяют эту функцию.
[ОРИГИНАЛЬНЫЙ СЛЕДУЮЩИЙ ОТВЕТ]
Попробуйте:
#define jack_VS queen
#define queen_VS jack
#define USER jack // jack or queen, your choice
#define USER_VS USER##_VS // jack_VS or queen_VS
// stringify usage: S(USER) or S(USER_VS) when you need the string form.
#define S(U) S_(U)
#define S_(U) #U
UPDATE:
Вставка токена ANSI иногда менее очевидна. ; -D
Помещение одиночного #
перед макросом приводит к тому, что он заменяется строкой своего значения, а не его пустым значением.
Помещение двойного ##
между двумя токенами приводит к их объединению в один токен.
Итак, макрос USER_VS
имеет расширение jack_VS
или queen_VS
, в зависимости от того, как вы установите USER
.
stringify macro S(...)
использует перенаправление макроса, поэтому значение указанного макроса преобразуется в строку. вместо имени макроса.
Таким образом, USER##_VS
становится jack_VS
(или queen_VS
), в зависимости от того, как вы установите USER
.
Позже, когда макрос stringify используется как S(USER_VS)
, значение USER_VS
(jack_VS
в этом примере) передается на шаг косвенного обращения S_(jack_VS)
, который преобразует его значение (queen
) в строку "queen"
.
Если вы установите USER
на queen
, тогда конечным результатом будет строка "jack"
.
Для объединения токенов см .: https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html
Для преобразования строки токена см .: https://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification
[ОБНОВЛЕНО 2015.02.15 для исправления опечатки.]