Reputation: 451
I have a class that needs to call an external function in a variety of different contexts. I want to keep things flexible, so I'm using an interface (inspired by the 3rd edition of Numerical Recipes) that should work with functors, function pointers, etc. A simplified example looks like:
class MyClass {
public:
template <class T>
MyClass(T &f_) { f = f_; }
private:
int (*f)(int);
};
int myFn(int i) {
return i % 100;
}
int main() {
MyClass test(myFn);
return 0;
}
So far so good; g++ compiles this without any complaints. In my real application, there's a lot more code so I've got things split up among multiple files. For example,
test2.h:
#ifndef __test2__
#define __test2__
class MyClass {
public:
template <class T>
MyClass(T &f_);
private:
int (*f)(int);
};
#endif
test2.cpp:
#include "test2.h"
template <class T>
MyClass::MyClass(T &f_) {
f = f_;
}
main.cpp:
#include "test2.h"
int myFn(int i) {
return i % 100;
}
int main() {
MyClass test(myFn);
return 0;
}
When I try to compile this using g++ test2.cpp main.cpp
, I get the following linking error:
/tmp/ccX02soo.o: In function 'main':
main.cpp:(.text+0x43): undefined reference to `MyClass::MyClass<int ()(int)>(int (&)(int))'
collect2: ld returned 1 exit status
It appears that g++ isn't aware of the fact that I'm also trying to compile test2.cpp. Any ideas about what might be going on here?
Thanks,
--craig
Upvotes: 0
Views: 210
Reputation: 258618
Template classes must have their implementation visible to all translation units that use them, unless they are fully specialized.
That means you have to move the implementation in the header:
//test2.h
#ifndef __test2__
#define __test2__
class MyClass {
public:
template <class T>
MyClass(T &f_);
private:
int (*f)(int);
};
template <class T>
MyClass::MyClass(T &f_) {
f = f_;
}
#endif
Upvotes: 1