2

I saw an interesting thing but couldn't understand why.

template<class dataType>
Class A
{
AFnc();
}

template<> A<int>::AFnc() { }

Using only specialized template generates an error saying multiple definition of the same function. And it says it was generated at the same place. But if I add

template<class dataType>
A<dataType>::AFnc()
{
}

Then it gets rid of the error.

Why ? Could someone please explain this behavior.

4

2 回答 2

6

(您需要清理语法。我假设实际代码没有所有这些语法错误。)

模板函数的显式特化不再是模板,因为它不再依赖于任何模板参数。从单一定义规则 (ODR) 的角度来看,它是一种“普通”功能。而且,作为一个“普通”函数,它必须在头文件中声明,并且在某个实现文件中只定义一次。您显然在头文件中定义了您的专业化,如果头文件包含在多个翻译单元中(例如您的“多个定义”错误),这就是导致 ODR 违规的原因。

在您的示例中,template<> void A<int>::AFnc()(我添加void为返回类型)不再是模板。这意味着这个定义

template<> void A<int>::AFnc() { }

必须从头文件移动到某个实现文件。同时,在头文件中,您必须为此函数保留一个非定义声明

template<> void A<int>::AFnc(); // <- note, no function body

让编译器知道存在这种专门化。

一般来说,记住一个简单的规则:如果你的函数模板仍然依赖于一些未指定的模板参数,那么它就是一个真正的模板,它必须在头文件中定义。但是一旦你“修复”了所有参数(通过显式特化),它就不再是一个模板。它变成了一个普通函数,必须在头文件中声明,并且在某个实现文件中只定义一次。

PS 以上适用于非内联函数。内联函数可以(并且通常应该)在头文件中定义。

PPS 相同的逻辑适用于模板类的静态数据成员的显式特化。

于 2013-07-10T16:20:59.253 回答
2

我猜,您将显式实例化放在头文件中。然后在包含该文件的每个翻译单元中发出其代码。只需移动此代码

template<> A<int>::AFnc() { }

到 .cpp 文件,它只会被发射一次。使用模板方法不会出现此错误,因为隐式实例化的规则不同。

于 2013-07-10T16:22:13.813 回答