宏计数(字符)参数

时间:2011-08-08 04:45:53

标签: c++ c macros

我有一个宏将字符串转换为字符列表:

#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(任意文本)。任何想法或解决方案?

3 个答案:

答案 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循环或其他任何东西的界限,编译器应该能够完美地优化所有内容。