10

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?

Community
  • 1
  • 1
xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • 1
    In practice, an explicit specialization of a class template does belong in a header file. But the Standard is far from clear about allowing this (maybe it's considered a "class type" for the ODR quote?) – aschepler Dec 03 '17 at 14:36
  • @aschepler but what about [temp.spec]/5? – xskxzr Dec 04 '17 at 03:21
  • It refers to the ODR section, which I take as meaning "see the exact wording there". – aschepler Dec 04 '17 at 13:16

2 Answers2

2

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.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • In [basic.def.odr]/12, maybe a class specialization is regarded as a class type, so the exception applies. But in [temp.spec]/5, it says "an explicit specialization shall be defined at most once in a program" and does not say any exception. I think, if the intent of the standard is to treat a class specialization the same as a class, at least the word is not strict enough. – xskxzr Dec 04 '17 at 03:25
  • It says "at most once (according to ODR)". Maybe they could have been more explicit, but I don't know how to interpret that sentence other than meaning "in exactly the same way as everything else can be defined only once, including the exceptions, as described in the ODR." How else would you interpret "according to ODR"? – Cris Luengo Dec 04 '17 at 14:05
0

This is a definition (the specialization will be instantiated), not a declaration, it probably ought to go in a specific source file (*.cpp):

template <> struct S<int>;

Note: it doesn't "hurt" to have this in every translation unit... other than the time it takes to instantiate by the compiler, and the bloat for the object files (*.o or *.obj).

This is a declaration (the specialization will not be instantiated), and is okay to put in a header file (*.h):

extern template <> struct S<int>;

The declaration requires C++11 or later.

Eljay
  • 4,648
  • 3
  • 16
  • 27
  • The first declaration is not a definition indeed, see http://www.eel.is/c++draft/temp.expl.spec#9 for a similar example. It is the first time I see the grammar for the second declaration, but it still does not compile (see https://wandbox.org/permlink/GjUNNzYDalLpfUzJ, note I use -std=c++1z). – xskxzr Nov 29 '17 at 14:21
  • This is what happens when I try to figure out an answer without a compiler on hand. I blame lack of coffee. I would delete my answer out of shame, but I will leave it as a testament to my decaffeinated incompetence. – Eljay Nov 29 '17 at 22:04
  • definition is a subset of declaration – Chen Li Dec 02 '17 at 03:20