是否有一个reference_wrapper<>对于右值引用?
我想知道如何完成以下操作
void f(string &&s) {
std::string i(move(s));
/* other stuff */
}
int main() {
std::string s;
bind(f, s)(); // Error.
bind(f, move(s))(); // Error.
bind(f, ref(s))(); // Error.
}
如何传递右值引用并将其作为右值引用(可能已包装)存储在调用包装器中?我知道我可以手动编写一个类似 std::reference_wrapper<>
的类,它具有到 T&&
的转换函数,但我宁愿避免这种情况并使用标准技术。
我按照 AProgrammer 的建议实现了它:
template<typename T> struct adv {
T t;
explicit adv(T &&t):t(forward<T>(t)) {}
template<typename ...U> T &&operator()(U &&...) {
return forward<T>(t);
}
};
template<typename T> adv<T> make_adv(T &&t) {
return adv<T>{forward<T>(t)};
}
namespace std {
template<typename T>
struct is_bind_expression< adv<T> > : std::true_type {};
}
现在我可以说,
void f(string &&s) {
std::string i(move(s));
/* other stuff */
}
int main() {
std::string s;
bind(f, make_adv(move(s)))(); // Works!
}
如果我们将左值传递给 make_adv
,它会将其作为引用输入参数的左值转发,因此它可以用作 的替代品>std::ref
,在本例中。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我对此的看法。
N3225 中的 20.8.10.1.2/10
因此,拥有右值引用的唯一可能是让
is_bind_expression::value
true 或is_placeholder::value
不为零。第二种可能性会产生您不想要的影响,并且通过第一种可能性实现想要的结果意味着,如果我们限制为标准提供的类型,我们试图解决的问题就得到了解决。因此,唯一的可能性是提供您自己的包装器和is_bind_expression
的专门化(20.8.10.1.1/1 允许),因为我没有看到。My take on this.
20.8.10.1.2/10 in N3225
So the only possibility to have a rvalue reference is to have
is_bind_expression<TiD>::value
true oris_placeholder<TiD>::value
not zero. The second possibility has implications you don't want and achieving the wanted result with the first would imply that the problem we are trying to solve is solved if we restrict to the standard provided types. So, the only possibility would be to provide your own wrapper and a specialisation foris_bind_expression<TiD>
(that is allowed by 20.8.10.1.1/1) as I don't see one.这里的问题是这样的绑定函数对象可以被多次调用。如果函数对象将绑定参数作为右值转发,则显然只能工作一次。所以,这是一个安全问题。
但在某些情况下,这种转发正是您想要的。您可以使用 lambda 作为中介:
基本上,我想出了这个绑定+lambda 组合作为缺少“移动捕获”的解决方法。
The problem here is that such a bind function object can be invoked multiple times. If the function object forwarded a bound parameter as rvalue this would obviously only work once. So, this is a bit of a safety issue.
But in some cases this kind of forwarding is exactly what you want. You could use a lambda as an intermediary:
Basically, I came up with this bind+lambda combination as a workaround for a missing "move-capture".
当我偶然发现这个问题时,我正在谷歌搜索“reference_wrapper for rvalues”。
不确定我的答案是否有用,它与 std::bind 无关,并且实际上不适用于它,但对于其他一些用例,它可能会对某人有所帮助。
这是我实现 rvalue_reference_wrapper 的尝试:
命名空间 std 中的最后一个专业化允许 MSVC 标准库的实现与我的类型一起使用,例如使用 std::make_tuple 时:
我相信为其他标准实现类似的“展开”逻辑并不困难库的实现。
I was googling for "reference_wrapper for rvalues" when I stumbled on this question.
Not sure whether my answer would be useful, it is not related to std::bind and actually doesn't work with it, but for some other use cases it might help somebody.
Here's my attempt to implement rvalue_reference_wrapper:
The last specialization in namespace std allows MSVC's implementation of standard library to work with my type, e.g. when using std::make_tuple:
I believe it would not be hard to implement similar "unwrapping" logic for other standard library implementations.
您可以使用可变的 lambda 对象。
You can use a mutable lambda object.