templates, linker, .h and .cpp files

Hi

I decided to "templatize" some of my classes. Usually I am splitting a class into .h and .cpp file, where interface goes to header and implementation of a particular functions goes to .cpp.

When I convert a class to a template class I noticed that linker is not happy anymore and I need to include cpp files in places where I use a template class.

After some searching I found out that it is recommended to put template implementation in the header, so only one file will be included.

Is it the best approach? If I am suggested to put all implementation into header file, why should I split it for non-template classes?
Hi afedorov,
At the end, you probably meant "If I am suggested to put all implementation into IMPLEMENTATION file" correct ? anyway.

C++ does a lot with template, especially optimization. And having the definition of a template is one of the better way for the compiler to optimize it. And thus, you have to put the definition (the implementation) in the header file.
But if optimization is not an issue, then you can put the definition in your cpp files as usual.
It's more or less the same as for the "inline" directive ^_^

Because "premature optimization" is a bad habit and the origin of a lot of bad design, just don't care about that and put your definitions in the cpp file and leave your header clean ;)... you can always revert that very quickly \o/ in the future when you will (really) optimize your code.

Also, don't forget that if the "use" of your templatized thing need some definitions, then you should give those in the header too. If not the compiler will complain.
In general, I can put all the code in .h file.

Do people split just because of separation of interface from implementation? Or there are other benefits of that?
Hi afedorov,
A great subject you have here... well, technically speaking "separating public from implementation" is very important :
* first because if you change a .h file because you change your implementation, then everybody will recompile... and maybe a bunch of code each time you modify something you deliver to me, your client for instance. This is a big issue when you want to compile often, that is fast enough. In agile development process, in TDD in particular, if you cannot compile in 1 or 2 seconds max, then you're almost dead.
* hiding the implementation is not only a "copyright" matter, it serves a great purpose : the readability. A 100-line header is far better than a 5000-lines header mixed with implementation ugly details.
* but most importantly, if you give the client enough for him to "hack", he will hack too deep and your "library" will no more be independant from 1) your interface and 2) from the code's client. Both are related because client learn to use and respect the interface but you have to grant them one. And in exchange, you get a high stability of your interface, that is for 100 changes in the implementation, the interface sometimes doesn't even change once. That is what we call "independency" right ? I modify a billion things in my code, you modify a billion things in your code but we have a contrat : the interface expressed in the header. This simplify, stabilies and make things a lot better, faster and clearer between us.

There is very much more to say to that but to conclude...
A clear header is the simpliest one, the most evident peace of information.
The best header is like : 2 or 3 functions and that's all. But who can do that ? ^_^

Now, in C++ in particular, most of the very good optimizations are obtained when the compiler have the "definition" where it has the declaration of the "thing". Because then, it knows more or at least a lot and then, it can decide weither or not (and also how) to optimize.
That's the reason why, if you don't give the implementation of an inline function (so in the header file), then you have almost no change at all that the compiler will ever inline your function. But hey, compilers are very very "intelligent" ;) nowadays. Now make the implementation available and the compiler will inline as often as it feels like doing so.

You use to put everything in the header file you say ?
Well, I can't imagine what it can be, really, I never do that, I never did and the few "testing" moments I did that, I regreted it so painfully, I decided to eat a 1000 burgers just to punish myself ! :D each time \o/
Last edited on
When I split template class into .h and .cpp files, in all places where I want to use this file I need to include both files, otherwise linker throws an error.

Am I doing something wrong?

For example
A.h
1
2
3
4
5
template<typename T>
class A {
public:
    void someFunction(T t);
};

A.cpp
1
2
3
4
5
6
#include "A.h"

template<typename T>
void A<T>::someFunction(T t) {
    t.hello();
}

B.h
1
2
3
4
class B {
public:
    void hello();
};

B.cpp
1
2
3
4
5
6
#include <iostream>
#include "B.h"

void B::hello() {
    std::cout << "hello";
}


main.cpp
1
2
3
4
5
6
7
8
9
10
11
# include <iostream>
#include "B.h"
#include "A.h"

int main() {
    B b;
    A<B> a;

    a.someFunction(b);
    return 0;
}


I got an error

Undefined symbols for architecture x86_64:
"A<B>::someFunction(B)", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)


Error disappears if I do
#include "A.cpp"

For templates the easiest thing to do is put all the template code in it's own header file.

https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
Topic archived. No new replies allowed.