c++ - 通过 std::bind 传递右值

标签 c++ c++11 std rvalue-reference rvalue

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

#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> ,你要绑定(bind)的函数是:

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

但是,std::bind 传递的值不会是右值,而是左值(作为成员存储在结果 bind 仿函数中的某处)。也就是说,生成的仿函数类似于:

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

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

    Movable arg0;
};

构造为 your_bind(Movable()) .所以你可以看到这失败了,因为 Movable&&无法绑定(bind)到 Movable .†

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

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

因为现在你调用的函数是:

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

而且通话效果很好(当然,如果需要,您可以调用 foo<const Movable&>)。但一个有趣的问题是,我们是否可以让您原来的绑定(bind)工作,我们可以通过:

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

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

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

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


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

这要简单得多。但除非你有这样的函数,否则我认为很明显你可能只想指定一个更明确的模板参数。


† 这与在没有显式模板参数的情况下调用函数不同,因为显式指定它消除了推导它的可能性。 ( T&& ,其中 T 是模板参数,可以推导出为 anythingif you let it be 。)

关于c++ - 通过 std::bind 传递右值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4871273/

相关文章:

c++ - std::stack 如何组织内部存储?

c++ - 如何使用Visual Studio调试从VBA调用的C++ DLL函数

c++ - 使用枚举基编写枚举时出现不明确的重载,但仅使用 clang

c++ - std::pair 是否存在类似 std::tie 的东西?

c++ - 将 vector <int> 保存到文件

c++ - std::atomic <>后递增何时发生?

c++ - std::list,仅使用迭代器移动列表中的项目

c++ - 如何将 C++ 预处理器应用于 Ubuntu 上的 C++ 头文件

c++ - 对数组的引用

c++ - SqlQuery 一个命名占位符多次