0

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.

Community
  • 1
  • 1
  • And implementation of your function is included too? – awesoon May 28 '13 at 14:10
  • @soon you want execAfter() function's code? –  May 28 '13 at 14:11
  • 1
    No. I'm talking about it: [Why can templates only be implemented in the header file](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). Do you know about it? – awesoon May 28 '13 at 14:14
  • @soon Maybe a good idea, but I dont think it will save me right now. –  May 28 '13 at 14:15
  • Tell me only one thing: do you have `Time.cpp` included? Or you compile it separately and then link? – awesoon May 28 '13 at 14:23
  • @soon Inside Time.cpp I include Time.hh. Nothing else, is this a problem? –  May 28 '13 at 14:26
  • 1
    Yes. Implementation of templates should be included. Please, read the link posted above again. – awesoon May 28 '13 at 14:28
  • Will do, thanks for not giving up and help me even I told you this wasn't the problem. –  May 28 '13 at 14:31
  • 1
    No problems. Glad it helped :) – awesoon May 28 '13 at 14:34
  • Are you sure your template body is in header file? BTW, you'd probably like to ready about perfect forwarding (e.g. http://thbecker.net/articles/rvalue_references/section_07.html ). –  May 28 '13 at 14:11

1 Answers1

3

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.
EGOrecords
  • 1,959
  • 2
  • 19
  • 33
  • Well I have done others templated functions the same way and they perfectly works, do you think this can be an exception? –  May 28 '13 at 14:24
  • Maybe you used the other templated functions only in the cpp files where they where defined, below the definition? – EGOrecords May 28 '13 at 14:25
  • Hum interesting, I check this and come back at you soon. –  May 28 '13 at 14:27
  • Ok this was the problem. You can do it my way only when you use it inside the same .cpp file. Thanks a lot. –  May 28 '13 at 14:32