繁体   English   中英

类模板成员的专业化

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM