简体   繁体   English

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

[英]Container begin / end / cbegin / cend semantics, iterator / const_iterator compatibility

I've been working on a custom ReversibleContainer , and I thought I was on the right track, but I've hit a snag in testing while going through the semantics of the Container named requirements which makes me think I've fundamentally mis-implemented this.我一直在研究自定义ReversibleContainer ,并且我认为我走在正确的轨道上,但是我在测试Container命名要求的语义时遇到了障碍,这让我认为我从根本上错误地实现了这个。 I'm working with C++17.我正在使用 C++17。

In particular, my current implementation is formed somewhat like this (pardon errors, I'm condensing it to an example as I type here), where:特别是,我当前的实现有点像这样(请原谅错误,我在此处键入时将其浓缩为一个示例),其中:

  • Item is the type the container holds Item是容器持有的类型
  • element is the type iterators dereference to (it's convertible to Item ) element是类型迭代器取消引用(它可以转换为Item
  • struct is used for overall brevity in this snippet struct在此代码段中用于整体简洁
  • only the types and members that I think are relevant are included只包含我认为相关的类型和成员
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;

};

Now, I'm looking at the operational semantics of begin , end , cbegin and cend (where a is a my_container , and C is its type):现在,我正在查看beginendcbegincend的操作语义(其中amy_containerC是它的类型):

expression表达 return type返回类型 semantics语义
a.begin() (const_)iterator (const_)迭代器 iterator to the first element of a指向 a 的第一个元素a迭代器
a.end() (const_)iterator (const_)迭代器 iterator to one past the last element of a指向a的最后一个元素的迭代器
a.cbegin() const_iterator const_iterator const_cast<const C&>(a).begin()
a.cend() const_iterator const_iterator const_cast<const C&>(a).end()

And the problem with my current implementation is that this expression, derived from the cbegin (and likewise cend ), is invalid:我当前实现的问题是,这个从cbegin (以及同样cend )派生的表达式是无效的:

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

Because my iterator and const_iterator types are incompatible due to the const being wrapped up in the iterator type via the template parameters to iterator_ , and also because my begin() is not const .因为我的iteratorconst_iterator类型不兼容,因为const通过 iterator_ 的模板参数包装在iterator_器类型中,而且我的begin()不是const And now I'm getting that sinking feeling that I have a fundamental flaw in my implementation.现在我有一种下沉的感觉,我的实施存在根本缺陷。

The second problem with my current implementation is that the requirements list the return type of begin and end as "(const_)iterator", and I am only just noticing the "(const_)" now.我当前实现的第二个问题是要求将beginend的返回类型列为“(const_)iterator”,而我现在只注意到“(const_)”。 However, my begin and end do not return a const_iterator .但是,我的beginend不返回const_iterator

My conclusion, then, is that my implementation does not meet the operational semantics requirements of Container , and is therefore invalid in its current form.因此,我的结论是,我的实现不符合Container的操作语义要求,因此在当前形式下是无效的。 And now I'm sad.现在我很难过。 :( :(

So, I'm confused about:所以,我很困惑:

  • General compatibility requirements of iterator and const_iterator . iteratorconst_iterator的一般兼容性要求。
  • The cv-qualifiers on the declaration of begin() and end() . begin()end()声明中的 cv 限定符。

And my questions are:我的问题是:

  1. Am I correct in my conclusion that my container currently fails to meet the requirements of Container wrt.我的结论是否正确,即我的容器目前无法满足Container wrt 的要求。 begin , end , cbegin , and cend ? beginendcbegincend
  2. Do the iterator and const_iterator types need to be equality comparable with each other? iteratorconst_iterator类型是否需要相互可比?
  3. Does const_iterator need to be copy constructible and assignable from an iterator ? const_iterator是否需要从iterator中复制构造和赋值?
  4. Do begin() and end() have to be declared as const ? begin()end()是否必须声明为const
  5. Did I make a mistake in wrapping up the const in iterator_::value_type ?我在iterator_::value_type中包装const时犯了一个错误吗?
  6. What does "(const_)iterator" mean for the return type of begin and end ? "(const_)iterator" 对于beginend的返回类型意味着什么?

I realize that looks like a lot of questions but they all sort of boil down to the single question of what the requirements for interoperability between iterator and const_iterator are.我意识到这看起来像很多问题,但它们都归结为一个问题,即iteratorconst_iterator之间的互操作性要求是什么。 I hope this post makes sense.我希望这篇文章有意义。

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

And yes, const_iterator it = iterator;是的, const_iterator it = iterator; should work (but not the other way around), as should == (I am not certain the first is mandated, but you should still do it).应该工作(但不是相反),应该== (我不确定第一个是强制性的,但你仍然应该这样做)。

Also consider writing SCARY iterators, where the iterator is not a subtype of the container.还可以考虑编写 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 );
};

This is an example of a == that works between types.这是在类型之间工作的==示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM