Visual Studio 2013 C ++ - 将std :: unique_ptr传递给绑定函数

时间:2013-10-11 01:15:44

标签: c++ visual-studio c++11 visual-studio-2013

使用Visual Studio 2013 RC和C ++,我正在尝试将std::unique_ptr传递给使用std::bind绑定的函数。但是,我遇到了麻烦,因为当我尝试这个时,VS似乎并不喜欢它。这是我正在尝试编译的内容:

#include <memory>
#include <iostream>
#include <functional>

void func(std::unique_ptr<int> arg)
{
    std::cout << *arg << std::endl;
}

int main()
{
    std::function<void (std::unique_ptr<int>)> bound =
        std::bind(&func, std::placeholders::_1);

    std::unique_ptr<int> ptr(new int(42));
    bound(std::move(ptr));

    return 0;
}

这在GCC 4.8.1中编译,但在VS2013 RC中不编译。我在VS中一直遇到移动语义的问题,但我真的很想使用std::unique_ptr代替std::shared_ptr或原始指针。

我找到的一个解决方法是更改​​函数签名以接受std::unique_ptr&,它在VS和GCC中编译,但不会使func的意图取得{的所有权{1}}特别清楚,并且还阻止我安全地异步调用函数,除非我做一些特别难看的事情:

std::unique_ptr

有没有办法绕过这个而不改变#include <memory> #include <iostream> #include <functional> #include <future> #include <string> void func(std::unique_ptr<int>& arg) { std::cout << *arg << std::endl; } int main() { std::function<void (std::unique_ptr<int>&)> bound = std::bind(&func, std::placeholders::_1); std::unique_ptr<int> ptr(new int(42)); std::promise<void> prom; std::async( [&bound, &ptr, &prom] { std::unique_ptr<int> movedPtr = std::move(ptr); prom.set_value(); bound(std::move(movedPtr)); }); prom.get_future().wait(); // Wait here std::string dummy; std::cin >> dummy; } 的签名?

谢谢!

3 个答案:

答案 0 :(得分:2)

我最近和VS 2012有同样的问题。我相信这是MSVC中的一个错误;至少在MSVC ++ 11中,伪可变参数扩展似乎通过值将参数转发给某些内部函数。似乎这没有得到改善。
作为一种解决方法,我正在使用lambdas,但需要另一个hack才能使它工作:

std::function<void (std::unique_ptr<int>)> bound =
    [] (std::unique_ptr<int> arg) { func(std::move(arg)); };

仍然无法编译。但是如果添加任何捕获的值(即使是未使用的值),它也会编译:

int x;
std::function<void (std::unique_ptr<int>)> bound =
    [x] (std::unique_ptr<int> arg) { func(std::move(arg)); };

答案 1 :(得分:1)

您还必须将参数移动到func的绑定调用中。不仅在bound

的调用中
bound(std::move(ptr));

但也在绑定中:

std::function<void(std::unique_ptr<int>)> bound =
    std::bind(func,
              std::bind(std::move<std::unique_ptr<int>&>,
                        std::placeholders::_1));

这是我在VS2013(更新4)中编译的。

答案 2 :(得分:0)

std::bind绑定的函数不转发参数,它将它们复制到函数中。因此,std::bind不适用于c ++ 11中的仅移动类型。这个问题是“更完美转发”(like this one)提案背后的想法。有一个更新的,但我现在似乎无法找到它。