3

I'm developing a C++ library that makes heavy uses of templates. For most of the classes, all the code resides in some .hpp file that will be #included directly by client code. There are two things that I'm worrying about:

  1. Is there some design pattern for moving implementation code to the "background"? When I design non-template classes I often separate the "interface" class and the implementation class, and the former will delegate to the latter by doing something like getImpl()->foo(), so that implementation code can be dynamically linked to. I'm not sure how to do this for templates. Probably dynamic linking just doesn't make sense for template, I think?

  2. Are big template headers (> 1000 lines) common? Or is that bad? If it's bad, what can I do with it?

I am aware of this question How to reduce output size of template-heavy C++ code?, but I think we are asking about different things: the OP of that question is trying to reduce the size of the output, while I am trying to reduce the size of my library headers themselves.

UPDATE: For example, if you were to design std::vector, how would you organize its interface & implementation (if needed)?

Community
  • 1
  • 1
Zizheng Tai
  • 6,170
  • 28
  • 79

1 Answers1

0

Don't worry too much about the header size. Templates almost always have all their code in a header because each client must know how instantiate the class in case they are creating a completely new version (with different template parameters).

If you're worried about 1000 lines, take a look at vector. In Visual Studio 2013, it's 3000 lines.

Having said that, you really only need the declaration of classes available everywhere and the definition once, like any normal class. So it is possible to have a template header with no implementation and then create a .cpp with the implementations. This .cpp will have to force the generation of all the templated types that you need everywhere.

In the example below, the author of B.cpp must know all template parameters that will ever be used. You don't need this many files, but I think this should cover every scenario.

B.h:

template<class T>
struct B
{
    B();
};

B_impl.h:

#include "B.h"
template<class T>
B<T>::B() {}

B.cpp:

#include "B_impl.h"
template struct B<int>;
template struct B<short>;

main.cpp:

#include "B.h"
B<int> b; 
Ian
  • 841
  • 5
  • 10
  • *So it is possible to have a template header with no implementation and then create a .cpp with the implementations. This .cpp will have to force the generation of all the templated types that you need everywhere.* This is for client code, or library code? – Zizheng Tai May 05 '16 at 04:29
  • I edited the answer with a full code example (and I replaced typedef with template, because typedef doesn't instantiate a templated class). It is quite dangerous to do this for library code because you probably don't know every type your clients will use your library for. If you are releasing compiled binaries, your binary must contain all instantiations as well. Imagine an std::vector where you couldn't use your own types. – Ian May 05 '16 at 04:51
  • You could ship B.h and B_impl.h in the library to avoid these problems, but I have never seen it been done. Also, imagine class B has 20 functions and main.cpp only uses one of them. I think the compiler only has to compile the 1 function. However, if you use template struct B as above, the compiler must compile all 20 functions (and maybe the linker will remove 19 of them). – Ian May 05 '16 at 05:04