Pap*_*ter 19 c++ string templates string-literals compile-time
假设我们有一个带有非类型参数的模板函数,const char *
如下所示:
template <const char * MESSAGE> void print() {
std::cout << MESSAGE << '\n';
}
Run Code Online (Sandbox Code Playgroud)
使用此模板不会像日志那样成为MESSAGE
可以在编译时推断出来的问题,因此以下用法是合法的:
namespace {
char namespace_message[] = "Anonymous Namespace Message";
constexpr char namespace_constexpr_message[] = "Anonymous Namespace Constexpr Message";
}
char message[] = "Message";
constexpr char constexpr_message[] = "Constexpr Message";
int main()
{
print<namespace_message>();
print<namespace_constexpr_message>();
print<message>();
print<constexpr_message>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但下面的那些不是(见这里):
namespace {
const char namespace_const_message[] = "Anonymous Namespace Const Message";
}
const char const_message[] = "Const Message";
int main()
{
print<namespace_const_message>();
print<const_message>();
print<"Literal">();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面代码生成的错误如下:
'{anonymous} :: namespace_const_message'的值在常量表达式中不可用
我不明白为什么namespace_const_message
不能在常量表达式中使用的同时namespace_message
是; 如果我必须赌他们其中一个不能用于常数表达式,我会打赌没有常数,但是已经作为常量表达的那个!
注意:'{anonymous} :: namespace_const_message'未被声明为'constexpr'
namespace_message
既未被声明为constexpr
并且被用于常量表达式,其值在编译时推断出来.如果没有const constexpr
,那么为什么需要表达式const
而不是必需的?
同样适用于匿名命名空间之外的值,我试图强制编译时constness将值放入内部链接空间,但显然我失败了.
最后,最后一个错误:
'"Literal"'不是类型'const char*'的有效模板参数,因为在此上下文中永远不能使用字符串文字
所以,令人惊讶的是(至少对我来说这是一个惊喜)字符串文字不能用作模板参数,但只要字符串(好吧,指向以null结尾的字符数组的指针)是编译时的值它可以用作非类型模板参数,因此:只要"它们是左值",它们就可以在编译时使用(但它们已经是左值!).
我试图猜测为什么在这种情况下永远不能使用字符串文字,我最好的猜测是两个具有相同内容的字符串文字不是相同的文字(因为指向内容的指针可能不同)而两个积分文字是相同的(它们是一个值,而不是一个指向值的指针).
那么,这里的问题是什么?
namespace_const_message
和const_message
不可在编译时间,从而在禁print
模板函数?谢谢.
Jam*_*nze 12
模板的实例化变量需要具有外部链接,并且const
是隐式内部链接.所以你必须写:
extern char const constMessage[] = "Const message";
Run Code Online (Sandbox Code Playgroud)
(另一种选择是它是一个静态类成员.静态类成员总是有外部链接.)
字符串文字的情况在某些方面类似:它们的类型是
char const[]
.但更糟糕的是:模板实例化(至少是早期版本)需要一个名称,而字符串文字则没有名称.更重要的是,未指定相同的字符串文字是否是同一个对象,因此在下面:
template <char const* m>
struct Toto { char const* f() const; };
Toto <"titi"> t1;
Toto <"titi"> t2;
Run Code Online (Sandbox Code Playgroud)
这将是不确定是否t1
与t2
有相同类型或不.