Lambda适用于最新的Visual Studio,但在其他地方不起作用

Lambda Works on Latest Visual Studio, but Doesn't Work Elsewhere

本文关键字:其他 不起作用 最新 适用于 Visual Studio Lambda      更新时间:2023-10-16

所以我已经写了一个讨厌的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社区2015更新3版14.0.25425.01这将输出所需的内容:

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

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

您依靠以下事实:您传递到算法的确切闭合是用作谓词的算法,但是标准允许它复制:

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

这正是libstdc 所做的。来自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内有点增加,但这不会改变呼叫站点的发生。

>

要解决此问题,您可以使用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))));

实时演示

相关文章: