我们有一些“可迭代的”数据集合,例如:std::vector<Foo> bar
。
我们希望处理来自Foo
的{{1}}元素,直到满足某些条件,此时我们“屈服”(想想Python)所有这些处理过的bar
的结果并等到下一个块请求解析的信息。
到目前为止,我们正在做的是:
Foo
有关更好地做到这一点的任何建议吗?
答案 0 :(得分:2)
正如我在评论中已经指出的那样,IMO是自定义迭代器的一个非常好的例子:
迭代器扫描你的范围,只要一些谓词成立,并且 当谓词对于某个元素不成立时,调用具有谓词所持有的子元素范围的函数(加上不满足谓词的元素)。那么函数调用的结果就是你取消引用迭代器时得到的值。
template<typename Fn, typename Predicate, typename Iterator>
struct collector {
using value_type = typename std::result_of<Fn(Iterator, Iterator)>::type;
using pointer = value_type const *;
using reference = value_type const &;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
value_type cache;
Fn fn;
Predicate predicate;
Iterator pos, from, stop;
collector(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e)
: fn(std::forward<Fn>(fn)),
predicate(std::forward<Predicate>(p)),
pos(std::forward<Iterator>(s)),
from(pos),
stop(std::forward<Iterator>(e))
{
next_range();
}
collector & operator++(void) {
next_range();
return *this;
}
reference operator*(void) const {
return cache;
}
void next_range(void) {
from = pos;
if (pos == stop) return;
for (; pos != stop; ++pos) {
if (not predicate(*pos)) {
++pos;
break;
}
}
cache = fn(from, pos);
}
collector end_of_range(void) const {
auto copy = collector{*this};
copy.pos = copy.stop;
copy.from = copy.stop;
return copy;
}
bool operator==(collector const & rhs) const {
return (from == rhs.from) and (pos == rhs.pos) and (stop == rhs.stop);
}
bool operator!=(collector const & rhs) const {
return (from != rhs.from) or (pos != rhs.pos) or (stop != rhs.stop);
}
};
template<typename Fn, typename Predicate, typename Iterator>
auto make_collector_range(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e) {
using I = typename std::decay<Iterator>::type;
using P = typename std::decay<Predicate>::type;
using F = typename std::decay<Fn>::type;
using C = collector<F,P,I>;
auto start = C{
std::forward<Fn>(fn), std::forward<Predicate>(p),
std::forward<Iterator>(s), std::forward<Iterator>(e)};
auto stop = start.end_of_range();
return make_pair(std::move(start), std::move(stop));
}
一个示例用法,计算到50之前的数字之和,但不是一步,而是每个15个数字的步骤:
int main(int, char**) {
vector<int> numbers = vector<int>(50);
generate(begin(numbers), end(numbers),
[i = 0] (void) mutable{
return ++i;
});
copy(begin(numbers), end(numbers), ostream_iterator<int>{cout, " "});
cout << endl;
auto collected = make_collector_range(
[](auto const & from, auto const & to) {
return accumulate(from, to, 0);
},
[](auto const & num) {
return not ((num % 3 == 0) and (num % 5 == 0));
},
begin(numbers), end(numbers));
copy(collected.first, collected.second, ostream_iterator<int>{cout, " "});
cout << endl;
bool passed = accumulate(collected.first, collected.second, 0) == (50*51)/2;
cout << "test " << (passed ? "passed" : "failed") << endl;
return 0;
}
(注意:此示例使用固定的“步长”,谓词和函数彼此无关且不保持状态,但迭代器不需要这样做。)
我希望代码的意图是明确的,如果不是,我可以尝试提供有关其工作的更详细的解释。