在std::bind中包装lambda以捕获r值
Wrapping a lambda in std::bind to capture R-value
我有一种情况,我被困在一个c++ 11只编译器(gcc 4.7.2,所以我没有访问c++ 14广义lambda捕获),所以我使用std::bind
作为一个解决方案,如果我需要捕获一个移动对象。
我从这个stackoverflow的答案中读到了这个解决方法,并且我已经成功地使用了这个技术。
然而,我有一种情况,我通过转发绑定表达式作为另一个绑定表达式的绑定参数来形成高阶函子。
我可以把它简化成一个例子。这个例子是为了回答这个问题而设计和简化的:
template <class F>
void func(F&& func)
{
auto f = std::bind(
[](F& f) -> void
{
},
std::forward<F>(func)
);
f(); // causes compiler error
}
int main()
{
func(
std::bind(
[]() { }
)
);
}
由于我无法理解的原因,当我调用f()
时,编译器会生成一大堆错误。我将尽量简化它,而不是粘贴整个错误消息:
test7.cpp:22:2: error: no match for call to ‘(std::_Bind<func(F&&) [with F = std::_Bind<main()::<lambda()>()>]::<lambda(std::_Bind<main()::<lambda()>()>)>(std::_Bind<main()::<lambda()>()>)>) ()’
这个错误是由GCC 4.7.2产生的。
我看不出为什么会发生这种事。在上面的人为示例中,您将注意到,在main()
中,我在空lambda周围有一个额外的bind
表达式。如果我删除bind
表达式,并简单地传递空lambda,如:
func([]() { });
…然后没有错误发生。但同样,这是一个人为的示例—在实际应用程序中,我需要将lambda包装在bind
表达式中,以便进行移动捕获。我看不出[](){}
和std::bind([](){})
在语义上有什么不同。它们在功能上应该是等价的,即使它们的计算结果是不同的类型。
当传递给bind(f, args...)
的参数之一是调用bind(g, args...)
的结果时,传递给f
的参数是对g
求值的结果(参见[function .bind])。/10,特别是子弹10.2)。在您的程序中,计算lambda [](){}
的结果作为第一个参数传递给[](F& f)
,这当然是错误的。
不太好看的解决方案:为内部绑定表达式引入一个包装器类,它隐式地转换为引用到包装的类型:
template <class F>
class protect_bind_expression {
F f_;
public:
protect_bind_expression(F f) :
f_{std::move(f)} {}
operator F&() { return f_; }
};
template <class F>
protect_bind_expression<typename std::decay<F>::type>
protect(F&& f) {
return {std::forward<F>(f)};
}
template <class F>
void func(F&& func)
{
auto f = std::bind(
[](F&){},
protect(std::forward<F>(func))
);
f(); // Doesn't cause compiler error
}
- std::vector的包装器,使数组的结构看起来像结构的数组
- 如何在c++迭代器类型中包装std::chrono
- 将函数包装器转换为 std::function
- std::reference_wrapper 打开包装器
- 将 std::vector<double> 从 C++ 包装到 C 以在 Swift 中使用
- std::带有颜色和标题的 clog 包装器无法正确打印整数
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- 使用"std::enable_if"转发包装失败
- std::包含 std::函数回调的多个包装器的向量不起作用
- pybind11:如何包装以 std::vector<double> 为参数以避免数据复制的 C++ 函数
- 在同一接口中包装不同的 std::vector<T>
- 包装 std::istream 时出现问题,移动后unique_ptr不为空
- Swig:如何从SwigpyObject获取包装std :: shared_ptr的值
- SWIG:包装 std::map<key 时编译器错误,val *>
- SWIG-包装STD ::一对串时的内存泄漏
- 包装 std C++功能有时是一个坏主意
- 使用 boost::p ython vector_indexing_suite 包装 std::vector
- 在帮助程序方法中包装 std::get<>
- 包装std::忽略
- 在自定义类中包装std::packaged_task