Lambda可在最新的Visual Studio上运行,但在其他地方无法使用 [英] Lambda Works on Latest Visual Studio, but Doesn't Work Elsewhere

查看:144
本文介绍了Lambda可在最新的Visual Studio上运行,但在其他地方无法使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我为写了一个讨厌的lambda,满足实现此问题所需的最短代码" :

values.resize(distance(
    begin(values),
    remove_if(begin(values), end(values),
        [i = 0U, it = cbegin(intervals), end = cend(intervals)](const auto&) mutable {
        return it != end && ++i > it->first && (i <= it->second || (++it, true));
    })
));

我的问题是,在Visual Studio Community 2015 Update 3版本14.0.25425.01上,此输出是所需的:

My problem is that on Visual Studio Community 2015 Update 3 version 14.0.25425.01 this outputs the desired:

4.2 9.1 2.3 0.6 6.4 3.6 1.4 7.5

4.2 9.1 2.3 0.6 6.4 3.6 1.4 7.5

但是在我尝试过的所有其他编译器上,我得到了:

4.2 2.3 0.6 1.2 0.3 1.4 2.5 7.5

4.2 2.3 0.6 1.2 0.3 1.4 2.5 7.5

谁能告诉我是什么导致了不同的行为?

Can anyone tell me what's causing the different behavior?

推荐答案

您所依赖的事实是,传递给算法的确切闭包是用作谓词的闭包,但是标准允许将其复制:/p>

You are relying on the fact that the exact closure you pass into the algorithm is the one used as the predicate, but the standard allows it to be copied:

[algorithms.general]/10 (N4140):[注意:除非另有说明,否则允许复制以函数对象作为参数的算法 这些功能对象是自由的.对于对象身份很重要的程序员,应考虑使用 指向未复制的实现对象(例如reference_wrapper(20.9.3))的包装器类, 或一些等效的解决方案. —尾注]

[algorithms.general]/10 (N4140): [Note: Unless otherwise specified, algorithms that take function objects as arguments are permitted to copy those function objects freely. Programmers for whom object identity is important should consider using a wrapper class that points to a noncopied implementation object such as reference_wrapper (20.9.3), or some equivalent solution. —end note ]

这正是libstdc ++所做的.从v6.2.1开始:

This is exactly what libstdc++ does. From v6.2.1:

template<typename _ForwardIterator, typename _Predicate>
_ForwardIterator
__remove_if(_ForwardIterator __first, _ForwardIterator __last,
            _Predicate __pred)
{
    __first = std::__find_if(__first, __last, __pred);
    if (__first == __last)
    return __first;
    _ForwardIterator __result = __first;
    ++__first;
    for (; __first != __last; ++__first)
    if (!__pred(__first))
        {
        *__result = _GLIBCXX_MOVE(*__first);
        ++__result;
        }
    return __result;
}

在函数开始处对std::__find_if的调用复制了__pred,这意味着i的值在std::__find_if内增加了一点,但这不会改变调用的过程网站.

That call to std::__find_if at the start of the function copies __pred, which means that the value of i is incremented a bit within std::__find_if, but this doesn't change what's going on at the call site.

要解决此问题,您可以使用std::ref:

To fix this problem, you could use std::ref:

auto clos = [i = 0U, it = cbegin(intervals), end = cend(intervals)](const auto&) mutable {
    return it != end && ++i > it->first && (i <= it->second || (++it, true));
};
values.resize(distance(begin(values), std::remove_if(begin(values), end(values), std::ref(clos))));

实时演示

这篇关于Lambda可在最新的Visual Studio上运行,但在其他地方无法使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆