Consider the following header and source files:
// main.cpp
#include "myClass.h"
int main()
{
MyClass m;
m.foo<double>();
m.foo<float>();
}
// myClass.h
#pragma once
#include <iostream>
using namespace std;
class MyClass
{
public:
template <typename T>
void foo()
{
cout << "Template function<T> called" << endl;
}
template <>
void foo<int>()
{
cout << "Template function<int> called" << endl;
}
template <>
void foo<float>();
};
// myClass.cpp
#include "myClass.h"
template <>
void MyClass::foo<float>()
{
cout << "Template function<float> called" << endl;
}
I get a linking error wrt the foo<float> specialization. If I place the definition of the specialization in the header file, then everything works as expected.
I figured that the reason may be that the method is not explicitly instantiated (although full specialization of template class does not need an explicit instantiation for proper linking). If I try to explicitly instantiate the method, I get this error:
error C3416: ‘MyClass::foo’ : an explicit specialization may not be explicitly instantiated
So the questions are:
- Is there any way to define the specialization in the
cppfile and link properly? - If not, why not? I can explicitly instantiate template methods that
are not specialized just fine. Why not the same for full specializations?
Although WhozCraig’s answer (now deleted) provides the correct code to solve your problem, here are some direct answers to your questions, including comments on your code:
foo<int>()andfoo<float>()are explicit specializations of a member template. Those must not appear inside the definition of the class they belong to. The Standard says:So you must put them after the class definition.
In the case of
foo<int>, which is fully defined in the header file, this implies that you must put the wordinlinebefore the definition; otherwise you will get into trouble with the linker if the header file is included in more than one translation unit.The specialization for
foo<float>()is defined in a separate file that is later linked tomain.cpp. This is possible, but it requires that a declaration of it be given in the header file (you do this already, but you must do it outside the class definition):This is required because of another statement in the Standard:
Since all specializations are explicit (i.e. full specializations, to use your word), there is no need for explicit instantiations, but they are possible (§14.7.2). You would place them at the end of the .cpp file, and the syntax would be:
Again, this is only really useful for types that do not have their own explicit specializations.
The correct code for the header and implementation file therefore looks like this:
.h file:
.cpp: