c++ 如何正确地使用继承实现自定义迭代器

3wabscal  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(152)

为了练习和理解,我重新发明了STL vector。当然,我还必须实现一个迭代器系统。为了重用,我希望实现所有具有继承性的迭代器类别(例如:class random_access_iterator : public bidirectional_iterator<T, Container>)。
现在我遇到了一个大问题。考虑以下片段:

custom_vector<int>::iterator it_start = container.begin(), it_end = container.end();
custom_vector<int> other_container(it_start, --(--it_end));

因为递减操作符有类别双向迭代器,所以我也在那里实现了它。

template <class T, class Container>
class bidirectional_iterator : public forward_iterator<T, Container>
{
    // ...
    public:
        /* Decrement Operators */
        bidirectional_iterator &operator--() { /* code */ }
        bidirectional_iterator operator--(int) { /* code */ }
    // ...
}

考虑到这一点,下面的代码将无法工作,因为第一个参数将是random_access_iterator类型,第二个参数将是bidirectional_iterator类型。

custom_vector<int> other_container(it_start, --(--it_end));

由于构造函数具有两种不同的迭代器类型是没有意义的(而且STL Vector也没有这样的构造函数),所以我不会实现这样的构造函数,这会导致编译错误。

error: no matching constructor for initialization of 'custom_vector<int>'
        custom_vector<int> other_container(it_start, --(--it_end));
                           ^               ~~~~~~~~~~~~~~~~~~~~~~
candidate constructor not viable: no known conversion from 'custom_vector<int>::iterator' (aka 'random_access_iterator<int, custom_vector<int> >') to 'custom_vector<int>::size_type' (aka 'unsigned long') for 1st argument
                explicit custom_vector(size_type n, const value_type &val = value_type(), const allocator_type &alloc = allocator_type()) : _capacity(n), _alloc(alloc)
                         ^
note: candidate template ignored: deduced conflicting types for parameter 'InputIterator' ('random_access_iterator<int, custom_vector<int> >' vs. 'bidirectional_iterator<int, custom_vector<int> >')
                custom_vector(InputIterator first, InputIterator last, const allocator_type &alloc = allocator_type(),
                ^
note: candidate constructor not viable: allows at most single argument 'alloc', but 2 arguments were provided
                explicit custom_vector(const allocator_type &alloc = allocator_type()) : _capacity(), _alloc(alloc), _content() {}
                         ^
note: candidate constructor not viable: requires single argument 'x', but 2 arguments were provided
                custom_vector(const custom_vector &x) : _capacity(x.capacity()), _alloc(x.get_allocator()), _content()
                ^
1 error generated.

1.我的继承迭代器实现是正确的吗?坚持这个实现有意义吗?还是只为每个容器实现一个特定的迭代器更好?
1.有没有一种方法可以实现一个“迭代器转换器”,在需要的时候自动地把我的bidirectional_iterator转换成random_access_iterator?

zxlwwiss

zxlwwiss1#

我的继承迭代器实现正确吗?
不可以。C++的迭代器不使用继承,它使用concepts。如果一个类型提供了随机访问迭代器方法([]+-等),那么它就是std::random_access_iterator。这包括指针类型,它们不能从某个基类继承。
每个容器的迭代器都是特定于该容器的。不同类别的存在是因为一些操作不能(有效地)为那些容器实现。

o0lyfsai

o0lyfsai2#

我相信已经太晚了,但我还是会尝试回答你。我认为你的实现有点太复杂了,我不相信继承是实现不同迭代器的好方法。而且,迭代器可以提供的访问类型与它的实现无关(std::vectorstd::deque容器都支持随机访问,但是双端队列不保证存储器中的连续性,并且期望特定的实现通过索引来访问各个元素)。
另一方面,基于内存模型创建泛型迭代器是一个有趣的想法,它允许一定的灵活性和健壮性。您可以基于使用迭代器的数据结构来实现迭代器,将它们划分如下:数组迭代器、反队列迭代器、前向列表迭代器、列表迭代器、二叉树迭代器。
基本实现可以如下:

template <typename T, bool is_const>
struct /* iterator */
{
  using value_type = T;
  using pointer = std::conditional_t<is_const, const T*, T*>;
  using reference = std::conditional_t<is_const, const T&, T&>;
  using difference_type = std::ptrdiff_t;
  using iterator_category = /* implementation-defined */;

  /* iterator */() noexcept = default;
  explicit /* iterator */(pointer) noexcept;
  /* iterator */(const /* iterator */&) noexcept;
 
  template <bool is_constR>
  requires is_const && (!is_constR)
  /* iterator */(const /* iterator */<T, is_constR>&) noexcept;

  reference operator*() const noexcept;
  pointer operator->() const noexcept;
  /* iterator */& operator++() noexcept;
  /* iterator */ operator++(int) noexcept;
};

template <typename T, bool is_constL, bool is_constR>
inline bool operator==(const /* iterator */<T, is_constL>&, const /* iterator */<T, is_constR>&) noexcept;

template <typename T, bool is_constL, bool is_constR>
inline std::strong_ordering operator<=>(const /* iterator */<T, is_constL>&, const /* iterator */<T, is_constR>&) noexcept;

相关问题