Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reconcile the C++ idiom of separating header/source with templates?

Tags:

I'm wondering a bit about this templating business.

In C and C++ it is very common to put declarations in header files and definitions in source files, and keep the two completely separate. However, this doesn't even seem to be possible (in any great way) when it comes to templates, and as we all know, templates are a great tool.

Also, Boost is mostly headers, so this is a real issue. Is separating headers and source still a good idea in C++, or should I just not rely heavily on templates?

like image 401
Max Avatar asked Feb 09 '11 20:02

Max


People also ask

Why templates are defined in header files?

To have all the information available, current compilers tend to require that a template must be fully defined whenever it is used. That includes all of its member functions and all template functions called from those. Consequently, template writers tend to place template definition in header files.

How are C++ templates implemented?

A class template is instantiated by passing a given set of types to it as template arguments. The C++ Standard Library contains many class templates, in particular the containers adapted from the Standard Template Library, such as vector .

Why are header files separate?

The need for header files results from the limitations that the compiler has for knowing about the type information for functions and or variables in other modules. The compiled program or library does not include the type information required by the compiler to bind to any objects defined in other compilation units.

Why can't we compile template code into its own .O file?

Because the templates are not functions, they can't be compiled separately.


2 Answers

Instantiating a template is costly at compile time but virtualy free at runtime. Basically, everytime you use a new template type, the compiler has to generate the code for that new type, that's why the code is in a header, so that the compiler have access to the code later.

Putting all your code in a .cpp lets the compiler compile that code only once which greatly speeds up compilation. You could in theory write all your code in headers, it will work fine, but it will take forever to compile very large projects. Also, as soon as you will change one line anywhere, you will have to rebuild everything.

Now you might ask, how comes the STL and BOOST are not so slow? That's where precompiled headers come to the rescue. PCHs let the compiler do the most costly work only once. This works well with code that won't change often like libraries, but its effect is totally nullified for code that changes a lot as you will have to recompile the whole set of precompiled headers everytime. The compiler also use a couple of tricks to avoid recompiling all template code in every compilation unit.

Also note that C++0x will introduce explicit mechanisms to better control template instantiation. You will be able to explicitly instantiate templates and, most importantly, prevent instanciation in some compilation units. However, most of that work is already being done by most compilers without our knowledge.

So, the rule of thumb is, put as much code (and include directives) as possible in your .cpp. If you can't, well, you can't.

My advice would be: don't template just for the heck of it. If you have to template, be careful and be aware that you are in fact choosing between speed of compilation and usability the template will bring.

like image 60
Coincoin Avatar answered Sep 20 '22 17:09

Coincoin


My personal favourite is this structure:

Header file:

#ifndef HEADER_FILE #define HEADER_FILE  template < typename T >  class X { void method(); };  #include "header_impl.h"  #endif 

Implementation file:

#ifndef HEADER_IMPL_FILE #define HEADER_IMPL_FILE  #include "header.h"  template < typename T >  void X<T>::method() { }  #endif 
like image 33
Šimon Tóth Avatar answered Sep 18 '22 17:09

Šimon Tóth