[英]clang error: non-type template argument refers to function that does not have linkage — bug?
I have some very simple ( C++11 ) code which the latest clang ( version 3.4 trunk 187493 ) fails to compile, but GCC compiles fine. 我有一些非常简单的( C ++ 11 )代码,最新的clang ( 版本3.4 trunk 187493 )无法编译,但是GCC编译得很好。
The code (below) instantiates the function-template foo
with the function-local type Bar
and then tries to use its address as a non-type template parameter for the class-template Func
: 代码(下面)使用函数本地类型
Bar
实例化函数模板foo
,然后尝试将其地址用作类模板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;
}
clang emits the following error: clang发出以下错误:
error : non-type template argument refers to function 'foo' that does not have linkage
错误 :非类型模板参数是指没有链接的函数'foo'
However, if I move type Bar
to global scope (by taking it out of the function), then clang compiles it fine, proving the issue is with the type being function-local . 但是,如果我将类型
Bar
移动到全局范围(通过将其从函数中取出),则clang编译它很好,证明问题是函数本地的类型。
So is clang correct to emit this error, or does the standard not support this (in which case GCC is being too lenient by allowing it)? 那么clang是否正确发出此错误,或者标准是否不支持这种情况(在这种情况下,GCC通过允许它过于宽松)?
using
declaration moved from foo<Bar>()
scope to main()
scope):
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; }
By definition of no linkage in C++.11 §3.5 Program and linkage ¶2, I originally believed foo<Bar>
has no linkage since it cannot be referred to by name by any other scope except that which defined the type Bar
(ie, main()
). 根据C ++中没有链接的定义.11§3.5 程序和链接 ¶2,我原本认为
foo<Bar>
没有链接,因为它除了定义类型Bar
(即main()
之外的任何其他范围都不能通过名称引用main()
)。 However, this is not correct. 但是,这是不正确的。 This is because the definition of a name with external linkage is described as:
这是因为具有外部链接的名称的定义描述为:
When a name has external linkage , the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
当名称具有外部链接时 ,其表示的实体可以通过其他翻译单元的范围或同一翻译单元的其他范围中的名称来引用。
And for a template function, this will always be the case. 对于模板功能,情况总是如此。 This is because there is one other scope from which the name can be referred.
这是因为可以引用名称的另一个范围。 Namely, the template function can refer to itself.
即,模板功能可以参考其自身。 Therefore,
foo<Bar>
has external linkage. 因此,
foo<Bar>
具有外部链接。 zneak's answer, EDIT 2 , has an e-mail thread with the clang developers confirming that foo<Bar>
should have external linkage. zneak的回答,编辑2 ,有一个电子邮件线程与clang开发人员确认
foo<Bar>
应该有外部链接。
Thus, from C++.11 §14.3.2 Template non-type arguments ¶1: 因此,从C ++。11§14.3.2 模板非类型参数 ¶1:
A template-argument for a non-type, non-template template-parameter shall be one of: ...
模板参数的一个非类型,非模板的模板参数应是一个:...
a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-id s but excluding non-static class members, expressed (ignoring parentheses) as &
id-expression , except that the&
may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference;一个常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部链接的对象的地址,或具有外部或内部链接的函数,包括函数模板和函数模板ID,但不包括非静态类成员,表达(忽略括号)作为
&
ID表达 ,除了&
如果名称是指功能或阵列,并且如果相应的模板的参数是一个参考将被省略可省略; ......
The most relevant bullet is the third bullet. 最相关的子弹是第三个子弹。 Since
foo<bar>
has external linkage, passing it as a non-type template-parameter should be fine. 由于
foo<bar>
具有外部链接,因此将其作为非类型模板参数传递应该没问题。
I'm late to the party, but standard says that type-local functions don't have linkage (§3.5:8): 我迟到了,但标准说类型本地函数没有链接(§3.5:8):
Names not covered by these rules have no linkage.
这些规则未涵盖的名称没有链接。 Moreover, except as noted, a name declared at block scope (3.3.3) has no linkage .
此外,除非另有说明,否则在块范围(3.3.3)中声明的名称没有链接 。
Same section goes on to say: 同一节继续说:
A type without linkage shall not be used as the type of a variable or function with external linkage unless
除非使用没有链接的类型,否则不应将其用作具有外部链接的变量或函数的类型
- the entity has C language linkage (7.5), or
该实体具有C语言链接(7.5),或
- the entity is declared within an unnamed namespace (7.3.1) , or
实体在未命名的命名空间(7.3.1)中声明 ,或
- the entity is not odr-used (3.2) or is defined in the same translation unit.
该实体不是使用过的(3.2)或在同一翻译单元中定义。
And, as a matter of fact, Clang will allow this: 而且,事实上,Clang将允许:
namespace
{
template<void (*FUNC_PTR)(void)>
struct Func {};
template<typename T>
void foo() {}
}
int main() {
struct Bar {}; // function-local type
Func<foo<Bar>> x;
}
And will reject it without the anonymous namespace. 并且将在没有匿名命名空间的情况下拒绝它。
EDIT 1 : As jxh notes, the names are also defined in the same translation unit, so I'm not sure what to think of this one. 编辑1 :正如jxh所说,名称也在同一个翻译单元中定义,所以我不确定该怎么想这个。
EDIT 2 : The guys at clang confirm it's a bug. 编辑2 : clang的家伙确认这是一个错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.