clang错误:非类型模板参数是指没有链接的函数 - bug?

eth*_*ice 9 c++ gcc templates clang c++11

我有一些非常简单的(C++ 11)代码,最新的clang(版本3.4 trunk 187493)无法编译,但GCC编译得很好.

代码(下面)foo使用函数本地类型 实例化函数模板,Bar然后尝试将其地址用作类模板的非类型模板参数Func:

template<void(*FUNC_PTR)(void)>
struct Func {};

template<typename T> extern inline
void foo() {
    using Foo = Func<foo<T>>;
}
int main() {
    struct Bar {}; // function-local type
    foo<Bar>();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

clang发出以下错误:

错误:非类型模板参数是指没有链接的函数'foo'

但是,如果我将类型移动Bar到全局范围(通过将其从函数中取出),则clang可以很好地编译它,证明问题在于函数本地类型.

那么clang是否正确发出此错误,或者标准是否不支持这种情况(在这种情况下,GCC通过允许它过于宽松)?


编辑#1:要清楚,这不是这个问题的重复,因为在C++ 11中删除了'不能使用本地类型作为模板参数'限制.但是,仍然不清楚使用本地类型是否涉及链接问题,以及发出此错误时clang是否正确.


编辑#2:已经确定clang对于上面的代码发出错误是正确的(参见@jxh的回答),但它错误地也为下面的代码发出错误(using声明从foo<Bar>()范围移到main()范围):

template<void(*FUNC_PTR)(void)>
struct Func {};

template<typename T> extern inline
void foo() {}

int main() {
    struct Bar {};
    using F = Func<foo<Bar>>;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

jxh*_*jxh 3

根据C++.11 §3.5程序和链接¶2 中无链接的定义,我最初认为没有链接,因为除了定义类型的范围(即)之外,任何其他范围都不能按名称引用它。然而,这是不正确的。这是因为具有外部链接的名称的定义描述为:foo<Bar>Barmain()

当名称具有外部链接时,它所表示的实体可以通过其他翻译单元范围或同一翻译单元的其他范围的名称来引用。

对于模板函数来说,情况总是如此。这是因为还有另一个范围可以引用该名称。即,模板函数可以引用自身。因此,foo<Bar>具有外部联系。zneak 的答案 EDIT 2有一个电子邮件线程与 clang 开发人员确认foo<Bar>应该具有外部链接。

因此,从 C++.11 §14.3.2模板非类型参数¶1:

非类型、非模板模板参数的模板参数应为以下之一: ...

  • 一个常量表达式 (5.19),指定具有静态存储持续时间和外部或内部链接的对象或具有外部或内部链接的函数的地址,包括函数模板和函数模板ID ,但不包括非静态类成员,表示为 (忽略括号)作为&id-expression,但&如果名称引用函数或数组,则可以省略 ;如果相应的模板参数是引用,则应省略;...

  • 最相关的项目符号是第三个项目符号。由于foo<bar>具有外部链接,因此将其作为非类型模板参数传递应该没问题。