在插入容器之前转换 OutputIterator
Transforming an OutputIterator before inserting into a container
我有一个函数定义如下:
template <class Iter> Iter generate(Iter);
其中 Iter 的行为应该像 OutputIterator,返回的迭代器是生成的最后一个元素之后的一个元素(类似于 std::transform
的第三个参数)
我想调用此函数,对生成的每个项目应用谓词,然后将剩余的元素转换为不同的类型。我知道我可以这样做:
std::vector<some_type> generated_raw;
generate(std::back_inserter(generated_raw));
generated_raw.erase(std::remove_if(generated_raw.begin(), generated_raw.end(), predicate));
std::vector<other_type> generated;
std::transform(generated_raw.begin(), generated_raw.end(), std::back_inserter(generated), transform);
其中 predicate 和 transform 都是函数。
然而,这是低效的,因为它涉及一个中间容器,其中存储了每个生成的元素——即使是那些稍后将被 erase/remove_if 调用拒绝的元素。有更好的方法吗?
像这样应该可以解决问题:
template<class Iter, class Pred>
struct PredicatedIter {
Iter it;
Pred pr;
PredicatedIter& operator=(const typename Iter::Container::value_type &v) {
if(pr(v)) {
it = v;
}
return *this;
}
PredicatedIter& operator=(typename Iter::Container::value_type &&v) {
if(pr(v)) {
it = std::move(v);
}
return *this;
}
// no-ops as in back_insert_iterator
PredicatedIter& operator++() {
return *this;
}
PredicatedIter& operator++(int) {
return *this;
}
PredicatedIter& operator*() {
return *this;
}
};
PS:我做了类似的事情 and reworked my answer here。
我有一个函数定义如下:
template <class Iter> Iter generate(Iter);
其中 Iter 的行为应该像 OutputIterator,返回的迭代器是生成的最后一个元素之后的一个元素(类似于 std::transform
的第三个参数)
我想调用此函数,对生成的每个项目应用谓词,然后将剩余的元素转换为不同的类型。我知道我可以这样做:
std::vector<some_type> generated_raw;
generate(std::back_inserter(generated_raw));
generated_raw.erase(std::remove_if(generated_raw.begin(), generated_raw.end(), predicate));
std::vector<other_type> generated;
std::transform(generated_raw.begin(), generated_raw.end(), std::back_inserter(generated), transform);
其中 predicate 和 transform 都是函数。
然而,这是低效的,因为它涉及一个中间容器,其中存储了每个生成的元素——即使是那些稍后将被 erase/remove_if 调用拒绝的元素。有更好的方法吗?
像这样应该可以解决问题:
template<class Iter, class Pred>
struct PredicatedIter {
Iter it;
Pred pr;
PredicatedIter& operator=(const typename Iter::Container::value_type &v) {
if(pr(v)) {
it = v;
}
return *this;
}
PredicatedIter& operator=(typename Iter::Container::value_type &&v) {
if(pr(v)) {
it = std::move(v);
}
return *this;
}
// no-ops as in back_insert_iterator
PredicatedIter& operator++() {
return *this;
}
PredicatedIter& operator++(int) {
return *this;
}
PredicatedIter& operator*() {
return *this;
}
};
PS:我做了类似的事情