使用 reverse_iterator 类型擦除
Use reverse_iterator with type erasure
我有一个 class,它包含并管理一系列对象。为了避免泄漏这些对象的存储方式,同时允许迭代它们,我决定使用类型擦除 boost::any_iterator
.
using my_erased_type_iterator = boost::range_detail::any_iterator<
MyClass,
boost::bidirectional_traversal_tag,
MyClass&,
std::ptrdiff_t>;
我在MyClass
中定义了一个函数Begin()
和End()
,它只是returns容器的begin()
和end()
函数作为一个my_erased_type_iterator
。它完全按照我的意愿工作,MyClass
之外的任何人都不知道我正在使用向量来存储对象,除了我在 Myclass
中公开的函数之外,他们也无法访问容器界面。
现在,出于多种原因,我需要对对象进行反向迭代。我还需要知道反向迭代器之后的下一个元素(类似于在普通迭代器上调用 std::next()
,这对于反向迭代器来说已经不是那么简单了),我可能还需要调用 erase()
之类的函数在那个反向迭代器上。
所以对于我的问题:是否有一种优雅的方式来使用类型擦除和反向迭代器(以及正向和反向的 const 版本)?我应该使用前向类型擦除迭代器并向后迭代吗?我突然想到我可能以错误的方式解决了这个问题,所以如果需要,我愿意接受任何建议或澄清我的问题。
请注意,any_iterator
是一个实现细节。
我会先回答你的直接问题,然后根据 Boost Range public API 的意图展示 any_range<>
的方法。
1。 make_reverse_iterator
您可以简单地使用
中的 make_reverse_iterator
工具
- 标准 c++14 http://en.cppreference.com/w/cpp/iterator/make_reverse_iterator
- 提升http://www.boost.org/doc/libs/1_60_0/libs/iterator/doc/reverse_iterator.html
#include <boost/range.hpp>
#include <boost/range/any_range.hpp>
struct MyClass {
int i;
};
using my_erased_type_iterator = boost::range_detail::any_iterator<
MyClass,
boost::bidirectional_traversal_tag,
MyClass&,
std::ptrdiff_t>;
#include <iostream>
#include <vector>
int main() {
using namespace boost;
std::vector<MyClass> const v { {1}, {2}, {3}, {4} };
for (auto& mc : make_iterator_range(
make_reverse_iterator(v.end()),
make_reverse_iterator(v.begin())))
{
std::cout << mc.i << " ";
}
}
版画
4 3 2 1
2。 reversed
范围适配器:
或者,您可以完整 range-style 并使用 any_range<>
:
int main() {
std::vector<MyClass> const v { {1}, {2}, {3}, {4} };
boost::any_range_type_generator<decltype(v)>::type x = reverse(v);
for (my_erased_type_const_iterator f = boost::begin(x), l = boost::end(x); f!=l; ++f) {
std::cout << f->i << " ";
}
}
简单地反转擦除迭代器的类型。
这暴露了.base()
,这意味着擦除几乎和擦除前面擦除的类型一样容易。
顺便说一句,您的设计具有(以我的经验)边际收益的性能成本。底层容器的 iterafor invalidadion 规则仍然适用,因此 class 的用户无论如何都必须知道底层容器是什么! (或者,他们可能也知道得太多了)。换出容器不会提供足够相似的行为,因此尽管您付出了合理的代价来隐藏它,但您的容器仍被锁定。
我有一个 class,它包含并管理一系列对象。为了避免泄漏这些对象的存储方式,同时允许迭代它们,我决定使用类型擦除 boost::any_iterator
.
using my_erased_type_iterator = boost::range_detail::any_iterator<
MyClass,
boost::bidirectional_traversal_tag,
MyClass&,
std::ptrdiff_t>;
我在MyClass
中定义了一个函数Begin()
和End()
,它只是returns容器的begin()
和end()
函数作为一个my_erased_type_iterator
。它完全按照我的意愿工作,MyClass
之外的任何人都不知道我正在使用向量来存储对象,除了我在 Myclass
中公开的函数之外,他们也无法访问容器界面。
现在,出于多种原因,我需要对对象进行反向迭代。我还需要知道反向迭代器之后的下一个元素(类似于在普通迭代器上调用 std::next()
,这对于反向迭代器来说已经不是那么简单了),我可能还需要调用 erase()
之类的函数在那个反向迭代器上。
所以对于我的问题:是否有一种优雅的方式来使用类型擦除和反向迭代器(以及正向和反向的 const 版本)?我应该使用前向类型擦除迭代器并向后迭代吗?我突然想到我可能以错误的方式解决了这个问题,所以如果需要,我愿意接受任何建议或澄清我的问题。
请注意,any_iterator
是一个实现细节。
我会先回答你的直接问题,然后根据 Boost Range public API 的意图展示 any_range<>
的方法。
1。 make_reverse_iterator
您可以简单地使用
中的make_reverse_iterator
工具
- 标准 c++14 http://en.cppreference.com/w/cpp/iterator/make_reverse_iterator
- 提升http://www.boost.org/doc/libs/1_60_0/libs/iterator/doc/reverse_iterator.html
#include <boost/range.hpp>
#include <boost/range/any_range.hpp>
struct MyClass {
int i;
};
using my_erased_type_iterator = boost::range_detail::any_iterator<
MyClass,
boost::bidirectional_traversal_tag,
MyClass&,
std::ptrdiff_t>;
#include <iostream>
#include <vector>
int main() {
using namespace boost;
std::vector<MyClass> const v { {1}, {2}, {3}, {4} };
for (auto& mc : make_iterator_range(
make_reverse_iterator(v.end()),
make_reverse_iterator(v.begin())))
{
std::cout << mc.i << " ";
}
}
版画
4 3 2 1
2。 reversed
范围适配器:
或者,您可以完整 range-style 并使用 any_range<>
:
int main() {
std::vector<MyClass> const v { {1}, {2}, {3}, {4} };
boost::any_range_type_generator<decltype(v)>::type x = reverse(v);
for (my_erased_type_const_iterator f = boost::begin(x), l = boost::end(x); f!=l; ++f) {
std::cout << f->i << " ";
}
}
简单地反转擦除迭代器的类型。
这暴露了.base()
,这意味着擦除几乎和擦除前面擦除的类型一样容易。
顺便说一句,您的设计具有(以我的经验)边际收益的性能成本。底层容器的 iterafor invalidadion 规则仍然适用,因此 class 的用户无论如何都必须知道底层容器是什么! (或者,他们可能也知道得太多了)。换出容器不会提供足够相似的行为,因此尽管您付出了合理的代价来隐藏它,但您的容器仍被锁定。