0

So I've learnt that it's best to first declared function in header file, than define it in a seperate .cpp file as function definition within headers aren't recommended. And I did so, with normal function and it worked. but when I try to do the same thing with template functions, it gave back error like

/usr/sbin/ld: /tmp/cc196bnS.o: in function `main':
test.cpp:(.text+0x11): undefined reference to `double d::numerical::test<double>(double)'
collect2: error: ld returned 1 exit status

Following will be a minimal working example where in header file I've define a normal function d::numerical::test2(double) and a template function template<typename T> d::numerical::test(T). Then cout their returning value individually in test.cpp. Compiled with g++ integration.cpp test.cpp, the one calling normal function test2 compiled and ran successfully, yet if I change it to test it throws the error as shown above.

Notice I've also added a const and a class in the header file, and those can also be accessed to ensure that the file actually get included properly.

I've read online (here) that it seems template functions' definition must also be in header file? But doesn't that goes against the rule that don't define function in header? What is the proper solution for these cases?


MWE

test.cpp

#include<bits/stdc++.h>
#include"./integration.hpp"

using namespace std;

int main() {
    cout << d::numerical::test(1.) << std::endl;
    return 0;
}

integration.hpp

#ifndef __FUNC_NUM_INTE__
#define __FUNC_NUM_INTE__
namespace d { namespace numerical {
    const double EPS=1e-24;
    double test2(double);
    template<typename T> double test(T);
    template<typename T>
        class dp {
            T odd, even;
        };
}}
#endif

integration.cpp

#include"integration.hpp"

double d::numerical::test2(double x) {
    return x;
}

template<typename T>
double d::numerical::test(T x) {
    return x;
}
Andrew.Wolphoe
  • 420
  • 5
  • 18
  • The short and simple answer is to put the definition of the template in the header. The alternative is (in the same source file where you define the function template) to explicitly instantiate the template over every type for which it ever gets used. – Jerry Coffin Jul 14 '21 at 04:46
  • @JerryCoffin So what I learnt is that, if you define function within header, and that header is included multiple times throughout the project, you might have multiple copies of that function which will break the linker. Then in this circumstance, is it a) defining template function within header won't cause such issue, or b) defining template function within header **then explicitly instantiate it in .cpp file** would prevent such issue? – Andrew.Wolphoe Jul 14 '21 at 05:21
  • 1
    When you define the function in the header, you want to to mark it as `inline` to prevent problems from multiple definitions. Yes, explicit instantiation in the cpp file will do the same (but it's more work). – Jerry Coffin Jul 14 '21 at 05:29
  • @JerryCoffin then will the explicit instantiation method prevents disadvantages for `inline` functions such as possibility of code-bloat and longer compilation time as listed in [Wikipedia](https://en.wikipedia.org/wiki/Header-only)? – Andrew.Wolphoe Jul 14 '21 at 06:19

1 Answers1

0

Short answer is that you define test2 with double type in .cpp file, but not test method (without 2 in name).

Did you expect the compiler to define it automatically?

Then, you should move the template definition to header, I mean the part:

template<typename T>
double d::numerical::test(T x) {
    return x;
}

Note that templates are a compile time feature, and if your method needs to accept multiple types as input (without being in a header), then research for variant (or QVariant which is part of Qt framework).

Top-Master
  • 7,611
  • 5
  • 39
  • 71