容器 begin / end / cbegin / cend 语义,迭代器 / const_iterator 兼容性

Container begin / end / cbegin / cend semantics, iterator / const_iterator compatibility

我一直在研究自定义 ReversibleContainer,我认为我走在正确的轨道上,但我在测试语义时遇到了障碍Container named requirements 这让我觉得我从根本上错误地实现了这一点。我正在使用 C++17。

特别是,我当前的实现有点像这样(请原谅错误,我在此处键入时将其浓缩为一个示例),其中:

struct my_container {

    using value_type = Item;
    using reference = value_type &;
    using const_reference = const value_type &;
    using size_type = std::vector<Item>::size_type;
    using difference_type = std::vector<Item>::difference_type;

    struct element { 
        // ... 
    };

    // V is value type, D is part of forward/reverse iterator control
    template <typename V, int D> struct iterator_ {

        using iterator_category = std::random_access_iterator_tag;
        using value_type = V;
        using reference = V &;
        using pointer = V *;
        using difference_type = my_container::difference_type;

        iterator_ (); // custom
        iterator_ (const iterator_<V,D> &) = default;
        iterator_ (iterator_<V,D> &&) = default;
        ~iterator_ () = default;

        iterator_<V,D> & operator = (const iterator_<V,D> &) = default;
        iterator_<V,D> & operator = (iterator_<V,D> &&) = default;

        bool operator == (const iterator_<V,D> &) const;

        // ...

    };

    using iterator = iterator_<element, 1>;
    using const_iterator = iterator_<const element, 1>;
    using reverse_iterator = iterator_<element, -1>;
    using const_reverse_iterator = iterator_<const element, -1>;

    iterator begin ();
    iterator end ();
    const_iterator cbegin () const;
    const_iterator cend () const;

    reverse_iterator rbegin ();
    reverse_iterator rend ();
    const_reverse_iterator crbegin () const;
    const_reverse_iterator crend () const;

};

现在,我正在查看 beginendcbegincend 的操作语义(其中 amy_container, C 是它的类型):

expression return type semantics
a.begin() (const_)iterator iterator to the first element of a
a.end() (const_)iterator iterator to one past the last element of a
a.cbegin() const_iterator const_cast<const C&>(a).begin()
a.cend() const_iterator const_cast<const C&>(a).end()

我当前实现的问题是这个从 cbegin(以及 cend)派生的表达式是无效的:

a.cbegin() == const_cast<const my_container&>(a).begin()

因为我的 iteratorconst_iterator 类型不兼容,因为 const 通过 iterator_ 的模板参数包装在迭代器类型中,还因为我的 begin() 不是 const。现在,我感到自己在实施过程中存在根本性缺陷。

我当前实现的第二个问题是要求将 beginend 的 return 类型列为“(const_)iterator”,我只是注意到现在的“(const_)”。但是,我的 beginend 没有 return const_iterator.

那么,我的结论是,我的实现不符合 Container 的操作语义要求,因此在其当前形式下是无效的。现在我很难过。 :(

所以,我很困惑:

我的问题是:

  1. 我的结论是否正确,即我的容器目前无法满足 Container wrt 的要求。 beginendcbegincend?
  2. iteratorconst_iterator 类型之间是否需要相等可比?
  3. const_iterator 是否需要从 iterator 复制构造和分配?
  4. 是否必须将 begin()end() 声明为 const
  5. 我在 iterator_::value_type 中结束 const 是不是搞错了?
  6. “(const_)iterator”对于 beginend 的 return 类型意味着什么?

我意识到这看起来有很多问题,但它们都归结为一个问题,即 iteratorconst_iterator 之间的互操作性要求是什么。我希望这个 post 有意义。

iterator begin ();
iterator end ();
const_iterator begin () const;
const_iterator end () const;
const_iterator cbegin () const;
const_iterator cend () const;

是的,const_iterator it = iterator; 应该有效(但反之则不行),== 也应该有效(我不确定第一个是强制性的,但你仍然应该这样做)。

还可以考虑编写 SCARY 迭代器,其中迭代器不是容器的子类型。

template<class T>
struct foo {
   template<class U, std::enable_if_t<std::is_same_v<std::remove_cv_t<U>, std::remove_cv_t<T>>,bool> =true>
   friend bool operator==( foo const& lhs, foo<U> const& rhs );
};

这是在类型之间工作的 == 示例。