c++ - 从标准容器迭代器派生

标签 c++ stl iterator

我有一个包含 std::shared_ptr 私有(private)集合的类,例如:

class Foo
{
private:
     using Bars = std::vector<std::shared_ptr<Bar>>;
     Bars items_;
}

给定一个 Foo 的实例,我希望能够直接迭代 items_ 中的 Bar 对象——实际上隐藏了集合包含指针。我相信 Bars::const_iterator 唯一需要更改的是 operator*,是否可以从它派生并实现 operator* >?即

class Iterator : public Bars::const_iterator
{
public:
    Iterator(Bars::const_iterator it) : Bars::const_iterator {it} {}

    const string& operator*() const
    {
        return *Bars::const_iterator::operator*();
    }
};

然后为Foo提供beginend方法:

Foo::Iterator Foo::begin() const noexcept { return Iterator {std::cbegin(items_)}; }
Foo::Iterator Foo::end()   const noexcept { return Iterator {std::cend(items_)}; }

最佳答案

为了灵 active ,您可以只编写一个适配器:

#include <type_traits>

template <typename Iterator>
class random_access_pointer_iterator
{
    // Types
    // =====

    public:
    typedef Iterator iterator_type;
    typedef std::random_access_iterator_tag iterator_category;
    using difference_type = typename iterator_type::difference_type;
    using pointer = decltype(&**std::declval<iterator_type>());
    using value_type = typename std::remove_pointer<pointer>::type;
    typedef value_type& reference;

    // Construction
    // ============

    public:
    explicit random_access_pointer_iterator(iterator_type iterator)
    :   m_iterator(iterator)
    {}

    // Element Access
    // ==============

    public:
    const iterator_type& base() const { return m_iterator; }
    iterator_type& base() { return m_iterator; }
    operator iterator_type () const { return m_iterator; }

    // Iterator
    // ========

    public:
    reference operator * () const { return **m_iterator; }
    pointer operator -> () const { return &(**m_iterator); }

    random_access_pointer_iterator& operator ++ () {
        ++m_iterator;
        return *this;
    }
    random_access_pointer_iterator operator ++ (int) {
        random_access_pointer_iterator tmp(*this);
        ++m_iterator;
        return tmp;

    }
    random_access_pointer_iterator& operator += (difference_type n) {
        m_iterator += n;
        return *this;
    }

    random_access_pointer_iterator& operator -- () {
        --m_iterator;
        return *this;
    }
    random_access_pointer_iterator operator -- (int) {
        random_access_pointer_iterator tmp(*this);
        --m_iterator;
        return tmp;
    }

    random_access_pointer_iterator& operator -= (difference_type n) {
        m_iterator -= n;
        return *this;
    }

    private:
    iterator_type m_iterator;
};

template <typename Iterator>
inline random_access_pointer_iterator<Iterator> operator + (
    random_access_pointer_iterator<Iterator> i,
    typename random_access_pointer_iterator<Iterator>::difference_type n) {
    return i += n;
}

template <typename Iterator>
inline random_access_pointer_iterator<Iterator> operator - (
    random_access_pointer_iterator<Iterator> i,
    typename random_access_pointer_iterator<Iterator>::difference_type n) {
    return i -= n;
}

template <typename Iterator>
inline typename random_access_pointer_iterator<Iterator>::difference_type
operator - (
    const random_access_pointer_iterator<Iterator>& a,
    const random_access_pointer_iterator<Iterator>& b) {
    return a.base() - b.base();
}

template <typename Iterator>
inline bool operator == (
    const random_access_pointer_iterator<Iterator>& a,
    const random_access_pointer_iterator<Iterator>& b) {
    return a.base() == b.base();
}

template <typename Iterator>
inline bool operator != (
    const random_access_pointer_iterator<Iterator>& a,
    const random_access_pointer_iterator<Iterator>& b) {
    return a.base() != b.base();
}

template <typename Iterator>
inline bool operator <  (
    const random_access_pointer_iterator<Iterator>& a,
    const random_access_pointer_iterator<Iterator>& b) {
    return a.base() <  b.base();
}

template <typename Iterator>
inline bool operator <= (
    const random_access_pointer_iterator<Iterator>& a,
    const random_access_pointer_iterator<Iterator>& b) {
    return a.base() <= b.base();
}

template <typename Iterator>
inline bool operator >  (
    const random_access_pointer_iterator<Iterator>& a,
    const random_access_pointer_iterator<Iterator>& b) {
    return a.base() >  b.base();
}

template <typename Iterator>
inline bool operator >= (
    const random_access_pointer_iterator<Iterator>& a,
    const random_access_pointer_iterator<Iterator>& b) {
    return a.base() >= b.base();
}


#include <cassert>
#include <memory>
#include <vector>

int main() {
    using vector = std::vector<std::shared_ptr<int>>;
    auto p = std::make_shared<int>(0);
    vector v = { p };

    using iterator = random_access_pointer_iterator<vector::iterator>;
    iterator a(v.begin());
    iterator b(v.end());

    assert(*a == 0);
    assert(a.operator -> () == &*p);
    ++a;
    assert(a == b);
    --a;
    assert(a != b);
    assert(a++ != b);
    assert(a-- == b);
    assert(a + 1 == b);
    assert(a == b - 1);
    assert(b - a == 1);
    assert(a <  b);
    assert(a <= b);
    assert(b >  a);
    assert(b >= a);
}

有了这个,您就可以使用任何随机访问迭代器(vector、deque、...)并使用任何指针类型(原始指针、shared_ptr、...)

注意:在您的情况下 - 当您从 vector 的迭代器派生时,您也必须调整类型定义。

注意:我不喜欢“random_access_pointer_iterator”,但我没有更好的想法。

关于c++ - 从标准容器迭代器派生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35206816/

相关文章:

c++ - 获取 map<string,vector<string>> 的键

c++ - 具有 2 种方法的 push_back 私有(private) vector ,一种不起作用

python - 使用步长 python 对列表的项目进行分组?

c++ - 如何遍历这样的 map ?如何修复 8 个可怕的 C2784 错误?

C++11 static_assert(以及其中使用的函数)

algorithm - LRU缓存算法的复杂度

c++ - 如果传递的指针为空,placement new 是否会调用构造函数?

c++ - std::map<UnicodeString, UnicodeString> 的 ofstream 输出产生地址而不是字符串

python - 获取非常大的 memmap 中满足条件的下一个元素的索引

c++ - 通过正则表达式崩溃删除 RTF 标签