传递值通过std :: bind [英] Passing rvalues through std::bind

查看:129
本文介绍了传递值通过std :: bind的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过 std :: bind 将值传递给在C ++ 0x中使用右值引用的函数。我不知道该怎么做。例如:

I want to pass an rvalue through std::bind to a function that takes an rvalue reference in C++0x. I can't figure out how to do it. For example:

#include <utility>
#include <functional>

template<class Type>
void foo(Type &&value)
{
    Type new_object = std::forward<Type>(value);    // move-construct if possible
}

class Movable
{
public:
    Movable(Movable &&) = default;
    Movable &operator=(Movable &&) = default;
};

int main()
{
    auto f = std::bind(foo<Movable>, Movable());
    f();    // error, but want the same effect as foo(Movable())
}


推荐答案

失败的原因是当你指定 foo< Movable> 时,你绑定的函数是:

The reason this fails is because when you specify foo<Movable>, the function you're binding to is:

void foo(Movable&&) // *must* be an rvalue
{
}

但是, std :: bind 传递的值不会是一个右值,但是一个左值(存储在结果 bind 函数中的某个成员)。生成的函子类似于:

However, the value passed by std::bind will not be an rvalue, but an lvalue (stored as a member somewhere in the resulting bind functor). That, is the generated functor is akin to:

struct your_bind
{
    your_bind(Movable arg0) :
    arg0(arg0)
    {}

    void operator()()
    {
        foo<int>(arg0); // lvalue!
    }

    Movable arg0;
};

构造为 your_bind(Movable()) 。因此,您可以看到此失败,因为 Movable&& 不能绑定到 Movable 。†

Constructed as your_bind(Movable()). So you can see this fails because Movable&& cannot bind to Movable.†

一个简单的解决方案可能是这样的:

A simple solution might be this instead:

auto f = std::bind(foo<Movable&>, Movable());

因为现在调用的函数是:

Because now the function you're calling is:

void foo(Movable& /* conceptually, this was Movable& &&
                        and collapsed to Movable& */)
{
}

调用工作正常(当然,你可以使 foo< const Movable&> )。但一个有趣的问题是,如果我们可以得到你的原始绑定工作,我们可以通过:

And the call works fine (and, of course, you could make that foo<const Movable&> if desired). But an interesting question is if we can get your original bind to work, and we can via:

auto f = std::bind(foo<Movable>,
            std::bind(static_cast<Movable&&(&)(Movable&)>(std::move<Movable&>),
                Movable()));

也就是说,我们只是 std :: move 在我们进行调用之前的参数,所以它可以绑定。但是,yikes,这是丑陋。需要转换,因为 std :: move 是一个重载函数,因此我们必须指定重载我们想要的,通过转换到所需的类型,消除其他选项。

That is, we just std::move the argument before we make the call, so it can bind. But yikes, that's ugly. The cast is required because std::move is an overloaded function, so we have to specify which overload we want by casting to the desired type, eliminating the other options.

如果 std :: move 没有重载,实际上不会那么糟糕,好像我们有类似的东西:

It actually wouldn't be so bad if std::move wasn't overloaded, as if we had something like:

Movable&& my_special_move(Movable& x)
{
    return std::move(x);
}


auto f = std::bind(foo<Movable>, std::bind(my_special_move, Movable()));

这更简单。但是除非你有这样的函数,我想你很可能只是想指定一个更明确的模板参数。

Which is much simpler. But unless you have such a function laying around, I think it's clear you probably just want to specify a more explicit template argument.

†这与调用没有显式模板参数的函数不同,因为显式指定它会删除它被推断的可能性。 ( T&&& ,其中 T 是模板参数,可以推导为 >,如果您允许。)

† This is different than calling the function without an explicit template argument, because explicitly specifying it removes the possibility for it to be deduced. (T&&, where T is a template parameter, can be deduced to anything, if you let it be.)

这篇关于传递值通过std :: bind的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆