According to [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
...
the definition of an explicit (full) specialization of a class template cannot be placed in a header (otherwise there is one definition in each translation unit containing this header, thus there will be more than one definition in the whole program).
In addition, as another evidence, the entities listed in [basic.def.odr]/12 (blockquoted below) do not contain a full specialization of a class template. Instead, "template specialization for which some template parameters are not specified" is contained.
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.
However, if I place the definition in a source file and leave its declaration in a header, for example,
// "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;
}
then an error occurs (tested by gcc) because S<int>
is an incomplete type.
In conclusion, where should I place the definition of an explicit specialization of a class template?
Templates in C++ is an interesting feature that is used for generic programming and templates in c++ is defined as a blueprint or formula for creating a generic class or a function. Simply put, you can create a single function or single class to work with different data types using templates.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
A template is a simple yet very powerful tool in C++. The simple idea is to pass data type as a parameter so that we don't need to write the same code for different data types. For example, a software company may need to sort() for different data types.
A template is a C++ entity that defines one of the following: a family of classes (class template), which may be nested classes. a family of functions (function template), which may be member functions.
I am going to try to summarize here what I've learned through the discussion in my other answer, in the hopes of leaving a good answer to this question, rather than having the answer be buried in the comments.
The standard says
an explicit specialization shall be defined at most once in a program (according to ODR)
ODR is the One Definition Rule. You can only define each class once within a program, with an exception designed to allow a class definition to be available in each translation unit: you can define a class in different translation units as long as these different definitions are identical, character for character. The quote of the OP is part of the ODR description, follow the OP's link to see the full description.
So IMO the standard's text above means that an explicit specialization can be defined only once, but according to the ODR, and thus with the same exceptions: you can define it in a header file so it is available in multiple translation units.
Note that it is not possible to instantiate a class without its full definition (the compiler needs to know at least how many bytes to allocate for it). The same is true for a templated class, or a specialization of such a class. So it must be possible for the definition to be present in each translation unit that uses it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With