0

I want to write the definition of a templated function in the .cpp file, instead of it being in the header.

Let's take this simple example:

// func.h

template <class T>
void print_message(T func) {
    func();
}

// main.cpp

#include <iostream>
#include "func.h"

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

int main(int argc, char* argv[]) {
    print_message(say_hello);
    return 0;
}

How do I template instantiate the print_message function explicitly in the .cpp file, along the lines of how it is described here.

I tried the following code snippet but I get this error: explicit instantiation of 'print_message' does not refer to a function template, variable template, member function, member class, or static data member.

// func.h
template <class T>
void print_message(T func) {
    func();
}

// main.cpp

#include <iostream>
#include "func.h"

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

template void print_message<say_hello>(say_hello func);

int main(int argc, char* argv[]) {
    print_message(say_hello);
    return 0;
}
jeffreyveon
  • 13,400
  • 18
  • 79
  • 129
  • whats the meaning of "does not work" ? – 463035818_is_not_an_ai Mar 28 '22 at 08:08
  • I get: `error: explicit instantiation of 'print_message' does not refer to a function template, variable template, member function, member class, or static data member` – jeffreyveon Mar 28 '22 at 08:11
  • Do you mean how to instantiate it in a *third* .cpp file? It doesn't really make much sense to d it in the `main.cpp` where the function is already instantiated. – Bob__ Mar 28 '22 at 08:20
  • what is the use case of templated function which accepts only a function pointer without any argument ? Why can't it be `void print_message(void(*)() func)` ? – TruthSeeker Mar 28 '22 at 10:15

1 Answers1

2

The issue is not that you provide the definition in the source. You did place the definition in the header. Moreover there is only a single translation unit in your example. The error would be the same if you place all code in main.cpp.

The issue is that print_message has a type argument, but say_hello is not a type.

This compiles whithout error:

#include <iostream>

// func.h
template <class T>
void print_message(T func) {
    func();
}

// main.cpp
void say_hello() {
    std::cout << "hello" << std::endl;
}

template void print_message<decltype(&say_hello)>(decltype(&say_hello) func);

int main(int argc, char* argv[]) {
    print_message(&say_hello);
    return 0;
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Thanks, `decltype` was indeed what I was missing! – jeffreyveon Mar 28 '22 at 08:26
  • @jeffreyveon it doesn't have to be `decltype`. I only used it out of lazyness. I'd actually rather use an alias `using void_fun = void();` – 463035818_is_not_an_ai Mar 28 '22 at 08:27
  • If I had another function like `say_bye`, would I be able to instantiate another explicit function like: `template void print_message(decltype(&say_bye) func);`? I get a `duplicate explicit instantiation of 'print_message'` error, while in this other answer, multiple explicit instantiations are shown to be possible: https://stackoverflow.com/a/495056/131050 – jeffreyveon Mar 28 '22 at 08:34
  • @jeffreyveon what is `say_bye` ? Use the type alias for the function type. If `decltype(&say_bye) == declype(&say_hello)` then `print_message(&say_bye)` and `print_message(&say_hello)` are calling the same function – 463035818_is_not_an_ai Mar 28 '22 at 08:36
  • Sorry for the confusion here, I have edited my question with the latest code snippet. The header file consists only of the definition. I define the templated function in the cpp file, but want to explicitly instatiate the function with 2 different functions `say_hello` and `say_bye` as shown in the updated example. – jeffreyveon Mar 28 '22 at 08:40
  • @jeffreyveon please do not alter your question to ask for something substantially different after you received answers. This answer was ok before but is not anymore. If you have a follow-up quesiton you can open another question – 463035818_is_not_an_ai Mar 28 '22 at 08:41
  • @jeffreyveon the two `say_xx` functions have the same type. You need not instantiate the template twice, because `print_message(&say_bye)` and `print_message(&say_hello)` are calling one and the same function – 463035818_is_not_an_ai Mar 28 '22 at 08:43
  • @jeffreyveon its like instantiating it once for `decltype(1)` and a second time for `decltype(2)`, both are `int`. In your case, both are `void()` – 463035818_is_not_an_ai Mar 28 '22 at 08:44
  • Sorry about that, I did not phrase my question correctly. The updated question is what I intended to ask. The first example in my question with the templated function being in the header file works fine, but how do I make it work such that the definition is in the cpp file as shown in the second example in my question. – jeffreyveon Mar 28 '22 at 08:45
  • @jeffreyveon its exactly the same issue as before + you need to instantiate the template only once not twice for the same type – 463035818_is_not_an_ai Mar 28 '22 at 08:48
  • Ok got it, both functions share the same type signature so that's causing issues. – jeffreyveon Mar 28 '22 at 08:52
  • @jeffreyveon the fact that you put the definition in `main.cpp` is not relevant for your example, because there is only a single translation unit in your example. You could put all code in `main.cpp` with the same effect – 463035818_is_not_an_ai Mar 28 '22 at 08:52
  • @jeffreyveon may I ask you to roll back your edit, because after your edit my answer is wrong. I dont have the time to fix it atm. And even worse, you accepted it even though it revers to an old version of the question and contains parts that are now wrong – 463035818_is_not_an_ai Mar 28 '22 at 08:55
  • Rolled back, sorry for the hassle. – jeffreyveon Mar 28 '22 at 08:58