Generic Programming and template function definitions only in header files?

Hi -- I'm trying to adopt generic programming as a practice as I learn C++, but have come up against a bit of a wall. Basically, unless you define your template functions in the header file, or explicitly tell the compiler what template parameters you want to instantiate in the implementation file, you can't use GP.
Is this correct?
Am I still going to have to create an explicit OOP interface & use that to resolve this issue?
If so, what's the point of GP?
Thanks for any & all help.
Doug.
unless you define your template functions in the header file
How is that a problem? (except that the implementation is exposed)
However you could separate the files if you put #include "implementation.hpp" at the end of the header file.

what's the point of GP?
Less work. You don't need to write every overload function/object that you need, the compiler handles that for you. (if the objects have the adequate behaviour)
Don't quite get what your problem is.
Can you supply an example.

For the record, compiler providers don't seem to have a problem using generic programming to write
the STL - are you not over-exaggerating your issue?
Hey... Thanks for your support....

ne555: Are you saying that people generally don't worry about having long implementations in header files when practicing GP? I'm just learning, but have tried to learn (long ago) in the past, so am probably being misguided by all kinds of atavistic best practices from then.
The appeal to me (coming from languages I'm fluent in like Ruby) of GP is what I see as its similarity to duck typing, so I guess another good question here would be, is that an accurate perception?

guestgulkan: I don't think I'm exaggerating it, but it could well be based on a misconception (or an outdated conception). Basically, if I'm getting this right, the compiler can't see two implementation files at the same time, so can't tell what class to compile for. There is an overview of the issue here: http://stackoverflow.com/questions/3008541/template-class--symbols-not-found
My problem is that none of the solutions posted there really satisfy me, as I have an aversion to putting long implementations into a header file (one that I'll get over if that's no longer frowned upon), and I have multiple targets in my project (due to practicing BDD), so will end up with lots of compiled classes I don't need, or a mess of defines and ifdefs, if I try the suggested solution that includes a .cpp file.

I guess really that I have quite a bit more reading on GP to do!
& thankyou very much for your replies,
Doug.
Last edited on
The issue is because templates are not real classes; the actual classes are generated as needed by the compiler when it sees one. And since (like you said) the compiler can't "see" multiple .cpp files at once (unless you have an awesome export compiler), then you have the issue.

Anyway, just put it all in the header file. Tbh, the coders probably won't be looking into your code and instead they should be reading your documentation on what the class has, etc.

If you really want to seperate the implementation, just put it in a seperate header file, then include that below the class:

something.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef SOME_TEMPLATE_CLASS
#define SOME_TEMPLATE_CLASS

//includes

template <typename T>
class something {
   //blah blah
};

#include "something_implementation.hpp"

#endif 


something_implementation.hpp:
1
2
3
4
5
6
//the functions
//not sure if the following is correct, haven't tested it
template <typename T>
void something<T>::some_func() {
   //blah blah
}
Last edited on
Brilliant, cheers for that -- I'll give that a bash.
& thanks again everyone for the advice -- it's really appreciated.
Doug.
Hi -- okay, I'm doing as advised, and I'm creating declarations in header files (for instance called "MyClass.h"), and then, instead of putting the definition in a .cpp file called "MyClass.cpp", I'm putting it in a file called "MyClass_impl.h" that gets included right at the bottom of "MyClass.h".
As the templatisation percolates through pretty much the whole structure of my code, this means that I'm going to end up with lots of *_impl.h files, and very few *.cpp files (aside from the one containing the main function).
I guess all I'm asking is this: Are you *sure* that's okay?
Damn' -- I sound like a child with strict parents that's been told by a laissez-faire babysitter he can watch late night TV, but I wanted to check. ;)
If nobody tells me the world is going to end, I'll just continue on this way, as I'm really liking the type of code it's allowing me to write.
& thanks again,
Doug.
There are 3 common ways of dealing with template files:

1. The all in one approach. This is where you put all the stuff in a single header file.
This can lead to some long files (have a look at some of the STL header files to se what I mean).

2. The h file and impl/inl split file approach.
This is similar to the method used for normal classes. You have a h file with the class declaration
and a second file with the implementation deatils.
The file extension with the implementation deatils can be (almost) anything you like - .h and .inl are common extensions.
You then #include this implementation file in the declaartion file after the class declaration
Note you should not give the implemation file a .cpp extension - because project management
software (MSVC, Codeblocks, other IDEs) assume that if you add a file called *.cpp
to a project, it is a candidate for compilation and will cause problems.

3. .h and .cpp split file approach - using explicit instantiation in the cpp file.
This method is pretty much the same as for normal non-template classes.
A *.h file for the declaration and a *.cpp file for the implementation.
BUT - we do a #include header file at the top of the cpp file - AND at the bottom of the cpp file, we explicitly instantiate any concrete classes that we need.
In this approach we COMPILE the *.cpp file
This is the most awkward approach because each time we find that we need a particular concrete class we need to go to the *.cpp file and add it to explicit instantiation list.



Methods 1 & 2 are the most common approach.
Last edited on
Brilliant, thanks.
Think I'm gonna be an approach no. 2 man, myself.
Thanks very much again for everyone's input.
Doug.
Topic archived. No new replies allowed.