问题描述
当应该内联专业时,我有点困惑。从this的问题中可以清楚地看出,必须内联每个专业化名称,以避免重复的符号错误。但是,如果我想先声明专业化,该怎么办?
如果我们考虑以下示例:
template<typename T>
class myClass
{
public:
static void myPrint(T myVal);
}
#include "declarations.hpp"
//-----------------------------------------------
//declarations.hpp
template<typename T>
void myClass<T>::myPrint(T myVal)
{
cout << "printing unkNown type " << myVal;
}
template <>
void myClass<int>::myPrint(int myVal); //inline here or in deFinition?
template <>
void myClass<float>::myPrint(float myVal); //inline here or in deFinition?
//-----------------------------------------------
//some_file_that_includes_myClass_header.cpp
template <>
void myClass<int>::myPrint(int myVal) //inline or no inline?
{
cout << "printing int " << myVal;
}
//-----------------------------------------------
//some_other_file_that_includes_myClass_header.cpp
template <>
void myClass<float>::myPrint(float myVal) //inline or no inline?
{
cout << "printing float " << myVal;
}
正确的方法是什么?为什么?
解决方法
就像其他问答中提到的那样,专业是它自己的实体。如果您这样做,则在标头中声明特殊化,然后在格式良好的另一个(单个)TU中定义它们。包含该标头的任何TU都会看到int
和float
的专业化只是声明。因此,它们的定义可以放在其他地方,就像非模板函数一样。
如果要使用仅标头的库(在此库中内联定义了专用功能),则必须按照ODR的要求使用inline
说明符。
在您似乎正在询问的意义上,这两种方法都不是“正确”的方法。每种都有自己的优点和缺点。内联定义函数有助于使库仅作为头文件。但是,如果功能复杂,那么所有依赖关系都将拉入每个包含标头的TU中。同样,更改专业将导致所有这些TU都重新编译。因此,有时也需要隐藏实现。您需要根据具体情况进行判断。
,正确的方法是什么?为什么?
由于与模板版本相同的原因,这些专业都需要内联。
如果未内联这些符号,您将在所有包含该标头的编译单元中最终获得这些符号的多个定义。
例如
template <>
inline void myClass<int>::myPrint(int myVal) {
cout << "printing int " << myVal;
}