这个问题提到了我之前的问题:clang does not compile my code, but g++ does。从我的研究中,问题归结为联系,静态变量data
在下面的示例中是否具有链接(它与g++-4.8.1
编译)?为什么它具有链接(否则我无法使用非类型模板参数进行实例化)?
template <int const* ptr>
void foo()
{
}
typedef void (*func_type)();
template <int = 0>
void run_me()
{
static int data;
func_type const f1 = foo<&data>;
// auto f2 = foo<&data>; // doesn't work with gcc
// foo<&data>(); // doesn't work with gcc
}
int main(int, char*[])
{
run_me();
return 0;
}
标准的强制性引用:
非类型非模板模板参数的模板参数应为以下之一: ...
- 一个常量表达式(5.19),用于指定具有静态存储持续时间和的对象的地址 外部或内部链接或具有外部或内部链接的功能,包括功能模板 和函数template-ids但不包括非静态类成员,表示(忽略括号)为 &安培; id-expression,除了&amp;如果名称引用函数或数组,则可以省略 如果相应的模板参数是引用,则省略;要么 ...
答案 0 :(得分:3)
当然,在函数中声明的静态变量(无论它是否是模板函数)都没有链接。
§3.5段。 8:“除非另有说明,否则在块范围内声明的名称(3.3.3)没有链接”
据我所知,该条款中列出的唯一例外情况见第7段。 6:“在块作用域中声明的函数的名称和由块作用域extern声明声明的变量的名称具有链接。”
但是,14.3.2可能会在某个时候放松。
DanielKrügler于2012-02-01提交了DR 1451:
根据14.3.2 [temp.arg.nontype]第1段子弹3,只有具有连接的对象才能用于形成非类型模板参数。这个限制仍然需要吗?使用块范围对象作为模板参数会很方便。
DR是因为它是扩展请求而关闭的,应由Evolution工作组处理。它似乎已包含在n3413,“允许非类型模板参数的任意文字类型”中。
因此,当然可以想象一个或多个C ++编译器可能会选择对非类型模板参数实施更宽松的限制。