wrap iterators for enumerate的另一种方式:
必需的标题:
#include <algorithm>
#include <iterator>
#include <utility>
包装迭代器:
template<class Iter, class Offset=int>
struct EnumerateIterator : std::iterator<std::input_iterator_tag, void, void, void, void> {
Iter base;
Offset n;
EnumerateIterator(Iter base, Offset n = Offset()) : base (base), n (n) {}
EnumerateIterator& operator++() { ++base; ++n; return *this; }
EnumerateIterator operator++(int) { auto copy = *this; ++*this; return copy; }
friend bool operator==(EnumerateIterator const& a, EnumerateIterator const& b) {
return a.base == b.base;
}
friend bool operator!=(EnumerateIterator const& a, EnumerateIterator const& b) {
return !(a == b);
}
struct Pair {
Offset first;
typename std::iterator_traits<Iter>::reference second;
Pair(Offset n, Iter iter) : first (n), second(*iter) {}
Pair* operator->() { return this; }
};
Pair operator*() { return Pair(n, base); }
Pair operator->() { return Pair(n, base); }
};
枚举重载:
template<class Iter, class Func>
Func enumerate(Iter begin, Iter end, Func func) {
typedef EnumerateIterator<Iter> EI;
return std::for_each(EI(begin), EI(end), func);
}
template<class T, int N, class Func>
Func enumerate(T (&a)[N], Func func) {
return enumerate(a, a + N, func);
}
template<class C, class Func>
Func enumerate(C& c, Func func) {
using std::begin;
using std::end;
return enumerate(begin(c), end(c), func);
}
从 James 那里复制的测试:
#include <array>
#include <iostream>
struct print_pair {
template<class Pair>
void operator()(Pair const& p) {
std::cout << p.first << ": " << p.second << "\n";
}
};
int main() {
std::array<float, 5> data = {1, 3, 5, 7, 9};
enumerate(data, print_pair());
return 0;
}
我不在这里提供偏移量;尽管它在 EnumerateIterator 中已完全准备好从 0 以外的地方开始。剩下的选择是要制作偏移的类型以及是否为额外参数添加重载或使用默认值。 (没有理由偏移量必须是迭代器的差异类型,例如,如果您将其设为与日期相关的类型,每次迭代对应于第二天呢?)