Jump to content
  • Advertisement
Sign in to follow this  
DrHalan

G++ and Templates

This topic is 3475 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
well I could however export the specialisations trough the shared object. But i hoped that i could but the whole template in the header.

Share this post


Link to post
Share on other sites
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__20090114
template <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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!