根据 [temp.spec]/5 :
For a given template and a given set of template-arguments,
...
an explicit specialization shall be defined at most once in a program (according to [basic.def.odr]), and
...
类模板的显式(完全)特化的定义不能放在头文件中(否则在包含该头文件的每个翻译单元中都有一个定义,因此整个程序中将有多个定义)。
此外,作为另一个证据,[basic.def.odr]/12 中列出的实体(下面引用)不包含类模板的完整特化。相反,包含“未指定某些模板参数的模板特化”。
There can be more than one definition of a class type, enumeration type, inline function with external linkage ([dcl.inline]), inline variable with external linkage ([dcl.inline]), class template, non-static function template, concept ([temp.concept]), static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified ([temp.spec], [temp.class.spec]) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements.
但是,如果我将定义放在源文件中并将其声明留在标题中,例如,
// "a.h"
template <typename T>
struct S {};
template <>
struct S<int>; // declaration
// "a.cpp"
#include "a.h"
template <>
struct S<int> {}; // definition
// "main.cpp"
#include "a.h"
int main()
{
S<int> s;
}
然后发生错误 ( tested by gcc ) 因为 S<int>
是一个不完整的类型。
总而言之,我应该在哪里定义类模板的显式特化?
最佳答案
我将尝试在这里总结我通过 the discussion in my other answer 学到的知识,希望为这个问题留下一个好的答案,而不是让答案埋在评论中。
标准说
an explicit specialization shall be defined at most once in a program (according to ODR)
ODR 是单一定义规则。您只能在程序中定义每个类一次,但设计允许类定义在每个翻译单元中可用的异常(exception)情况:您可以在不同的翻译单元中定义一个类,只要这些不同的定义是相同的,一个字符一个字符。 OP的引用是ODR描述的一部分,关注the OP's link查看完整说明。
因此 IMO 标准的上述文本意味着显式特化只能定义一次,但根据 ODR,因此有相同的异常(exception):您可以在头文件中定义它,以便它在多个翻译单元中可用。
请注意,如果没有完整的定义,就不可能实例化一个类(编译器至少需要知道要为其分配多少字节)。对于模板化类或此类类的特化也是如此。因此,定义必须可能出现在使用它的每个翻译单元中。
关于c++ - 在 C++ 中,类模板的显式特化定义应该放在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47544299/