CAVEAT:并非所有的编译器都以相同的方式实现C ++ 11规范。以下代码可在我测试过的编译器中使用,而许多注释者使用其他编译器。
引用Shafik Yaghmour的回答:在编译时计算C字符串的长度。这真的是constexpr吗?
不能保证在编译时就对常量表达式进行求值,但是从C ++标准草案第5.19节常量表达式中我们只能得到一个非规范性的引用,尽管如此:
[...]> [注意:常量表达式可以在翻译过程中求值。
这个词can改变了世界。
因此,YMMV对此问题(或任何问题)的涉及constexpr,取决于编译器作者对规范的解释。
[2016.01.31更新]
由于有些人不喜欢我之前的答案,因为它不需要字符串比较就可以实现目标,从而避免了compile time string compareOP 的整个方面,因此这里提供了更详细的答案。
你不能!不在C98或C99中。甚至在C11中也没有。大量的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
您可以!在C ++ 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
更新:ANSI令牌粘贴有时不太明显。;-D
#在宏之前放置单个会导致将其更改为其值的字符串,而不是其裸值。
##在两个标记之间放置一个双精度值会使它们被串联为一个标记。
因此,宏USER_VS的扩展名为jack_VS或queen_VS,具体取决于您的设置方式USER。
该字符串化宏S(...)使用宏间接这样命名宏的值被转换成字符串。而不是宏的名称。
因此,USER##_VS成为jack_VS(或queen_VS),这取决于你如何设置USER。
稍后,当将stringify宏用作(在此示例中)S(USER_VS)的值时,将传递到间接步骤,该步骤会将其value()转换为string 。USER_VSjack_VSS_(jack_VS)queen"queen"
如果设置USER为,queen则最终结果是字符串"jack"。
有关令牌串联的信息,请参见:https : //gcc.gnu.org/onlinedocs/cpp/Concatenation.html
有关令牌字符串的转换,请参见:https : //gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification