[UPDATE: 2018.05.03]
CAVEAT : Nicht alle Compiler implementieren die C ++ 11-Spezifikation auf dieselbe Weise. Der folgende Code funktioniert in dem Compiler, auf dem ich getestet habe, während viele Kommentatoren einen anderen Compiler verwendeten.
Zitat aus Shafik Yaghmours Antwort unter: Berechnung der Länge eines C-Strings zur Kompilierungszeit. Ist das wirklich ein constexpr?
Es wird nicht garantiert, dass konstante Ausdrücke zur Kompilierungszeit ausgewertet werden. Wir haben nur ein nicht normatives Zitat aus dem Entwurf des C ++ - Standardabschnitts 5.19 Konstante Ausdrücke, das dies jedoch sagt:
[...]> [Hinweis: Konstante Ausdrücke können während der Übersetzung ausgewertet werden. - Endnote]
Dieses Wort can
macht den Unterschied in der Welt.
Also, YMMV zu dieser (oder einer beliebigen) Antwort constexpr
, die abhängig von der Interpretation der Spezifikation durch den Compiler-Autor beinhaltet.
[AKTUALISIERT am 31.01.2016]
Da einige meine frühere Antwort nicht mochten, weil sie den gesamten Aspekt des OP vermieden hat,compile time string compare
indem das Ziel erreicht wurde, ohne dass Zeichenfolgenvergleiche erforderlich waren, finden Sie hier eine detailliertere Antwort.
Das kannst du nicht! Nicht in C98 oder C99. Nicht einmal in C11. Keine MACRO-Manipulation wird dies ändern.
Die Definition von const-expression
verwendet in #if
erlaubt keine Zeichenfolgen.
Es erlaubt Zeichen. Wenn Sie sich also auf Zeichen beschränken, können Sie Folgendes verwenden:
#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
Sie können! In C ++ 11. Wenn Sie eine Kompilierungszeit-Hilfsfunktion für den Vergleich definieren.
// 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
Letztendlich müssen Sie also die Art und Weise ändern, in der Sie Ihr Ziel erreichen, die endgültigen Zeichenfolgenwerte für USER
und auszuwählen USER_VS
.
In C99 können Sie keine Vergleiche zur Kompilierungszeit von Zeichenfolgen durchführen, aber Sie können die Auswahl der Zeichenfolgen zur Kompilierungszeit durchführen.
Wenn Sie wirklich Vergleiche zum Kompilieren von Zeitstichen durchführen müssen, müssen Sie zu C ++ 11 oder neueren Varianten wechseln, die diese Funktion zulassen.
[ORIGINAL ANTWORT FOLGT]
Versuchen:
#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: Das Einfügen von ANSI-Token ist manchmal weniger als offensichtlich. ;-D
Wenn Sie ein einzelnes #
vor ein Makro stellen, wird es in eine Zeichenfolge mit seinem Wert anstelle seines bloßen Werts geändert.
Wenn Sie ##
zwischen zwei Token ein Double setzen , werden diese zu einem einzigen Token verkettet.
Das Makro USER_VS
hat also die Erweiterung jack_VS
oder queen_VS
, je nachdem, wie Sie es einstellen USER
.
Das Stringify- Makro S(...)
verwendet die Makro-Indirektion, sodass der Wert des benannten Makros in eine Zeichenfolge konvertiert wird. anstelle des Namens des Makros.
So USER##_VS
wird jack_VS
(oder queen_VS
), je nachdem wie Sie einstellen USER
.
Wenn später das Stringify- Makro als S(USER_VS)
Wert von USER_VS
( jack_VS
in diesem Beispiel) verwendet wird, wird es an den Indirektionsschritt übergeben S_(jack_VS)
, der seinen Wert ( queen
) in einen String konvertiert "queen"
.
Wenn Sie festlegen USER
, queen
ist das Endergebnis die Zeichenfolge "jack"
.
Informationen zur Token-Verkettung finden Sie unter: https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html
Informationen zur Konvertierung von Token-Zeichenfolgen finden Sie unter: https://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification
[AKTUALISIERT am 15.02.2015, um einen Tippfehler zu korrigieren.]