将元组的内容作为可变参数函数参数传递

问题描述:

我使用C++ 0x播放了一段时间,现在我想使用可变参数模板和元组来实现“Task”类。我将把Task对象传递到新创建的线程中(使用pthread)。任务类将包含功能函数指针应该内螺纹和参数此函数调用,简化代码:将元组的内容作为可变参数函数参数传递

class TaskCaller 
{ 
    // ... 
    virtual bool dispatch (void); 
}; 

template<typename ...T_arguments> Task : 
    public TaskCaller 
{ 
    public: 
     // ... 
     Task (bool   (*function) (T_arguments&...), 
       T_arguments... arguments) : 
        function_arguments_tuple (arguments...), 
        function (function) 
     { 
      // ... 
     } 

     bool dispatch (void) 
     { 
      return TupleUnpack<sizeof ...(T_arguments)>::unpack (this->function, this->function_arguments_tuple); 
     } 

    private: 
     std::tuple<T_arguments&...> function_arguments_tuple; 
     bool      (*function) (T_arguments...); 
}; 

和代码,我用它来解压缩解析成函数参数:

template<unsigned int i> class TupleUnpack 
{ 
    public: 
     template<typename T_return_type, typename ...T_tuple_arguments, typename ...T_function_arguments> 
      inline static T_return_type unpack (T_return_type      (*function) (T_tuple_arguments&...), 
               std::tuple<T_tuple_arguments...>& arguments_tuple, 
               T_function_arguments    ...function_arguments) 
      { 
       return TupleUnpack<i-1>::unpack (function, arguments_tuple, std::get<i-1> (arguments_tuple), function_arguments...); 
      }      
}; 

template<> class TupleUnpack<0> 
{ 
    public: 
     template<typename T_return_type, typename ...T_tuple_arguments, typename ...T_function_arguments> 
      inline static T_return_type unpack (T_return_type      (*function) (T_tuple_arguments&...), 
               std::tuple<T_tuple_arguments...>& arguments_tuple, 
               T_function_arguments    ...function_arguments) 
      { 
       return function (function_arguments...); 
      }   
}; 

使用案例:

bool task_function (Foo &foo, Bar &bar) 
{ 
    // ... 
    return true; 
} 

void* thread_function (void* argument) 
{ 
    Task* task ((Task*) argument); 

    task->dispatch(); 

    delete task; 

    pthread_exit (0); 
} 

void function (void) 
{ 
    Foo    foo (1, 2, 3); 
    Bar    bar (1, 2, 3); 
    Task<Foo, Bar>* task = new Task (task_function, std::move (foo) std::move (bar)); 
    pthread_t  thread_id; 

    pthread_create (&thread_id, task_function, task); 
} 

我还没有测试过这个代码,但它只是和想法。

现在我想知道TupleUnpack类如何影响最终代码。根据我的知识,Task :: dispatch函数(编译器解析模板之后)的最终实现将相当于:

template<typename ...T_arguments> static bool Task<...T_arguments>::dispatch (void) 
{ 
    return this->function (std::get<0> (this->function_arguments_tuple), std::get<1> (this->function_arguments_tuple), ..., std::get<n> (this->function_arguments_tuple)); 
} 

对不对?

此外,元组本身和std :: get()应该在最终代码中“消失”,并且不提供运行时开销(according to Boost documentation)

也许有解决我的问题更好的办法...

应该等同,但可以肯定的唯一方式是与你正在使用的编译器进行测试。

请注意,您可以使用std::function而不是std::bind。是这样的:

template<typename ...T_arguments> class Task : public TaskCaller 
{ 
    std::function<bool (T_arguments&...)> functor; 
public: 
    Task (bool (*func)(T_arguments&...), T_arguments... arguments) 
     : functor(std::bind(func, arguments...)) 
    {} 
    bool dispatch() { 
     return functor(); 
    } 
    // ... 

或者更好的是,让用户通过一个std::function在:

class Task : public TaskCaller { 
    std::function<bool()> functor; 
public: 
    Task(std::function<bool()> func) : functor(func) {} 
    // ... 

,允许用户选择什么来传递,而不是强迫他使用free函数或静态成员函数。