Alex Rivera | Logout

How object files with templates are linked together

Asked 2013-01-22T12:42:52.727
9

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

Edit
Report

1 Answer

0

Sounds too obvious, but your class is using implicit inlining. That is, when ever you put the source code inside the class declaration, you are "hinting" that you want it inlined. So...

The only things the linker will see are f(),g() and h().

It might be interesting to retry your code with something like this, although it is still so simple, the compiler might simply inline it still (depending on your compiler).

template <typename T> class Class 
{
public: 
     Class() {}
T id(T x);
};

template <typename T> 
T Class::id(T x)
{ 
   return x; 
}
answered 2013-01-22T14:15:33.743

Your Answer