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

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

#include #include #include <功能>void func(std::unique_ptr arg){std::cout <<*arg<)>界 =std::bind(&func, std::placeholders::_1);std::unique_ptrptr(new int(42));边界(标准::移动(ptr));返回0;}

这可以在 GCC 4.8.1 中编译,但不能在 VS2013 RC 中编译.我总是在 VS 中遇到移动语义的问题,但我真的很喜欢使用 std::unique_ptr 而不是 std::shared_ptr 或原始指针.>

我发现的一种解决方法是更改??函数签名以接受 std::unique_ptr&,它确实在 VS 和 GCC 中编译,但不符合 的意图func 特别清楚地获得 std::unique_ptr 的所有权,并且还阻止我安全地异步调用该函数,除非我做了一些特别难看的事情:

#include #include #include <功能>#include <未来>#include <字符串>void func(std::unique_ptr<int>&arg){std::cout <<*arg<&)>界 =std::bind(&func, std::placeholders::_1);std::unique_ptrptr(new int(42));std::promise舞会;标准::异步([&bound、&ptr、&prom]{std::unique_ptrmovedPtr = std::move(ptr);prom.set_value();边界(标准::移动(移动Ptr));});prom.get_future().wait();//在这里等候std::string 虚拟对象;std::cin >>假;}

有没有办法在不改变func的签名的情况下解决这个问题?

谢谢!

解决方案

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

std::function)>界 =[] (std::unique_ptr arg) { func(std::move(arg));};

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

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

Using Visual Studio 2013 RC and C++, I'm trying to pass an std::unique_ptr to a function that has been bound using std::bind. However, I'm having trouble because VS doesn't seem to like it when I try this. Here's what I'm trying to compile:

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

This compiles in GCC 4.8.1, but not in VS2013 RC. I've always had problems with move semantics in VS, but I'd really like to use std::unique_ptr instead of std::shared_ptr or raw pointers.

One workaround I've found is to change the function signature to accept an std::unique_ptr&, which does compile in VS and GCC, but doesn't make the intent of func taking ownership of the std::unique_ptr particularly clear, and also prevents me from safely asynchronously calling the function unless I do something particularly ugly:

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

Is there a way to get around this without changing func's signature?

Thanks!

解决方案

I had the same problem with VS 2012 recently. I believe this is a bug in MSVC; at least in MSVC++11 the pseudo-variadic expansion seems to forward the parameters by value to some internal function. Seems this hasn't been improved.
As a workaround, I'm using lambdas instead, but another hack is required to make it work:

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

still doesn't compile. But if you add any captured value (even one that isn't used), it compiles:

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

相关文章