using namespace std;
float test1(float i){
return i * i;
}
int test2(int i){
return i+9;
}
struct Wrapper{
typedef void (*wrapper_type)(int);
template<class R, class A>
void wrap(string name,R (*fn) (A) ){
wrapper_type f_ = &Wrapper::wrapper1<R,A,fn>;
// in the real program, f_ would be passed in an array to some c library
wrappers[name] = f_;
}
void run(int i){
map<string,wrapper_type>::iterator it, end = wrappers.end();
for(it=wrappers.begin();it!=end;it++){
wrapper_type wt = (*it).second;
(*wt)(i);
}
}
template<class R, class A, R (*fn) (A)>
static void wrapper1(int mul){
//do something
A arg = mul;
R result = (*fn)( arg );
cout << "Result: " << result << endl;
}
map<string,wrapper_type> wrappers;
};
int main(int argc, char** argv) {
Wrapper w;
w.wrap("test1",&test1);
w.wrap("test2",&test2);
w.run(89);
return 0;
}
Here's the g++ error:
main.cpp:31: error: ‘fn’ is not a valid template argument for type ‘float (*)(float)’ because function ‘fn’ has not external linkage
From what i understand, the problem is that a local variable has no linkage; thus it can not be used as a template parameter.
So, i wanted to know if there's a way to get around this problem or another technique to accomplish the same ?
Thanks.
Edit 1:
I totally understand that I can't pass a value that can not be determined at compile time as a template paramter. What i'm asking is - is there a better way to do this? Right now the solution that works for me is :
template<class R, class A,R (*fn) (A)>
void wrap(string name){
wrapper_type f_ = &Wrapper::wrapper1<R,A,fn>;
// in the real program, f_ would be passed in an array to sm c library
wrappers[name] = f_;
}
and called as :
w.wrap<float, float, &test1>("test1");
w.wrap<int, int, &test2>("test2");
But here I've to pass argument-type during wrapping. Is there someway to avoid this ?
EDIT 2:
Just to clarify or add more info: The interface I want to present to the user has to be similar to LuaBind or Boost.Python i.e. Wrapper.wrap("test1",&test1); should be sufficient.
Template parameters must be known at compile time, so you'll have to redesign your code taking this into account.
Edit: for your updated question use Boost function_traits.
template<R (*fn) (A)>
void wrap(string name){
wrapper_type f_ = &Wrapper::wrapper1<function_traits<A>::result_type, function_traits<A>::arg1_type,fn>;
// in the real program, f_ would be passed in an array to sm c library
wrappers[name] = f_;
}
what about encapsulating your "test*" functions in classes sharing a common interface and then passing the classes into the templates?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With