C ++:如何传递函数指针,存储在局部变量中,作为模板参数 [英] C++ : How to pass function pointer, stored in a local variable, as a template parameter

查看:243
本文介绍了C ++:如何传递函数指针,存储在局部变量中,作为模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  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&
//在真正的程序中,f_会在一个数组中传递给某个c库
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:<<结果< endl
}

map< string,wrapper_type>包装纸

};

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'不是类型'float(*)(float)'的有效模板参数,因为函数'fn' 

从我的理解,问题是一个局部变量没有链接;因此它不能用作模板参数。



所以,我想知道是否有办法解决这个问题或另一种技术来完成同样的工作?



感谢。



编辑1:



我完全理解,我不能传递一个值,不能在编译时确定为一个模板参数。我要问的是 - 有更好的方法吗?现在对我有用的解决方案是:

  template< class R,class A,R(* fn) > 
void wrap(string name){
wrapper_type f_ =& Wrapper :: wrapper1< R,A,fn> ;;
//在实际程序中,f_将被传递到一个数组sm c库
wrappers [name] = f_;
}

并调用:

  w.wrap< float,float,& test1>(test1); 
w.wrap< int,int,& test2>(test2);

但这里我必须在包装期间传递参数类型。有什么地方可以避免这种情况吗?



编辑2:



只是为了澄清或添加更多信息:必须类似于LuaBind或Boost.Python ie Wrapper.wrap(test1,& test1);应该足够了。

解决方案

模板参数必须在编译时已知,因此您必须重新设计您的代码, p>

编辑:为您更新的问题使用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> ;;
//在实际程序中,f_将被传递到一个数组sm c库
wrappers [name] = f_;
}


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_;
}

这篇关于C ++:如何传递函数指针,存储在局部变量中,作为模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆