我在头文件中专门化模板类的成员函数,如下所示:
#pragma once
#include <iostream>
template<class T>
struct Test
{
void Print() { }
};
template<>
void Test<int>::Print()
{
std::cout << "int" << std::endl;
}
将专门化放在头文件中(没有内联)或者是否应该在cpp文件中是否正确?它如上所示编译得很好(使用VS2012),但我很惊讶我没有得到多个定义链接器错误。
答案 0 :(得分:2)
ODR对 ODR-used 的非内联函数只需要一个定义(粗略意味着,对于函数,可能被称为)。
引用n3485,[basic.def.odr]
4 每个程序都应该只包含一个定义 每个非内联函数或变量,其中使用的是odr 程序;无需诊断。
然后, templates 有一个例外(即不适用于函数):
6 类类型[...],类模板,非静态函数模板,静态数据成员可以有多个定义 类模板,类模板的成员函数或模板特化 在[...]
提供的程序中未指定某些模板参数
[强调我的]
模板的显式特化不是模板。例如,显式专用的类模板是一个类(具有奇怪的名称)。因此,您的假设是正确的,并且明确专门的类模板成员的多个定义违反了ODR。
使用g ++ 4.8.1,我甚至在这样的程序中遇到链接器错误;请注意我有ODR使用该功能。违反ODR无需诊断。
答案 1 :(得分:1)
将标题文件中的特化作为规范形式(如boost
所做),它不会违反ODR。