Imagine we have three .h files:
f.h:
template <typename T> class Class {public: Class() {} T id(T x) { return x; }};
g.h:
template <typename T> class Class {public: Class() {} T id(T x) { return x + 100; }};
h.h:
template <typename T> class Class {public: Class(); T id(T x); };
Now, we also have three .cpp files:
f.cpp:
#include "f.h"
int f(int x) { Class<int> t; return t.id(x); }
g.cpp:
#include "g.h"
int g(int x) { Class<int> t; return t.id(x); }
h.cpp:
#include "h.h"
int h(int x) { Class<int> t; return t.id(x); }
Compiling them gives us f.o, g.o and h.o. Now let's throw in this main.cpp:
#include <stdio>
extern int f(int);
extern int g(int);
extern int h(int);
int main() {
std::cout << f(1) << std::endl;
std::cout << g(2) << std::endl;
std::cout << h(3) << std::endl;
}
A-a-and let's do g++ main.cpp f.o g.o h.o. Now comes my actual surprise: Since those three .o files contain three different definitions for int Class<int>::id(int), I expect to get a linking error. However, what I get is a working a.out, which prints 1 2 3. And if I reorder .o files in the command, it will print 101 102 103.
And now for the actual questions: How exactly does the linker perform linking in this case? How does it figures out what instantiation of Class<int> to keep and what to throw away? And why it does not complain about multiple definitions?
nm