Nob*_*ody 24 c++ algorithm foreach
是否有一个标准的实现for_each,它调用元素和范围中的下一个元素?
例如,取范围{0, 1, 2, 3, 4, 5},我想f用每个元素及其后继者调用一个函数:{f(0, 1), f(1, 2), f(2, 3), f(3, 4), f(4, 5)}
注意最后一个元素是如何被省略的,因为它没有后继元素.
如果对n个后继者进行泛化,那么它也会很好.
到目前为止,我总是用迭代器的手写循环来解决这个问题.但是,我想更多地遵循C++ 11范围的基础或std::for_each避免锅炉板代码.
// today: handwritten loop
for(Range::iterator current = range.begin(); current != range.end(); ++current)
f(*current, *std::next(current));
// near future: wrapped version
for_each_pair(range.begin(), range.end(), f);
// slightly further future: generalized version
for_each_tuple<n>(range.begin(), range.end(), f);
Run Code Online (Sandbox Code Playgroud)
可以改进函数的名称.对我来说for_each_pair/ tuple听起来应该返回范围大小为n的所有子集(这本身就是我想要解决的另一个问题).所以我想对更好的名字提出一些建议:
for_each_adjacent<n>
Run Code Online (Sandbox Code Playgroud)
您实际上可以滥用std::unique或std::adjacent_find为此:在迭代器范围内的每个连续对中调用谓词,并且只要谓词始终返回 false,它就不会修改任何内容或提前返回。
不考虑那个特定的 hack,我会将它实现为迭代器适配器,而不是算法。也就是说,我将实现一个consecutive_tuple_iterator<N>将返回 N 个连续项目的所有元组。然后你可以将它用于诸如count_ifand之类的事情includes,而不仅仅是for_each. (不过,它不适用于大多数修改算法。)
最简单的事情是将其编写为通用算法,然后多次应用它。
template< typename FwdIter, typename Func >
Func for_each_pair( FwdIter iterStart, FwdIter iterEnd, Func func )
{
if( iterStart == iterEnd )
return func;
FwdIter iterNext = iterStart;
++iterNext;
for( ; iterNext != iterEnd; ++iterStart, ++iterNext )
{
func( *iterStart, *iterNext );
}
return func;
}
Run Code Online (Sandbox Code Playgroud)
当我被问到为什么它返回 func (而不是 void)时,这是典型的 for_each 因为以下事实:
func 可能会“积累”某种状态,但积累这种状态的是我们在该算法中制作的副本,而不是用户的原始对象。因此,我们将它们传回修改后的“func”对象。
使用 C++ 11 和迭代器的新迭代器辅助函数std::next和std::prev,标准算法std::transform的第二个变体的第二个变体可用于迭代相邻元素。
下面是一个从列表生成相邻对列表的示例:
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::vector<std::pair<int,int>> num_pairs;
if (!nums.empty()) {
std::transform(
std::begin(nums), std::prev(std::end(nums)),
std::next(std::begin(nums)),
std::back_inserter(num_pairs),
std::make_pair<
decltype(nums)::const_reference,
decltype(nums)::const_reference
>
);
}
Run Code Online (Sandbox Code Playgroud)