rokoder

C++ Templates, not so generic

by on Mar.19, 2012, under Programming

Lets start with basic ideology of .h and .cpp files. When building libraries, the idea is to share only your header files and not your implementation (mean .cpp files). This is also the basics OOP’s encapsulation, abstraction etc, to hide the implementation details.

Now templates in C++ violates this encapsulation principle, bcoz C++ is a compiled language. And compiler generates all the needed (generic) code during compilation (it is different from Java as in Java this code can be generated in Java Run Time during execution and not at compilation. As Java compiled .class files contains enough info to generate a specific implementation later). Now to adhere to OOP we end up with fragile templates which are not 100% generic in nature.

Now there are two ways to implement templates.

Keep declaration and definitions separate (SHARING implementation)

Now you can put all your code (including implementation) in a single header and distribute that. But if you want to keep things clean and in order, then you can include your implementation file in another header. I think it should be header file as this goes with basic convention that we share .h files (even though this contains code) and we keep .cpp files (not to be shared, until you are sharing the code itself). Here is how the files look.

foo.h

This is simple file with including foo_impl.h.

#ifndef FOO_H
#define FOO_H
template <class T>
class Foo {
  public:
    Foo (T);
    T get();
  private:
    T data;
};

#include "foo_impl.h"
#endif

foo_impl.h

This one is bit different from the norms. Here we are not guarding the header file content. Instead we will raise an compilation error if some one include foo_impl.h directly (which in our case does not make sense).

#ifndef FOO_H
#error 'foo_impl.h' is not supposed to be included directly. Include 'foo.h' instead.
#endif

template <class T>
Foo <T> :: Foo (T stuff) {
   data = stuff;
}

template <class T>
T Foo <T> :: get () {
   return data;
}

Now if some one tries to include foo_impl.h directly will get error like:

foo_impl.h:2:2: error: #error 'foo_impl.h' is not supposed to be included directly. Include 'foo.h' instead.

PROS:

  • Separation of concerns, implementation and declarations are in separate files.
  • Safe guarding implementation file to avoid accidental inclusion.
  • The header file used to include is not bloated with implementation code.

CONS:

  • As mentioned above, have to share the implementation.

Keep declaration and definitions separate (NOT SHARING implementation)

For not sharing code for templates, you have to define all the possible datatypes your template can be used with in .cc/.cpp file like:

template class foo< int >;
template class foo< double >;

PROS:

  • Separation of concerns, implementation and declarations are in separate files.
  • No need to share your implementation

CONS:

  • Not too generic. Have to know before hand what is required.
:, , , ,

Leave a Reply

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Blogroll

A few highly recommended websites...

Archives

All entries, chronologically...