我正在尝试做一个这样的宏:
#define STRING(i) \
struct STRING##i \
{ \
size_t len; \
char chars[i]; \
}
但问题是这适用于像这样的
constexpr
参数:
constexpr int ten = 10;
STRING(ten) mystr;
我不希望这样,因为
STRING(ten)
和STRING(10)
不是兼容的类型,这可能会让这个宏的用户感到困惑。
我尝试了以下方法:
#define STRING(i) \
struct STRING##i \
{ \
_Static_assert( CAT(i, ul) , "must be nonzero literal"); \
size_t len; \
char chars[i]; \
}
它将
ul
附加到文字并使其成为无符号长文字,但对于非文字会失败,因为它使其成为不同的标识符。但问题是,如果用户有另一个名为 constexpr
的 tenul
,例如。
我想知道是否有更好的方法让这个宏失败,除非提供整数文字。
有效标识符以字母字符或下划线开头。有效的整数文字以数字开头。如果有一种方法可以在编译时检查
#i
(宏参数转换为字符串)的第一个字符是否是数字。但据我所知,使用 (#i)[0]
仅在运行时有效。问题被标记为在 6.6 常量表达式中:
从结构体或联合常量开始,成员访问 .如上所述,运算符可用于形成命名常量或复合文字常量。这意味着理论上您可以:
#define IS_LITERAL(i)\
_Static_assert(((constexpr union {unsigned char f, s[sizeof(#i)];}){.s = #i}).f - '0' <= 9,\
"Not numeric literal");
它的作用是创建一个包含 char
字段和
char[]
字段的常量匿名联合,并使用
.
运算符获取
char
字段,该字段将成为
char[]
字段的第一个字符,然后检查字符是否为数字。