如何在C++中将参数包传递给void指针?

3
请考虑以下代码示例:
#include <functional>
#include <iostream>

template <typename... Ts>
class SomeClass
{
public:
    std::function<bool(Ts...)> some_func;

    void run(Ts... args)
    {
        this->some_func(args...); // this works

        this->thread_run((void *)&this->some_func, args); // this won't work, can't pass the parameter pack
    }

    static void thread_run(void *func_ptr, void *args_ptr)
    {
        auto thread_func = *(std::function<bool(Ts...)> *)(func_ptr);
        thread_func(2, 3);
    }
};

int main()
{
    SomeClass<int, int> a;

    a.some_func = [](int x, int y)
    { std::cout << "Arguments: " << x << " " << y << std::endl; return x > y; };

    a.run(2, 3);

    return 0;
}

如您所见,有一个类具有一个模板std::function成员变量。我可以通过给它一个lambda表达式来设置它,该表达式必须返回bool,但可以具有任意数量的参数,这很好!
不幸的是,我现在被要求使用给定的线程库(这是不可协商的)将此函数作为线程运行。线程库的入口函数必须是具有以下签名的static函数: void (*thread_entry_t)(void *p1, void *p2) 我已经成功将std::function变量传递给示例中的static函数,请参见thread_run()函数,但我找不到通过void*指针将参数包args传递给static函数的方法。
我该如何做呢?

传递一个 std::tuple - undefined
我从来没有使用过参数包,但是经过一些快速阅读后,我认为这些包实际上是作为多个参数实现的,并且没有简单的方法将多个参数转换为单个空指针,而不知道实际参数的数量和类型。确实,你需要更具体的东西,比如一个元组。 - undefined
1
auto args_tuple = std::make_tuple(args...); thread_run(&some_func, &args_tuple); And inside thread_run use std::apply - undefined
1
顺便问一下,图书馆功能不太清楚。p1p2是什么,是谁提供的? - undefined
3
为什么你需要这样做呢?难道你不能只使用std::jthread来进行多线程编程吗?我猜你是想使用一些特定于平台的线程库。为什么不尝试使用std版本呢? - undefined
1个回答

5
你可以将args...包装在一个元组中,并传递一个指向它的指针。我已经将它设为你的类的成员,以便它与std::function对象具有相同的生命周期。
template <typename... Ts>
class SomeClass
{
public:
    std::function<bool(Ts...)> some_func;
    std::tuple<Ts...> args;

    void run(Ts... args)
    {
        this->args = { args... };    
        thread_run((void *)&this->some_func, (void *)&this->args);
    }

    static void thread_run(void *func_ptr, void *args_ptr)
    {
        auto & thread_func = *(std::function<bool(Ts...)> *)(func_ptr);
        auto & args = *(std::tuple<Ts...> *)(args_ptr);
        std::apply(thread_func, args);
    }
};

你不需要使用this->,只需重命名其中一个args。而且你不需要使用void*类型转换。你应该使用static_cast代替C风格的转换。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接