容器 begin / end / cbegin / cend 语义,迭代器 / const_iterator 兼容性
Container begin / end / cbegin / cend semantics, iterator / const_iterator compatibility
我一直在研究自定义 ReversibleContainer,我认为我走在正确的轨道上,但我在测试语义时遇到了障碍Container named requirements 这让我觉得我从根本上错误地实现了这一点。我正在使用 C++17。
特别是,我当前的实现有点像这样(请原谅错误,我在此处键入时将其浓缩为一个示例),其中:
Item
是容器持有的类型
element
是迭代器取消引用的类型(它可以转换为 Item
)
struct
用于此代码段中的整体简洁性
- 只包含我认为相关的类型和成员
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;
};
现在,我正在查看 begin
、end
、cbegin
和 cend
的操作语义(其中 a
是 my_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()
因为我的 iterator
和 const_iterator
类型不兼容,因为 const
通过 iterator_
的模板参数包装在迭代器类型中,还因为我的 begin()
不是 const
。现在,我感到自己在实施过程中存在根本性缺陷。
我当前实现的第二个问题是要求将 begin
和 end
的 return 类型列为“(const_)iterator”,我只是注意到现在的“(const_)”。但是,我的 begin
和 end
没有 return const_iterator
.
那么,我的结论是,我的实现不符合 Container 的操作语义要求,因此在其当前形式下是无效的。现在我很难过。 :(
所以,我很困惑:
iterator
和 const_iterator
的一般兼容性要求。
begin()
和 end()
. 声明中的 cv 限定符
我的问题是:
- 我的结论是否正确,即我的容器目前无法满足 Container wrt 的要求。
begin
、end
、cbegin
和 cend
?
iterator
和 const_iterator
类型之间是否需要相等可比?
const_iterator
是否需要从 iterator
复制构造和分配?
- 是否必须将
begin()
和 end()
声明为 const
?
- 我在
iterator_::value_type
中结束 const
是不是搞错了?
- “(const_)iterator”对于
begin
和 end
的 return 类型意味着什么?
我意识到这看起来有很多问题,但它们都归结为一个问题,即 iterator
和 const_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 );
};
这是在类型之间工作的 ==
示例。
我一直在研究自定义 ReversibleContainer,我认为我走在正确的轨道上,但我在测试语义时遇到了障碍Container named requirements 这让我觉得我从根本上错误地实现了这一点。我正在使用 C++17。
特别是,我当前的实现有点像这样(请原谅错误,我在此处键入时将其浓缩为一个示例),其中:
Item
是容器持有的类型element
是迭代器取消引用的类型(它可以转换为Item
)struct
用于此代码段中的整体简洁性- 只包含我认为相关的类型和成员
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;
};
现在,我正在查看 begin
、end
、cbegin
和 cend
的操作语义(其中 a
是 my_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()
因为我的 iterator
和 const_iterator
类型不兼容,因为 const
通过 iterator_
的模板参数包装在迭代器类型中,还因为我的 begin()
不是 const
。现在,我感到自己在实施过程中存在根本性缺陷。
我当前实现的第二个问题是要求将 begin
和 end
的 return 类型列为“(const_)iterator”,我只是注意到现在的“(const_)”。但是,我的 begin
和 end
没有 return const_iterator
.
那么,我的结论是,我的实现不符合 Container 的操作语义要求,因此在其当前形式下是无效的。现在我很难过。 :(
所以,我很困惑:
iterator
和const_iterator
的一般兼容性要求。begin()
和end()
. 声明中的 cv 限定符
我的问题是:
- 我的结论是否正确,即我的容器目前无法满足 Container wrt 的要求。
begin
、end
、cbegin
和cend
? iterator
和const_iterator
类型之间是否需要相等可比?const_iterator
是否需要从iterator
复制构造和分配?- 是否必须将
begin()
和end()
声明为const
? - 我在
iterator_::value_type
中结束const
是不是搞错了? - “(const_)iterator”对于
begin
和end
的 return 类型意味着什么?
我意识到这看起来有很多问题,但它们都归结为一个问题,即 iterator
和 const_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 );
};
这是在类型之间工作的 ==
示例。