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

标签 c++ templates c++11 tuples variadic-functions

我使用 C++0x 有一段时间了,现在我想使用可变参数模板和元组来实现类“任务”。我将把 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::functionstd::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) {}
    // ...

这允许用户选择要传递的内容,而不是强制他使用自由函数或静态成员函数。

关于c++ - 将元组的内容作为可变函数参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4105002/

相关文章:

c++ - 将值从一个数组插入到另一个直接排序

c++ - 如何让 this_thread::sleep_for(while)?

c++ - 确定涉及模板类型参数的表达式的结果类型?

c++ - 转换嵌套包的每个内包

c++ - 为什么 C++ 不允许模板重载?

c++ - 如何在构造函数的初始化列表中初始化共享指针?

c++ - C++11赋值运算符副作用的求值顺序

c++ - CAsyncSocket receive()返回值

c++ - 有什么类似 Watin 的东西可以用于 C++ 吗?

c++ - 如何保护 C++03 和 C++11 的移动构造函数?