See the following code and please clear my doubts.
-
As ABC is a template, why does it not show an error when we put the definition of the ABC class member function in test.cpp?
-
If I put test.cpp code in test.h and remve 2, then it works fine. Why?
.
// test.h
template <typename T>
class ABC {
public:
void foo( T& );
void bar( T& );
};
// test.cpp
template <typename T>
void ABC<T>::foo( T& ) {} // definition
template <typename T>
void ABC<T>::bar( T& ) {} // definition
template void ABC<char>::foo( char & ); // 1
template class ABC<char>; // 2
// main.cpp
#include "test.h"
int main() {
ABC<char> a;
a.foo(); // valid with 1 or 2
a.bar(); // link error if only 1, valid with 2
}
In both cases you are doing an explicit instantiation. In the second case, only
ABC<char>::foois being instantiated, while in the first caseABC<char>::baris also being instantiated.A different similar example may clarify the implications:
In the example, in
mainthe compiler cannot seefoonorbardefinitions, so it cannot instantiate the methods. The compiler, when processing main.cpp will accept the code in main gladly, since you are telling it thatABCis a template and that it has those two functions, and will assume that they will be defined in some other translation unit.In the translation unit that contains test.cpp the compiler is seeing both method definitions, and the both of the instantiations (method/class) can be fully processed. If only the method instantiation ([1]) is present, the compiler will only generate that method, and will leave
barundefined. So any code that includes test.h, links against the compiled test.cpp and uses onlyfoomethod will compile and link, but usage ofbarwill fail to link due to it being undefined.Explicitly instantiating the class template generates the symbols for all the member methods, and in that case, any translation unit that includes test.h and links against the compiled test.cpp object file will both compile and link.