Std::bind和unique_ptr语言 - 如何移动

std::bind and unique_ptr - how to move only?

本文关键字:何移动 移动 语言 bind unique ptr Std      更新时间:2023-10-16

我必须通过低级系统例程调用函数,该例程获得传递的函数和参数。

void doLater(void* func, void* arg);

我想用bind调用任何函数和参数的callLater函数。所以:

template<typename Call>
void caller(void *arg) {
    std::unique_ptr<Call> upCall(static_cast<Call*>(arg));
    (*upCall)();
}
template<class Function, class... Args>
void callLater(Function &&f, Args&&...args) {
  typedef decltype(std::bind(std::forward<Function>(f), std::forward<Args>(args)...))) Call;
  Call* call = new Call(std::bind(std::forward<Function>(f), std::forward<Args>(args)...));
  doLater(caller<Call>, (void*) call);
}

与std::unique_ptr一起使用会产生不需要的副本,因此无法编译。

std::function<void(std::unique_ptr<int>)> foo = [](std::unique_ptr<int> i) {
  std::cout << "Hello world!n";
};
std::unique_ptr<int> value = std::make_unique<int>(1);
callLater(foo, std::move(value));

使用删除功能的std:: unique_ptr<_Tp _Dp>:: unique_ptr…

一个可能的解决方法是使用std::__bind_simple,就像在std::thread (gcc)中使用的那样,但它不是标准化的。你知道怎么解决这个问题吗?

生活例子。

这是一个概念的证明,你可能会把它添加到你正在寻找的表单中。

arg parameter to callLater:

首先,callLater将参数作为void*,所以你需要传递一个指向它的指针。

因此,我建议在堆上分配一个std::function,然后将其地址传递为arg

因为你只能传递1个参数,而且这个参数必须是指向std::function的指针,所以你必须绑定所有你想传递给std::function调用的函数的参数。

因此,std::function的格式必须为std::function<void()>

std::function<void()>* fn = new std::function<void()>;
// have to bind all arguments here
*fn = std::bind(func, i, d);

func parameter to callLater:

对于传递给callLater的函数void*,它必须是一个自由函数,将void* arg强制转换为std::function指针,然后解引用该指针以调用其operator()()

void arg_to_func(void* arg)
{
    std::unique_ptr<std::function<void()>> fn(reinterpret_cast<std::function<void()>*>(arg));
    (*fn)();
}
工作的例子:

下面是一个绑定函数和lambda的工作示例:

#include <iostream>
#include <functional>
#include <memory>
void callLater(void* f, void* arg)
{
    using fp = void(*)(void*);
    fp func = (fp)f;
    (*func)(arg);
}
using Call = std::function<void()>;
void arg_to_func(void* arg)
{
    std::unique_ptr<Call> fn(reinterpret_cast<Call*>(arg));
    (*fn)();
}
void func(int i, double d)
{
    std::cout << "func " << i << ' ' << d << 'n';
}
int main()
{
    // arguments we're going to capture
    int i = 5;
    double d = 2.3;
    Call* fn;
    // using std::bind to capture the variables
    fn = new Call;
    *fn = std::bind(func, i, d);
    callLater((void*)arg_to_func, fn);
    // using a lambda to capture the variables
    fn = new Call;
    *fn = [=](){ std::cout << "lambda " << i << ' ' << d << 'n'; };
    callLater((void*)arg_to_func, fn);
    return 0;
}
输出:

func 5 2.3
lambda 5 2.3