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;
}
Вот ошибка g ++:
main.cpp:31: error: ‘fn’ is not a valid template argument for type ‘float (*)(float)’ because function ‘fn’ has not external linkage
Из того, что я понимаю, проблема в том, что локальная переменная не имеет связи; таким образом, его нельзя использовать в качестве параметра шаблона.
Итак, я хотел знать, есть ли способ обойти эту проблему или другой метод для достижения той же цели?
Спасибо.
Редактировать 1:
Я полностью понимаю, что не могу передать значение, которое не может быть определено во время компиляции, как параметр шаблона. Я спрашиваю, есть ли лучший способ сделать это? Прямо сейчас решение, которое работает для меня:
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_;
}
и называется как:
w.wrap<float, float, &test1>("test1");
w.wrap<int, int, &test2>("test2");
Но здесь я должен передать аргумент-тип во время переноса. Есть ли способ избежать этого?
РЕДАКТИРОВАТЬ 2:
Просто для пояснения или добавления дополнительной информации: интерфейс, который я хочу представить пользователю, должен быть похож на LuaBind или Boost.Python, т.е. Wrapper.wrap ("test1", & test1); должно быть достаточно.