This problem is in defining and declaring a function template in a namespace that is defined in an external file from where the function is instantiated. Here’s the smallest reproducible example I could come up with. 4 files follow:
The function template declaration in a named namespace:
// bar.h
#include <algorithm>
namespace barspace {
template <typename Iter>
void DoSomething (Iter first, Iter last);
}
The function template definition in a separate file:
// bar.cpp
#include "bar.h"
namespace barspace {
template <typename Iter>
void DoSomething (Iter first, Iter last) {
typedef typename std::iterator_traits<Iter>::value_type val_t;
std::sort (first, last);
}
} // namespace barspace
The header for the main program
// foo.h
#include "bar.h"
#include <vector>
Lastly, the main program where the function template is called:
//foo.cpp
#include "foo.h"
int main () {
std::vector<double> v_d;
for (int i = 0; i < 10; i++) {
v_d.push_back (i);
}
barspace::DoSomething (v_d.begin(), v_d.end());
return 0;
}
I compile as follows:
g++ -c -o bar.o bar.cpp
g++ -c -o foo.o foo.cpp
These run fine. Now for linking:
g++ bar.o foo.o -o foobar
And the resulting compiler error about the undefined reference:
foo.o: In function `main':
foo.cpp:(.text+0x6e): undefined reference to `void barspace::DoSomething<__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >(__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >)'
collect2: ld returned 1 exit status
There is an obvious problem with the code not getting made available from within the namespace, or from the bar compilation unit.
Furthermore, when I try to place the definition of DoSomething in the bar.h header, as I would to circumvent the issues when defining class template methods in separate .cpp files, I get the same error.
Can you shed some light unto my compiler linking error?
You are trying to hide the implementation of your templated function into the cpp file, which, unfortunately, is not possible for most compilers. Templated functions/classes are instantiated when used, so at the point where you are calling
DoSomething, the compiler needs the definition of the function to be able to compile it.There are a couple of solutions.
Move the function body into the header file. You had trouble doing that before, but i’d say it’s related to something else. This is the preferred approach.
Include the cpp file from
foo.cpp. (wild, but not that uncommon).Instantiate the template for
double: