区分字符串文字和运行时生成的字符串的方法

Kan*_* Li -4 c++ templates string-literals c++11

假设我有一个函数,它接受一个字符串作为输入:

SomeOutputType f_impl(const char* s);
Run Code Online (Sandbox Code Playgroud)

大多数呼叫站点只使用字符串文字作为输入,例如f("Hello, world").假设我已经实现了以下函数来在编译时计算结果

template <char...> SomeOutputType f_impl();
Run Code Online (Sandbox Code Playgroud)

我的问题是,有没有办法让调用网站像f("Hello, world")调用模板形式,而对于一般调用网站,如string s="Hello, world"; f(s.c_str());调用一般形式?为了澄清,auto s = "Hello, world"; f(s);不必调用模板化形式,因为s它现在是一个变量而不再是编译时常量.

这个问题的一个有用的例子是优化printf.在大多数情况下,format将是字符串文字,因此可以在编译时完成很多事情来优化事物,而不是format在运行时解析.

Joh*_*itb 17

不,字符串文字"foo"的类型const char[S + 1]在哪里S是您编写的字符数.它的行为类似于没有特殊规则的那种类型的数组.

在C++ 03中,有一个特殊规则表示字符串文字可以转换为char*.这让你说

#define isStringLiteral(X) \
  isConvertibleToCharStar(X) && hasTypeConstCharArray(X)
Run Code Online (Sandbox Code Playgroud)

例如isStringLiteral(+"foo"),屈服false,isStringLiteral("foo")并将产生真实.即使这种可能性也不允许您使用字符串文字参数调用函数并且行为方式不同.

C++ 11删除了特殊的转换规则,字符串文字的行为与任何其他数组一样.在C++ 11中,作为一个肮脏的黑客,你可以编写一些宏,匹配一些简单的字符串文字而不处理转义序列

constexpr bool isStringLiteral(const char *x, int n = 0) {
  return *x == '"' ? 
           n == 0 ?
             isStringLiteral(x + 1, n + 1)
             : !*(x + 1) 
           : (*x && n != 0 && isStringLiteral(x + 1, n + 1));
}

#define FastFun(X) \
  (isStringLiteral(#X) ? fConstExpr(X, sizeof(X) - 1) : f(X))
Run Code Online (Sandbox Code Playgroud)

  • @icando不,我不会删除它.它正确地解释了为什么不可能做你要求的.我可以理解你发现它不起作用令人沮丧,但是没有答案而不是答案表明它不起作用将不会改变它. (12认同)
  • @icando:是的,这是完全正确的.你是"C++超级专家". (6认同)
  • @icando别担心.它可能对其他人有用. (4认同)
  • @icando:Johannes Schaub是一位世界知名的C++专家,他为标准委员会本身贡献了大量的专业知识,所以你可能希望花更少的时间来责怪每个人做错事,还有更多的时间来试图去做你是做错了什么的. (4认同)
  • @icando我现在正在调用[Godwin定律](http://en.wikipedia.org/wiki/Godwin's_law).讨论; 你输了. (4认同)
  • 我不知道.这家伙可能很棒.他应该开始一个教派.这将是超级有效的 (3认同)
  • @icando绝对,对权威的诉求是一个微弱的论点.让选民决定怎么样? (2认同)