views:

54

answers:

2

With this question I'd like to better understand how C++ templates system works with regards to this question.

As far as I know, template-based classes and functions are usually placed into header files. This is due to the technical issue of managing generic data types, which characterstics are unknown in principle. As soon as they are known, the compiler can generate the executable code which is suited for the required data type.

In the header file something.h, our class shall be defined as follows:

template <typename T>
class Something
{
    public:
        void setElement (T &elem) {
            element = elem;
        }
        T getElement () {
            return element;
        }
    private:
        T element;
};

Now let's suppose to split source and class definition:

The following class definition will be written in something.h:

template <typename T>
class Something
{
    public:
        void setElement (T &elem);
        T getElement ();
    private:
        T element;
};

While the following methods will be written in something.cpp:

#include "something.h"

template <typename T>
void Something<T>::setElement (T &elem)
{
    element = elem;
}

template <typename T>
T Something<T>::getElement ()
{
    return element;
}

Unless we declare some specific-type instances inside something.cpp, if we compile it as object file we won't obtain any text section inside it:

dacav@mithril:<tmp>$ g++ something.cpp  -c
dacav@mithril:<tmp>$ objdump -D something.o 

something.o:     file format elf64-x86-64


Disassembly of section .comment:

0000000000000000 <.comment>:
   0:   00 47 43                add    %al,0x43(%rdi)
   3:   43 3a 20                rex.XB cmp    (%r8),%spl
...
...
  20:   34 2e                   xor    $0x2e,%al
  22:   31 00                   xor    %eax,(%rax)
dacav@mithril:<tmp>$

As Martin York shows we can force the compiler to generate the code for some specific data types in order to control which types can be used and which cannot. But what if we don't want any restriction?

+1  A: 

You're stuffed, in short. The Standard did define an "export" keyword, that was supposed to export instantiable (i.e., the raw form, not a specific type) templates from a file. However, the reality is that virtually no major compilers support it and said that they would never support it. Therefore, it was removed from C++0x.

DeadMG
How should the "export" keyword technically work?
Dacav
@Dacav: Technically, you should be able to write export template<typename T> std::vector; for example, and then the compiler can read the .cpp file for std::vector's implementation. Effectively, an exported template obeys the same declaration and definition rules as a normal class.
DeadMG
+2  A: 

If you want to be able to instantiate a template for arbitrary types, simply put everything that is needed for the instantiation in the header file. This means to put the function bodies (which need to be available to be instantiated) in the header file, not in a .cpp file.

If you want declarations and definitions in separate files simply for better structuring of the source code, you could use a scheme like this:

something.h

// Just the declaration

template<typename T>
class Something {
  void foo();
};

// include the header file with the definitons
#include "something.impl.h"

something.impl.h

// Put definitions here

template<typename T>
void Something<T>::foo() {
}
sth
+1 for the awesome splitting trick!
Dacav