2010-11-05 97 views
0

我使用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)

也許有解決我的問題更好的辦法...

回答

3

應該等同,但可以肯定的唯一方式是與你正在使用的編譯器進行測試。

請注意,您可以使用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函數或靜態成員函數。