In both cases you are doing an explicit instantiation. In the second case, only ABC<char>::foo
is being instantiated, while in the first case ABC<char>::bar
is also being instantiated.
A different similar example may clarify the implications:
// 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 the example, in main
the compiler cannot see foo
nor bar
definitions, so it cannot instantiate the methods. The compiler, when processing main.cpp will accept the code in main gladly, since you are telling it that ABC
is 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 bar
undefined. So any code that includes test.h, links against the compiled test.cpp and uses only foo
method will compile and link, but usage of bar
will 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.