我有一个宏将字符串转换为字符列表:
#define TO_STRING(x) #x
#define CHAR_LIST_7(x) TO_STRING(x)[0] \
, TO_STRING(x)[1] \
, TO_STRING(x)[2] \
, TO_STRING(x)[3] \
, TO_STRING(x)[4] \
, TO_STRING(x)[5] \
, TO_STRING(x)[6]
e.g。用法: “CHAR_LIST_7(鸡)”给出''c','h','i','c','k','e','n'“所以它可以用在模板之类的东西上(例如:{{ 3}})
但是,我想对任意数量的字符进行概括(并且不需要手动计算字符数)?所以我可以简单地去:CHAR_LIST(任意文本)。任何想法或解决方案?
答案 0 :(得分:3)
您无法在预处理期间拆分令牌,只能将它们组合在一起(使用##
)。
将标识符转换为字符串文字也无济于事,因为在预处理期间无法将字符串文字拆分,也无法对字符串文字执行操作(例如计算长度)。
在预处理期间,编译器知道一个标记是一个字符串文字,它是什么样的文字,但它还不知道它的完整类型和长度,至少不是宏可以访问的方式。
答案 1 :(得分:1)
一般来说,你要求分裂的方式是不可能的。最好的方法是将参数提供给template
:
Literal<'c','h','i','c','k','e','n'>::print();
我知道打字会多一点。为了克服这个问题,您可以编写一个简单的程序,它将chicken
之类的字符串文字作为参数,并将其输出到'c'
,'h'
,'i'
,...等。类似的东西:
int main(int argc, char **argv)
{
if(argc != 2)
return 0;
const char *s = argv[1];
int length = strlen(s)-1;
for(int i = 0; i < length; i++)
cout<<s[i]<<",";
cout<<s[length]<<endl;
}
但是,由于template
参数中的分裂字符,没有解决方案的详细程度。
答案 2 :(得分:1)
不,正如James已经说过的那样,没有办法在预处理器中拆分令牌或让它知道字符串的长度。
但我认为对于您的用例,在任何情况下根本不需要。通过使用#x
对参数进行字符串化处理所得到的字符串是一个常量大小的字符串,例如chicken
会导致"chicken"
只有char[8]
类型。这样一个字符串的长度是编译时常量,您只需使用sizeof
检测它:
#define TOKLEN(TOK) (sizeof(#TOK)-1)
在C中使用这样的东西会“简单地”看
#define SCARY(TOK) for (size_t i = 0; i < TOKLEN(TOK); ++i) printf("%c:", #TOK[i])
因为TOKLEN(TOK)
是编译时常量,所以编译器可以在适当时展开它。
在C ++的用例中使用它
template < size_t n >
class constLenString {
size_t const len = n;
char const* str;
constLenString(char* s) : str(s) { }
};
#define defConstLenString(TOK, NAME) constLenString< TOKLEN(TOK) > NAME(#TOK)
(未经测试,我的C ++生锈了)
现在用
defConstLenString(chicken, chick);
chick.n
是一个常量,可以是for
循环或其他任何东西的界限,编译器应该能够完美地优化所有内容。