通过 std::bind 传递右值
我想通过 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())
}
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())
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
失败的原因是,当您指定
foo
时,您要绑定的函数是:但是,
std::bind
传递的值将不会是一个右值,但是一个左值(作为成员存储在生成的bind
函子中的某个位置)。也就是说,生成的函子类似于:构造为
your_bind(Movable())
。因此,您可以看到此操作失败,因为Movable&&
无法绑定到Movable
。†一个简单的解决方案可能是这样的:
因为现在您调用的函数是:
并且调用工作正常(当然,如果需要,您可以使
foo
)。但一个有趣的问题是,我们是否可以让您的原始绑定起作用,我们可以通过:也就是说,我们只需在调用之前
std::move
参数,以便它可以绑定。但哎呀,这太丑了。强制转换是必需的,因为 std::move 是一个重载函数,因此我们必须通过强制转换为所需类型来指定我们想要的重载,从而消除其他选项。如果
std::move
没有重载,实际上不会那么糟糕,就好像我们有这样的东西:这更简单。但除非您有这样的函数,否则我认为很明显您可能只是想指定一个更明确的模板参数。
† 这与在没有显式模板参数的情况下调用函数不同,因为显式指定它消除了推断它的可能性。 (
T&&
,其中T
是模板参数,可以推导出任何东西,如果你愿意的话。)The reason this fails is because when you specify
foo<Movable>
, the function you're binding to is:However, the value passed by
std::bind
will not be an rvalue, but an lvalue (stored as a member somewhere in the resultingbind
functor). That, is the generated functor is akin to:Constructed as
your_bind(Movable())
. So you can see this fails becauseMovable&&
cannot bind toMovable
.†A simple solution might be this instead:
Because now the function you're calling is:
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: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 becausestd::move
is an overloaded function, so we have to specify which overload we want by casting to the desired type, eliminating the other options.It actually wouldn't be so bad if
std::move
wasn't overloaded, as if we had something like: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.
† 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&&
, whereT
is a template parameter, can be deduced to anything, if you let it be.)您可以使用 lambda 表达式。
这似乎是最简单的选择。
You could use a lambda expression.
This would seem to be the simplest option.
伙计们,我在这里编写了一个完美转发版本的活页夹(仅限 1 个参数)
http://code-slim-jim .blogspot.jp/2012/11/stdbind-not-compatable-with-stdmove.html
供参考,代码是
正如您从上面的概念证明中看到的那样,它很有可能......
我看不出任何原因为什么 std::bind 与 std::move 不兼容... std::forward 毕竟是完美转发的我不明白为什么没有 std::forwarding_bind ???
Guys i have hacked up a perfect forwarding version of a binder(limited to 1 param) here
http://code-slim-jim.blogspot.jp/2012/11/stdbind-not-compatable-with-stdmove.html
For reference the code is
As u can see from the above proof of concept, its very possible...
I see no reason why std::bind is incompatible with std::move... std::forward is after all for perfect forwarding I dont understand why there isnt a std::forwarding_bind ???
(这实际上是对 GMan 答案的评论,但我需要对代码进行一些格式化)。
如果生成的函子实际上是这样的:
则
编译无错误。因为可以使用右值分配和初始化数据,然后将数据值传递给 foo() 的右值参数。
但是,我认为绑定实现直接从 foo() 签名中提取函数参数类型。即生成的函子是:
事实上,这确实无法初始化右值数据成员。
也许,绑定实现只是没有正确地从函数参数类型中提取“未引用”类型,并“按原样”使用该类型作为函子的数据成员声明,而不修剪 &&。
正确的函子应该是:
(This is actually a comment to GMan's answer, but I need some formatting for the code).
If generated functor actually is like this:
then
compliles without errors. as it's possible to assign and initialize data with rvalue and then pass a data value to rvalue argument of the foo().
However, I suppose that bind implementation extracts function argument type directly from foo() signature. i.e. the generated functor is:
and indeed, this really fails to initialize rvalue data member.
Perhaps,the bind implpementation simply does not correctly extract "unreferenced" type from function argument type and uses this type for functor's data member declaration "as is", without trimming &&.
the correct functor should be:
GManNickG 的答案还有一项改进,我得到了很好的解决方案:(
适用于 gcc-4.9.2 和 msvc2013)
One more improvement in GManNickG's answer and I've got pretty solution:
(works in gcc-4.9.2 and msvc2013)