在C ++中,如何在“Args&& ... args”参数列表中添加参数?

时间:2018-05-10 16:50:34

标签: c++ arguments variadic-functions

我有自己的线程实现,允许我管理与线程通信的各种方式。它基于C ++ std::thread类。

我创建了一个线程来运行一个名为run()的函数来调用用户函数。我希望能够做的是调用用户函数,包括我的线程对象指针。

我在构造函数中遇到问题。我想传递构造函数中指定的Args并将this添加到该列表中:

class safe_thread
{
public:
    typedef std::shared_ptr<safe_thread>    pointer_t;
    typedef std::vector<pointer_t>          vector_t;

    template<class Function, class... Args>
    safe_thread(Function&& f, Args&&... args)
        : f_function([this, f, args...]{ std::bind(f, this, args...)(); })
    {
[...snip...]

private:
    std::function<void()>               f_function;
};

// I use that constructor with two different types of signatures:
//
// 1. member function
//
safe_thread listen(&my_other_class::some_function, this);

// 2. static function
//
safe_thread worker(&my_static_function);

std::bind()无法理解我当前的语法。它需要一个函数(f)和args...。那么,我如何更改 args...以包含this

1 个答案:

答案 0 :(得分:0)

对于那些感兴趣的人,我实际上找到了一个解决方案,即将this参数移动到列表的末尾。这样我的成员函数std::invoke()或标准静态函数的工作方式相同:

f_function([this, f, args...]{ std::invoke(f, args..., this)(); })

如果没有这个,正如Miles Budnek所提到的那样,需要一大堆SFINAE才能知道f是成员函数还是普通函数。

问题在于,在某些情况下,我会在成员函数中创建一个线程,而在其他情况下,我会创建一个静态函数的步骤。

如果是成员函数,args...列表中的第一个参数是调用者的this,显然this不能作为下一个参数移动。

实际上,我的第一次尝试产生了这个:

std::invoke(
    &my_other_class::some_func,     // correct
    safe_thread::this,              // wrong 'this' (i.e. safe_thread)
    my_other_class::this,           // 'this' for function, wrong location
    ...);                           // other parameters

通过更改通话中的顺序,我现在可以在正确的位置找到正确的'this':

std::invoke(
    &my_other_class::some_func,     // correct
    my_other_class::this,           // 'this' for function, correct location
    ...,                            // other parameters
    safe_thread::this);             // 'this' to safe_thread

显然这意味着我必须修复被调用函数的签名,但我对此很好。

如tkausl所述,std::bind()不是必需的。有关详细信息,请参阅注释。话虽如此,std::invoke()是C ++ 17,所以如果你仍然使用旧版本,你可能必须坚持使用std::bind()