Lambda 适用于最新的 Visual Studio,但在其他地方不起作用
Lambda Works on Latest Visual Studio, but Doesn't Work Elsewhere
所以我写了一个讨厌的 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 上输出所需的:
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))));
所以我写了一个讨厌的 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 上输出所需的:
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))));