G++ and Templates

Started by
4 comments, last by phresnel 15 years, 3 months ago
Hey, i am using G++ as compiler and try to figure out a way to make a template header only so users of my lib can easily include it into their project. However, it seems like you have to make specific implementations in a file that will be built. Is there a workaround? greetings, Halan
My Blog - http://www.freakybytes.org
Advertisement
Quote:Original post by DrHalan
However, it seems like you have to make specific implementations in a file that will be built. Is there a workaround?


Short answer, no. The implementation of a templated class or function must be fully visible from where the template is instantiated. Further reading.
Templates need to be defined in the same translation unit (a source file after the preprocessing stage) they where declared unless the compiler supports the export keyword which virtual no compiler does (I know just one and it isn't GCC on it's own).
Quote:Original post by snk_kid
... which virtual no compiler does (I know just one and it isn't GCC on it's own).


No really. Most EDG based compilers support it e.g. Intel Compiler.
well I could however export the specialisations trough the shared object. But i hoped that i could but the whole template in the header.
My Blog - http://www.freakybytes.org
Quote:Original post by snk_kid
Templates need to be defined in the same translation unit (a source file after the preprocessing stage) they where declared unless the compiler supports the export keyword which virtual no compiler does (I know just one and it isn't GCC on it's own).


Actually they have to be known where theyy are instantiated, as mentioned sooner.

Say you have the following:

max.h
#ifndef MAX_H__INCLUDED__20090114#define MAX_H__INCLUDED__20090114template <typename T> T max (const T& lhs, const T& rhs) ;#endif


main.cc
#include "max.h"#include <iostream>int main () {    ::std::cout << max (5, 3) << '\n';}


Then upon compiling the translation unit main.cc, the compiler will see if it can find a declaration of a function max() that accepts two integers. Everything is fine.

But upon linking, it (the linker) will search for a definition of max() that accepts two integers.

Say there is a second header, containing:

maxdef.h
#include "max.h"template <typename T> T max <T> (const T& lhs, const T& rhs) {    return lhs > rhs ? lhs : rhs;}


The linker will still fail to find a definition, because templates are "unfolded" (i.e. instantiated) where they are used (but this fails because main.cc did not include maxdef.h, i.e. the template definition), or where they are explicitly instantiated (at that point, the template definition must be available).

So in most compilers you have two choices: 1) #include the definition of the template (called the "inclusion model"), or 2) explicit instantiation (see [VJ]).

As for 1), #include "maxdef.h" into main.cc

As for 2), add another translation unit, and instantiate your function templates (or class templates) by substituting the template parameters manually as its arguments into the template declaration:

maxinst.cc
#include "maxdef.h"template <> max <int> (const int& lhs, const int& rhs);


Compile maxinst.cc, and pass it together with the main unit to the linker. The linker now finds a definition of max() that accepts two integers.

Two things are apparent:
  • Each template-id must be unique accross translation units, hence explicitly instantiate the template for each combination of template parameters once and only once.
  • You have to "hardcode" the parameters for each template parameter combination (but this can be solved in that every source code file can simply #include "maxdef.h" on its own, or by adding more explicit instantiations to maxinst.cc, or other translation units)


The big advantage is that dot-c files are now only required to #include the template declaration in case a matching template-id is given, which is lightyears faster if the template definition doesn't change frequently.

There's also the export keyword, as mentioned, but only EDG implemented it in its c++ frontend [exp] (btw, Vandevoorde works at EDG), and as far as I know, most EDG based compilers like ICC disabled export by default.


References
[VJ] Vandevoorde, Josuttis -- C++ Template - The Complete Guide, Addison Wesley
[exp] Plum, Sutter -- Why we can't afford export

This topic is closed to new replies.

Advertisement