首页 文章

调用函数并传递存储在元组中的参数?

提问于
浏览
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'进行编译,则最后一行的下一行将显示以下错误:

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 ...>&)

我错过了什么?谢谢!

3 回答

  • 2

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

    • 用户指出的指针错误:templatetypedef

    • 我不得不在这篇文章中回到apply tuple的原始版本:How do I expand a tuple into variadic template function's arguments? . 我将所有模板参数更改为 ARGS... ,因为对于元组,函数和类,它们都是相同的 . 老实说,我仍然没有工作......

    • 函数指针必须像我一样存储( void (*m_f) (ARGS...); )而不是 std::function<void(ARGS...)> 对象 . 当然,必须相应地更改构造函数

    谢谢你的回答!

  • 0

    我认为问题是 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

    你不能说 apply_func<N-1>::... . 这将使用 ARGS = {} 实例化结构,因此"candidate expects 2 arguments, 5 provided"错误 .

    此外,在 applyTuple 中,您使用了 apply_func<sizeof...(ARGS), ARGS...>::applyTuple ,它希望接受4个参数:函数 f ,元组 tARGS... args ,但是您无法传递参数,因此"candidate expects 4 arguments, 2 provided"错误 .

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

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

    (注意:要求g 4.7)

相关问题