user1585121
user1585121

Reputation:

Use a templated function outside of the .cpp file without declaring it in the .hh file

The title isn't representative of my question but I couldn't find a correct one, feel free to edit.

Context :

Bomberman project for school.

In my Bomberman I have an execAfter() function prototyped as follow:

void execAfter(std::function<void(t_params *)> func, t_params *params, int ms);

The aim of this function is to execute func, taking params struct as parameter, after a ms delay.

Example : drop a bomb, explose after X ms.

It works perfectly (using lambda as told here on a previous SO question).

Problem

Now I want to template my function in order to be able to pass different function type and different params type.

Time.hh

template<typename T, typename U, typename V>
void execAfter(T func, U params, V ms);

Time.cpp

template<typename T, typename U, typename V>
void Time::execAfter(T func, U params, V ms)
{ 
 ...
}

(templating the V param is useless but it was just for compilation problem, I will figure out how to do later)

Example : *call the function void X(Y), passing as parameter Y*.

I done everything the right way, from my point of view, everything compile, except after linkage gcc throws this:

[...]
 linkage ...
[...]
 src/Entities/Character.o: In function `Character::landBomb()':
 /home/teube_a/Code/tech2/c++/bomberman-2016-      couille_c/zizi_g/src/Entities/Character.cpp:208: undefined reference to `void   Time::execAfter<std::function<void (s_params*)>, s_params*, int>(std::function<void  (s_params*)>, s_params*, int)'
 collect2: ld returned 1 exit status
 make: *** [bomberman] Error 1

I really don't understand, please explain me the possibles reasons why this templated function can't be generated.

Tell me if you need more info.

Upvotes: 0

Views: 179

Answers (1)

EGOrecords
EGOrecords

Reputation: 1969

In C++ a Template is understood as a Template for the Compiler to generate code. So the Compiler has to know at every instantiation of the template, what the implementation is, i.e. it should to be in the header file the Template is defined in.

You can have concrete Implementations for templates like that:

template <typename T>
T f(T) { ...}

template<> 
int f<int>(int) {...} 

then the linker will find an implementation to a concrete type, and will use it preferred to the compiler generated version.

What you have now is a template declaration without the implementation, wich means the linker will search only for the concrete Implementation, and does not find one!

There are two possible solutions:

  1. You provide a default template Implementation instead of only the signature
  2. You provide a concretisation of the template for the requested type. Keep in mind, that you have to/are able to do this for every type your template should work on.

Upvotes: 3

Related Questions