std :: bind和unique_ptr - 如何只移动?

时间:2016-11-09 08:47:53

标签: c++ c++11 callback unique-ptr

我必须通过一个低级系统例程调用一个函数,它会传递函数和参数。

Object obj = parser.parse(new FileReader("D:\\demo.json"));

              JSONObject jsonObject = (JSONObject) obj;
              for (Object key : jsonObject.keySet()) {
                //based on you key types
                String keyStr = (String)key;
                Object keyvalue = jsonObject.get(keyStr);

                //Print key and value
               System.out.println("key: "+ keyStr + " value: " + keyvalue);
                if(Driver.driver.findElement(By.name(keyStr)).isDisplayed() && Driver.driver.findElement(By.name(keyStr)).isEnabled())
                      Driver.driver.findElement(By.name(keyStr)).sendKeys((keyvalue.toString()));   

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

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

将它与std :: unique_ptr一起使用会导致不需要的副本,因此无法编译。

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);
}

使用已删除的功能&#39; std :: unique_ptr&lt; _Tp,_Dp&gt; :: unique_ptr ...

一种可能的解决方法是使用 std :: __ bind_simple ,就像在std :: thread(gcc)中使用它一样,但它不是标准化的。知道如何解决这个问题吗?

Live example.

1 个答案:

答案 0 :(得分:1)

这是一个概念证明,您可以按照您正在寻找的形式进行按摩。

arg参数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参数callLater

对于传递给void*的函数callLater,它必须是一个将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