[英]Specialisations of class template members
我有一个包含包含模板成员的类和该成员的一些特殊化的类的标头:
#include <iostream>
class Foo {
public:
template<typename T>
void print(const T& t) {
std::cout << t << std::endl;
}
};
template<>
void Foo::print<int>(const int& t) {
std::cout << t << std::endl;
}
此标头包含在多个源文件中。
如果我将专业化放在类定义中,那么GCC会抱怨:
error: explicit specialization in non-namespace scope ‘class Foo’
但是,如果我将专业化移到类定义之外,那么VC ++就会抱怨多重定义符号。
两个编译器都会满意的正确做法是什么?
显式专门化的模板功能不再是模板(它不再依赖于任何模板参数)。 因此,它遵循“一个定义规则”作为普通功能。 这意味着在整个程序中,只应一次对显式专门功能的定义进行一次定义 。 即,您必须将定义放入实现文件( .cpp
文件)中。
但是,您仍然必须在头文件中声明此特化(以告诉编译器它实际上已经存在)。 即在头文件中,您必须执行
template<>
void Foo::print<int>(const int& t);
(请注意,根据标准要求,应在名称空间范围内,即在类定义之外进行。)
然后在一个实施文件中
template<>
void Foo::print<int>(const int& t) {
std::cout << t << std::endl;
}
PS当然,与其他任何函数一样,您可以inline
声明它并将定义保留在头文件中。
该标准规定(§14.7.3/ 12):
仅当使用内联说明符声明或定义为已删除时,函数模板的显式特化才是内联的,而与其功能模板是否为内联无关。
ODR将功能模板的特殊化视为正常功能(无特殊化)。 如果您在标头中定义特殊化,则必须使用inline
说明符对其进行声明,以便多个翻译单元可以包含它。
如果要在源文件中定义它,则必须在标头(在名称空间范围)内声明特殊化:
template<>
void Foo::print<int>(const int&);
并将定义放在源文件中
template<>
void Foo::print<int>(const int& t)
{
std::cout << t << std::endl;
}
,就像您习惯使用常规功能一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.