为什么总是在std :: for_each中指定迭代器?

Jon*_*ing 2 c++ design-patterns idioms

据我所知,迭代STL集合的习惯看起来像这样:

int a[] = { 1,2,3 };
std::vector<int> v(a, a+3);

std::for_each(a.begin(), a.end(), some_function);
Run Code Online (Sandbox Code Playgroud)

如果我只想处理集合的某个范围,或者做一些更有创意的事情,那么指定第一个和最后一个迭代器是很有用的,但大多数时候,我怀疑我们实际上是想要使用整个集合.所以,我想知道为什么人们在那种情况下烦恼指定迭代器(因为它们总是相同的),并且不只是沿着这些方向使用便利函数:

namespace easy
{
  template <class T, class F>
  F for_each(T& collection, F function)
  {
    std::for_each(collection.begin(), collection.end(), function);
    return function;
  }
}
Run Code Online (Sandbox Code Playgroud)

(当然,这是可能的,这做事的惯用方式,我从来没有注意到!我是新的C++,虽然).

Pot*_*ter 5

我绝对是STL的ga-ga.但我记不起实际上曾经使用过for_each.

这个成语是

for ( container::iterator it = coll.begin(); it != coll.end(); ++ it )
Run Code Online (Sandbox Code Playgroud)

C++ 11引入了糖来减少这种情况

for ( auto elem : coll )
Run Code Online (Sandbox Code Playgroud)

这类似于您的便利功能,但使用免费(非成员)std::beginstd::end功能,允许与非标准容器的对象兼容.

另外,查一下(我还没有玩这个,因为它还没有在GCC中),看起来它限制了程序员访问范围的元素,而不是迭代器.


至于使用容器来指代其整个范围,最好保持允许子范围的灵活性.另一种解决方案是为一迭代器引入一个习惯用法{ begin, end }.有一些争论,我期望C++ 11包含这样的功能

begin( make_pair( begin_, end_ ) ) // == begin_,
end( make_pair( begin_, end_ ) ) // == end_,
for ( auto elem : make_pair( begin_, end_ ) ) // iterates over [ begin_, end )
Run Code Online (Sandbox Code Playgroud)

但在阅读标准后,它似乎pair缺乏此功能.

pair但是,您可以创建自己的类型,以获得灵活的基于范围的for:

template< typename iter >
struct range_type {
    iter first, last;

    // use friends because Standard specifies these should be found by ADL:
    friend iter begin( range_type const &r ) { return r.first; }
    friend iter end( range_type const &r ) { return r.last; }
};

template< typename iter >
range_type< iter > range( iter first, iter last )
    { return range_type< iter >{ first, last }; }

// usage:
for ( auto elem : range( begin_, end_ ) ) // iterates over [ begin_, end )
Run Code Online (Sandbox Code Playgroud)