2012-02-08 43 views
4

我想要一个Foo类来存储一个构造函数指针,并在某个时候调用这个函数。我看着这两个问题求助:调用函数并传递存储在元组中的参数?

,并根据问题的答案,想出了这个代码:

#include <functional> 

template < int N, typename... ARGS > 
struct apply_func { 
    static void applyTuple(std::function<void(ARGS...)>& f, 
          const std::tuple<ARGS...>& t, 
          ARGS... args) { 
    apply_func<N-1>::applyTuple(f, t, std::get<N-1>(t), args...); 
    } 
}; 

template <typename... ARGS> 
struct apply_func<0,ARGS...> 
{ 
    static void applyTuple(std::function<void(ARGS...)>& f, 
          const std::tuple<ARGS...>& /* t */, 
          ARGS... args) { 
    f(args...); 
    } 
}; 

template < typename... ARGS > 
void applyTuple(std::function<void(ARGS...)>& f, 
       std::tuple<ARGS...> const& t) { 
    apply_func<sizeof...(ARGS), ARGS...>::applyTuple(f, t); 
} 

template<typename... ARGS> 
class Foo 
{ 
    std::function<void(ARGS...)> m_f; 
    std::tuple<ARGS...> *argument_pack; 

    public: 
    Foo(std::function<void(ARGS...)> f):m_f(f){} 
    void operator()(ARGS... args); 
    void run(); 

}; 

template<typename... ARGS> 
void Foo<ARGS...>::operator()(ARGS... args) 
{ 
    m_f(args...); // this works 
} 

template<typename... ARGS> 
void Foo<ARGS...>::run() 
{ 
    applyTuple<ARGS...>(m_f, *argument_pack); // this doesn't compile 
} 

void bar(int i, double d){} 

int main(void) 
{ 
    Foo<int,double> foo(bar); 
    foo(1,1.0); // this works 
    foo.run(); // this doesn't compile 
} 

如果用编译'g ++ -std = C++ 0x' next next to last line will give this error:

test.cc: In function ‘void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]’: 
test.cc:52:9: instantiated from ‘void Foo<ARGS>::run() [with ARGS = {int, double}]’ 
test.cc:61:17: instantiated from here 
test.cc:27:8: error: no matching function for call to ‘apply_func<2, int, double>::applyTuple(std::function<void(int, double)>&, const std::tuple<int, double>&)’ 
test.cc:27:8: note: candidate is: 
test.cc:6:19: note: static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}] 
test.cc:6:19: note: candidate expects 4 arguments, 2 provided 
test.cc: In static member function ‘static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}]’: 
test.cc:27:8: instantiated from ‘void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]’ 
test.cc:52:9: instantiated from ‘void Foo<ARGS>::run() [with ARGS = {int, double}]’ 
test.cc:61:17: instantiated from here 
test.cc:9:9: error: no matching function for call to ‘apply_func<1>::applyTuple(std::function<void(int, double)>&, const std::tuple<int, double>&, const double&, int&, double&)’ 
test.cc:9:9: note: candidate is: 
test.cc:6:19: note: static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 1, ARGS = {}] 
test.cc:6:19: note: candidate expects 2 arguments, 5 provided 
test.cc: In static member function ‘static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 1, ARGS = {}]’: 
test.cc:9:9: instantiated from ‘static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}]’ 
test.cc:27:8: instantiated from ‘void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]’ 
test.cc:52:9: instantiated from ‘void Foo<ARGS>::run() [with ARGS = {int, double}]’ 
test.cc:61:17: instantiated from here 
test.cc:9:9: error: no matching function for call to ‘get(const std::tuple<>&)’ 
test.cc:9:9: note: candidates are: 
/usr/include/c++/4.6/utility:133:5: note: template<long unsigned int _Int, class _Tp1, class _Tp2> typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&) 
/usr/include/c++/4.6/utility:138:5: note: template<long unsigned int _Int, class _Tp1, class _Tp2> const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&) 
/usr/include/c++/4.6/tuple:531:5: note: template<long unsigned int __i, class ... _Elements> typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&) 
/usr/include/c++/4.6/tuple:538:5: note: template<long unsigned int __i, class ... _Elements> typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&) 

我错过了什么?谢谢!

回答

0

我解决它。这是三个错误的组合:

  1. 指针错误所指出的用户:templatetypedef
  2. 我不得不回去后这一应用的元组的原始版本:How do I expand a tuple into variadic template function's arguments?。我将所有模板参数改为ARGS...,因为对于元组,函数和类他们都是一样的。老实说,我仍然不明白为什么这不应该工作...
  3. 函数指针必须像这样存储(void (*m_f) (ARGS...);)而不是像我一样存储std::function<void(ARGS...)>对象。构造者必须相应地改变,当然

谢谢你的回答!

+0

你能编辑你的答案来包含你的工作解决方案吗? – 2013-03-08 21:45:40

2

我认为这个问题是applyTuple需要参考元组作为其第二个参数:

template < typename... ARGS > 
void applyTuple(std::function<void(ARGS...)>& f, 
       std::tuple<ARGS...> const& t) { 
    apply_func<sizeof...(ARGS), ARGS...>::applyTuple(f, t); 
} 

但,run里面,你传递一个指针元组,由于argument_pack是指针指向一个元组:

std::tuple<ARGS...> *argument_pack; 

如果更改run身体要

applyTuple<ARGS...>(m_f, *argument_pack); 

然后我认为你的问题应该消失。

希望这会有所帮助!

+0

哇,这是令人尴尬的......我正在抛弃可变模板,我无法在需要的地方解引用指针!无论如何,它仍然没有编译。感谢您指出错误!我更新了这个问题。 – steffen 2012-02-08 09:18:35

+0

只要当你省略一个小细节时,你会从编译器得到一个很好的清晰简明的错误信息,告诉你你做了什么,而不是一些复杂的模板混乱。 – CashCow 2012-02-08 18:32:15

0

你不能说apply_func<N-1>::...。这将用ARGS = {}实例化结构,因此“候选人期待2个参数,5个提供”错误。

此外,在applyTuple,你已经使用apply_func<sizeof...(ARGS), ARGS...>::applyTuple,这预计将接受4个参数:功能f,元组tARGS... args,但你无法通过ARGS,因此“候选预计4个参数, 2提供了“错误。

作为一个替代的解决方案,你可以用我的vtmp库,并使用

template<typename... ARGS> 
void Foo<ARGS...>::run() 
{ 
    utils::tuple_apply(*argument_pack, m_f); 
} 

(注:需要G ++ 4.7)

相关问题