2011-05-18 86 views
4
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 ++错误:C++:如何通过函数指针,保存在一个局部变量,作为模板参数

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(“测试1”,&测试1) ;应该足够了。

+1

什么时候知道指针指向哪个函数 - 在运行时还是编译时? – sharptooth 2011-05-18 08:04:35

+0

在链接时... – hirschhornsalz 2011-05-18 08:10:56

回答

7

在编译时必须知道模板参数,因此您必须重新设计代码并将其考虑在内。

编辑:为您更新的问题使用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_; 
} 
+0

我知道编译时必须知道参数。请检查更新后的问题。谢谢。 – 2011-05-18 08:38:45

+0

@Code怪胎,看到更新的答案。 – AProgrammer 2011-05-18 08:58:53

+0

在您的修订代码中,我们是否也需要添加类A,类R作为模板参数?然后这将变成完全相同的我当前的解决方案(编辑1) – 2011-05-18 09:27:20

0

无法将存储在变量中的函数指针作为模板参数传递。即使变量在编译时是恒定的并且已知的。但它有可能通过一个函数指针字面

void foo() { 
} 

typedef void (FunctionPtr*)(); 

template<FunctionPtr F> 
void wrap() { 
    F(); 
} 

,然后调用:

wrap<&foo>(); 

我已经解决了类似的问题here

+0

我也试过这个,但是在这里,参数的返回类型和类型也需要作为模板参数传递。想找到一种方法来避免这种情况。感谢评论虽然:) – 2011-05-18 08:17:46

1

如何在共享一个通用接口的类中封装“test *”函数然后将这些类传递给模板?

+0

是的,但我喜欢的东西像boot.python或lu.bind即Wrapper.wrap(“func1”,&func);这是可能的吗?谢谢 – 2011-05-18 08:45:30

+0

我看到这样做的唯一途径,是不使用模板...但这可能只是我... – sergio 2011-05-18 08:58:53

0

函数的地址在编译期间(仅在链接时稍后)是未知的,在编译时必须知道模板参数。

解决这个问题的方法正是您在第一个换行函数中所做的:将其作为函数参数。

1

如何使用一组类有同名静态成员函数

struct FirstAlternative { 
    static void DoStuff(); 
}; 

struct SecondAlternative { 
    static void DoStuff(); 
}; 

template<class R, class A, class Alternative> 
void wrap(string name) (A)){ 
    wrapper_type f_ = &Wrapper::wrapper1<R,A,&Alternative::DoStuff>; 
    wrappers[name] = f_; 
} 

,然后通过class Alternative作为参数传入从调用站点模板?

+0

你的提议与sergio类似,请检查评论。谢谢 – 2011-05-18 08:46:46

相关问题