c – 如何将std :: reference_wrapper转换为rvalue lambda?

前端之家收集整理的这篇文章主要介绍了c – 如何将std :: reference_wrapper转换为rvalue lambda?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
this article它说下面的代码是有效的C 11,并与GNU的libstdc:
int n;
std::vector<int> v;
...
std::function<bool(int)> f(std::cref([n](int i) {return i%n == 0));
std::count_if(v.begin(),v.end(),f);

事实是,我相信在调用站点上要创建的lambda对象,这将使它成为这个代码段中的一个临时对象,因为它不存储在任何变量上,而是正在创建和传递一个const引用到std ::函数.如果是这样,那么lambda对象应该已经被破坏了,在f中留下一个悬挂的引用,当std :: count_if使用时会导致未定义的行为.

假设文章没有错,我的心理模型有什么问题?当lambda对象被破坏时?

解决方法

好的,我们从基础开始:上面的代码当然是不合法的,因为它在一些相当基本的方式是不正确的.线
std::function<bool(int)> f(std::cref([n](int i) {return i%n == 0));

最低限度需要写成

std::function<bool(int)> f(std::cref([n](int i) {return i%n == 0;}));

请注意,代码是在Dr.Dobb的文章中写成的,就像在问题中一样,即代码合法的任何陈述都已经很有问题了.

一旦解决了简单的语法错误,下一个问题是std :: cref()是否可以实际用于绑定到rvalue.根据5.1.2 [expr.prim.lambda]第2段(感谢DyP参考),lambda表示显然是一个暂时的.由于将引用绑定到临时文件通常是一个相当糟糕的主意,因此std :: cref()将是规避此限制的一种方式.事实证明,根据20.10 [function.objects]第2段std :: cref()被声明为

template <class T> reference_wrapper<const T> cref(const T&) noexcept;
template <class T> void cref(const T&&) = delete;
template <class T> reference_wrapper<const T> cref(reference_wrapper<T>) noexcept;

也就是说,即使纠正语法错误,语句也是不正确的. gccclang都不编译此代码(我已经使用了两个编译器的相当近期版本及其各自的标准C库).也就是说,基于上述声明,这段代码显然是非法的!

最后,没有什么可以延长上述表达式中的临时性生命周期.临时扩展的唯一原因是它或其一个数据成员立即绑定到[const]引用.围绕临时包装函数调用可以禁止这个终身延期.

总结:文章引用的代码在许多不同层次上是不合法的!

猜你在找的C&C++相关文章