Reputation: 2461
I am newbie in programming with c++ template. I have 3 code files
main.cpp
#include "template_test.h"
#include <iostream>
using namespace std;
int main()
{
mytest<int> mt;
mt.method(1);
system("pause");
return 0;
}
template_test.h
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input){}
};
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
template_test.cpp
#include "template_test.h"
//empty
The code takes effective in VS2013. However when I change my code to 2 sitiuations, there are both something wrong with my code.
1.The first is with the linker error code.
main.cpp
#include "template_test.h"
#include <iostream>
using namespace std;
int main()
{
mytest<int> mt;
mt.method(1);
system("pause");
return 0;
}
template_test.h
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input);
};
template<class T>
void mytest<T>::method(T input)
{
cout << " " << endl;
}//explicit specialization here
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
template_test.cpp
#include "template_test.h"
//empty
2.The second output nothing instead of the correct answer 'ok'.
main.cpp
#include "template_test.h"
#include <iostream>
using namespace std;
int main()
{
mytest<int> mt;
mt.method(1);
system("pause");
return 0;
}
template_test.h
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input){}
};
template_test.cpp
#include "template_test.h"
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}//move from .h to .cpp file here
The strange behaviour of c++ template makes me confused. So, what's the problem?
Upvotes: 2
Views: 136
Reputation: 70037
The first problem is caused by the fact that your explicit specialization
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
is defined in the header file and outside the class definition and without the keyword inline
.
An explicit specialization causes an actual function (rather than a mere template) to be defined. That definition will occur in every translation unit, so if you compile template_test.cpp
and main.cpp
separately, the definition of the function will be included in both object files, causing a multiple-definition error at linking time (because it's a violation of the ODR, the one-definition-rule).
You best avoid this either by including the function definition inside the class template definition (by specializing the entire class template for int
), or using the keyword inline
:
template<>
inline void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
The second problem is caused by the fact that a template specialization must always be declared before it is used:
(14.7.3/6) If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined. [...]
Since your main.cpp
includes the header file, but not the .cpp file, the declaration of the template specialization is not known when it is used in main.cpp
. You solve this best by including the specialization in the header file, either inside the class template definition (by specializing the entire class template for int
), or using the keyword inline
outside the class template definition.
Upvotes: 3
Reputation: 3984
You second question first. Remember a rule when using template. Do not separate the template implementation to a cpp file. Make them all in one .h file.
You first code compiles fine in my VC2012, I am not sure what's wrong with VC2013.
Upvotes: 0