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

标签 c++ visual-studio visual-studio-2015 lambda compiler-bug

所以我写了一个讨厌的 lambda 到 satisfy a "shortest amount of code necessary to achieve this" question :

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 上,这会输出所需的内容:

4.2 9.1 2.3 0.6 6.4 3.6 1.4 7.5

但是在 all the other compilers I've tried我得到:

4.2 2.3 0.6 1.2 0.3 1.4 2.5 7.5

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

最佳答案

您依赖于这样一个事实,即您传递给算法的确切闭包是用作谓词的闭包,但标准允许复制它:

[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 开始:

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))));

Live demo

关于c++ - Lambda 适用于最新的 Visual Studio,但在其他地方不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41103743/

相关文章:

c++ - 检索 C++ 程序/文件中使用的指针变量列表

c++ - 结构可以具有类型 `Card*` 吗? (书中的例子)

c++ - 从 Visual Studio 2017 运行 MPI 应用程序,每个进程在不同的 cmd 窗口中

c++ - 使用具有两个动态数组的 Visual Studio 调试器可视化工具提供帮助

node.js - Visual Studio 2015 社区版,打开文件夹丢失

C++ 错误 : was not declared in this scope with private after public

c++ - 是否有任何编译器忽略有关默认内联函数的 C++ 标准?

asp.net - VS2012 中的 Entity Framework 问题 - 重命名属性不粘

c# - Visual Studio 上的 "The File Exist"错误

c# - Visual Studio 2015 中的隐藏/折叠属性