使用虚拟派生方法返回不同的迭代器

时间:2016-03-08 11:23:35

标签: c++ oop iterator

假设我有一个虚拟基类Base,其部分行为类似于容器,具有两个派生类VectorLikeRangeLike。 我希望实现以下内容:

class VectorLike : public Base {
    std::vector<int> data;
public:
    virtual std::vector<int>::const_iterator cbegin() { return data.cbegin() }
    virtual std::vector<int>::const_iterator cend() { return data.cend() }
}

class RangeLike : public Base {
    int min, max;
    class const_iterator {
        int x;
    public:
        int operator++() { return ++x }
        bool operator==( const_iterator rhs ) { return x == rhs.x }
        const_iterator( int y ) { x = y }
    }
public:
    virtual const_iterator cbegin() { return const_iterator( min ); }
    virtual const_iterator cend() { return const_iterator( max ); }
}

此代码无法编译,因为std::vector<int>::const_iteratorRangeLike::const_iterator不相同或covariant。 为了实现第二个,我需要一个迭代器基类,std::vector<int>::const_iteratorRangeLike::const_iterator都将从中派生出来。但是仍然cbegin()cend()必须返回指向迭代器的指针,这将造成更大的混乱。

我的问题是,是否有可能实现类似上述代码的内容,如果是这样的话?

1 个答案:

答案 0 :(得分:4)

这是一个多态const int迭代器的实现。您可以使用std::iterator_traits<Iter>::value_type解析为int的任何迭代器类型(包括指针)来构造它。

std::vector<int>your_range_type<int>都应该是这种情况。

这应该让你开始。

#include <iostream>
#include <vector>
#include <array>
#include <memory>
#include <algorithm>

struct poly_const_iterator
{
    using value_type = int;

    struct concept {
        virtual void next(int n) = 0;
        virtual const value_type& deref() const = 0;
        virtual bool equal(const void* other) const = 0;
        virtual std::unique_ptr<concept> clone() const = 0;
        virtual const std::type_info& type() const = 0;
        virtual const void* address() const = 0;
        virtual ~concept() = default;
    };

    template<class Iter>
    struct model : concept
    {
        model(Iter iter) : _iter(iter) {}

        void next(int n) override { _iter = std::next(_iter, n); }
        const value_type& deref() const override { return *_iter; }
        bool equal(const void* rp) const override { return _iter == static_cast<const model*>(rp)->_iter; }
        std::unique_ptr<concept> clone() const override { return std::make_unique<model>(*this); }
        const std::type_info& type() const override { return typeid(_iter); }
        const void* address() const override { return this; }


        Iter _iter;
    };

    std::unique_ptr<concept> _impl;

public:
    // interface

    // todo: constrain Iter to be something that iterates value_type
    template<class Iter>
    poly_const_iterator(Iter iter) : _impl(std::make_unique<model<Iter>>(iter)) {};

    poly_const_iterator(const poly_const_iterator& r) : _impl(r._impl->clone()) {};

    const value_type& operator*() const {
        return _impl->deref();
    }

    poly_const_iterator& operator++() {
        _impl->next(1);
        return *this;
    }

    bool operator==(const poly_const_iterator& r) const {
        return _impl->type() == r._impl->type()
        and _impl->equal(r._impl->address());
    }

    bool operator != (const poly_const_iterator& r) const {
        return not(*this == r);
    }
};

void emit(poly_const_iterator from, poly_const_iterator to)
{
    std::copy(from, to, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
}

int main()
{
    std::vector<int> v = { 1, 2, 3, 4, 5 };
    std::array<int, 5> a = { 6, 7,8, 9, 0 };

    emit(std::begin(v), std::end(v));
    emit(std::begin(a), std::end(a));


    return 0;
}

预期结果:

1, 2, 3, 4, 5,
6, 7, 8, 9, 0,