我有一个包含和管理一系列对象的类。为了避免在允许迭代这些对象的同时泄漏这些对象的方式,我决定使用boost::any_iterator
来使用类型擦除。
using my_erased_type_iterator = boost::range_detail::any_iterator<
MyClass,
boost::bidirectional_traversal_tag,
MyClass&,
std::ptrdiff_t>;
我在Begin()
中定义了一个函数End()
和MyClass
,它只是将容器的begin()
和end()
函数作为my_erased_type_iterator
返回。它完全按照我的意愿工作,MyClass
之外的任何人都知道我使用向量来存储对象,除了我在Myclass
中公开的函数之外,他们还可以访问容器接口
现在,由于多种原因,我需要反向迭代对象。我还需要知道反向迭代器之后的下一个元素(类似于在普通迭代器上调用std::next()
,这对于反向迭代器来说已经不是那么简单了)我可能还需要调用像erase()
这样的函数在反向迭代器上。
所以对于我的问题:是否有一种优雅的方式来使用类型擦除和反向迭代器(以及正向和反向的const版本)?我应该使用正向类型擦除迭代器并反向迭代吗?我突然意识到,我可能会以错误的方式解决这个问题,因此我愿意接受任何建议或在必要时澄清我的问题。
答案 0 :(得分:1)
请注意any_iterator
是一个实现细节。
我将首先回答您的直接问题,然后按照Boost Range公共API的预期显示any_range<>
方法。
make_reverse_iterator
您只需使用
中的make_reverse_iterator
设施即可
<强> Live On Coliru 强>
#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
reversed
范围适配器:或者,您可以使用全范围风格并使用any_range<>
:
<强> Live On Coliru 强>
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 << " ";
}
}
答案 1 :(得分:1)
简单地反转类型擦除迭代器。
这会暴露.base()
,这意味着擦除几乎与删除已删除类型的擦除一样容易。
另外,您的设计具有(根据我的经验)边际收益的性能成本。底层容器的invalidadion规则的itera仍然适用,因此您的类的用户无论如何都必须知道底层容器是什么! (或者,他们也可以这么了解)。对容器进行Swappimng将无法提供足够类似的行为,因此尽管您试图隐藏它,但是您的容器仍被锁定。