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?