跨多个命名空间的 clang 错误 "explicit instantiation does not refer to a function template"
clang error "explicit instantiation does not refer to a function template" across multiple namespaces
我正在尝试在我自己的命名空间中重新使用来自某个命名空间的现有模板化函数,并出于代码覆盖原因显式实例化它们。
以下代码使用 gcc 9.3 编译但不使用 clang 10.0.0
编译
namespace bar {
template<typename T>
T func(T arg){ return arg;};
}
namespace foo {
using bar::func;
}
template int foo::func<int>(int);
int main()
{ }
查看示例here
如果我将模板函数实例化为
template int bar::func<int>(int);
clang 也可以编译。但这不是我想要的。
是否可以使用 clang 跨命名空间显式实例化模板函数?
为什么gcc和clang给出不同的结果?
恐怕你不能那样做。 Clang 是正确的。
[temp.explicit]
2 The syntax for explicit instantiation is:
explicit-instantiation:
externopt template declaration
4 If the explicit instantiation is for a class or member class,
the elaborated-type-specifier in the declaration shall include a
simple-template-id; otherwise, the declaration shall be a
simple-declaration whose init-declarator-list comprises a single
init-declarator that does not have an initializer.
这一段告诉我们,template
关键字之后的位必须在句法和语义上都是对某物的有效声明(并且不能包含此处不相关的初始值设定项)。声明有几个部分,但这里感兴趣的是声明的 declarator 部分。
关于这一点,我们有以下段落
[dcl.meaning] (emphasis mine)
1 A declarator contains exactly one declarator-id; it names the
identifier that is declared. An unqualified-id occurring in a
declarator-id shall be a simple identifier except for the declaration
of some special functions ([class.ctor], [class.conv], [class.dtor],
[over.oper]) and for the declaration of template specializations or
partial specializations ([temp.spec]). When the declarator-id is
qualified, the declaration shall refer to a previously declared member
of the class or namespace to which the qualifier refers (or, in the
case of a namespace, of an element of the inline namespace set of that
namespace ([namespace.def])) or to a specialization thereof; the
member shall not merely have been introduced by a using-declaration in
the scope of the class or namespace nominated by the
nested-name-specifier of the declarator-id.
由于显式模板实例化中的 declarator-id 是 foo::func
,因此它不遵循我用粗体标记的句子中列出的规则。这使您尝试显式实例化 ill-formed.
GCC 应该也拒绝了你的尝试。
我正在尝试在我自己的命名空间中重新使用来自某个命名空间的现有模板化函数,并出于代码覆盖原因显式实例化它们。
以下代码使用 gcc 9.3 编译但不使用 clang 10.0.0
编译namespace bar {
template<typename T>
T func(T arg){ return arg;};
}
namespace foo {
using bar::func;
}
template int foo::func<int>(int);
int main()
{ }
查看示例here
如果我将模板函数实例化为
template int bar::func<int>(int);
clang 也可以编译。但这不是我想要的。
是否可以使用 clang 跨命名空间显式实例化模板函数?
为什么gcc和clang给出不同的结果?
恐怕你不能那样做。 Clang 是正确的。
[temp.explicit]
2 The syntax for explicit instantiation is:
explicit-instantiation: externopt template declaration4 If the explicit instantiation is for a class or member class, the elaborated-type-specifier in the declaration shall include a simple-template-id; otherwise, the declaration shall be a simple-declaration whose init-declarator-list comprises a single init-declarator that does not have an initializer.
这一段告诉我们,template
关键字之后的位必须在句法和语义上都是对某物的有效声明(并且不能包含此处不相关的初始值设定项)。声明有几个部分,但这里感兴趣的是声明的 declarator 部分。
关于这一点,我们有以下段落
[dcl.meaning] (emphasis mine)
1 A declarator contains exactly one declarator-id; it names the identifier that is declared. An unqualified-id occurring in a declarator-id shall be a simple identifier except for the declaration of some special functions ([class.ctor], [class.conv], [class.dtor], [over.oper]) and for the declaration of template specializations or partial specializations ([temp.spec]). When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace ([namespace.def])) or to a specialization thereof; the member shall not merely have been introduced by a using-declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id.
由于显式模板实例化中的 declarator-id 是 foo::func
,因此它不遵循我用粗体标记的句子中列出的规则。这使您尝试显式实例化 ill-formed.
GCC 应该也拒绝了你的尝试。