使用带有类型擦除

时间:2016-01-26 22:43:42

标签: c++ boost iterator reverse-iterator boost-type-erasure

我有一个包含和管理一系列对象的类。为了避免在允许迭代这些对象的同时泄漏这些对象的方式,我决定使用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版本)?我应该使用正向类型擦除迭代器并反向迭代吗?我突然意识到,我可能会以错误的方式解决这个问题,因此我愿意接受任何建议或在必要时澄清我的问题。

2 个答案:

答案 0 :(得分:1)

请注意any_iterator是一个实现细节。

我将首先回答您的直接问题,然后按照Boost Range公共API的预期显示any_range<>方法。

1。 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 

2。 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将无法提供足够类似的行为,因此尽管您试图隐藏它,但是您的容器仍被锁定。