STL 容器中的迭代器实现

时间:2021-01-18 05:46:16

标签: c++ c++17

这是我编写的示例代码,只是一个测试迭代器实现的简单版本:

template <typename T>
struct ArrayIterator {
  using value_type = typename T::value_type;
  using pointer = value_type*;
  using reference = value_type&;
  using self = ArrayIterator;
  
  pointer ptr;
  
  ArrayIterator() : ptr{nullptr} {}
  ArrayIterator(pointer ptr) : ptr{ptr} {}
  
  reference operator*() {
    return *ptr;
  }
  
  bool operator==(self const& other) const {
    return ptr == other.ptr;
  }
  
  bool operator!=(self const& other) const {
    return !(*this == other);
  }
  
  self operator++() {
    ++ptr;
    return *this;
  }
  
  self operator++(int) {
    auto copy = *this;
    ++ptr;
    return copy;
  }
  
};

template <typename T, size_t size>
struct Array {
  T arr[size];
  
  using value_type = T;
  using iterator = ArrayIterator<Array<T, size>>;
  
  iterator begin() {
    return iterator(arr);
  }
  
  Array() : arr{1, 3, 4, 22, 3} {}
  
  iterator end() {
    return iterator(arr + size);
  }
};

int main() {
  using array = Array<int, 5>;
  array arr;
}

假设一切都是公开的,我们只传递 int 作为类型参数,并且数组具有默认构造函数只是为了测试基于范围的 for 循环。它有效。

我的问题是,为什么我们不能使用继承?像这样:

template <typename T, size_t size>
struct Array : ArrayIterator<Array<T, size>> {}

如果使用,我得到以下错误(编译器是 clang 11):

first.cpp:46:34: error: no type named 'value_type' in 'Array<int, 5>'
  using value_type = typename T::value_type;
                     ~~~~~~~~~~~~^~~~~~~~~~
first.cpp:82:16: note: in instantiation of template class 'ArrayIterator<Array<int, 5>>' requested here
struct Array : ArrayIterator<Array<T, size>> {
               ^
first.cpp:101:9: note: in instantiation of template class 'Array<int, 5>' requested here
  array arr;
        ^
1 error generated

我无法理解发生了什么。

1 个答案:

答案 0 :(得分:2)

您不能随意使用继承,因为如果您尝试,代码将有一个 catch-22。 ArrayIterator 将尝试将其 value_type 定义为数组 value_type 的别名,然后后者尚未定义。这就是您收到编译器错误的原因。

您的迭代器不需要访问 Array 类本身,因此将 Array 类类型传递给迭代器的模板参数是没有意义的。只需传递数组的 value_type 而不是 Array 本身,并将迭代器的 value_type 更改为只是 T 而不是 typename T::value_type

template <typename T>
struct ArrayIterator {
  using value_type = T;
  using pointer = value_type*;
  using reference = value_type&;
  using self = ArrayIterator;
  
  pointer ptr;
  
  ArrayIterator() : ptr{nullptr} {}
  ArrayIterator(pointer ptr) : ptr{ptr} {}
  
  reference operator*() {
    return *ptr;
  }
  
  bool operator==(self const& other) const {
    return ptr == other.ptr;
  }
  
  bool operator!=(self const& other) const {
    return ptr != other.ptr;
  }
  
  self& operator++() {
    ++ptr;
    return *this;
  }
  
  self operator++(int) {
    auto copy = *this;
    ++ptr;
    return copy;
  }
};

template <typename T, size_t size>
struct Array {
  using value_type = T;
  using iterator = ArrayIterator<T>;

  T arr[size];

  iterator begin() {
    return iterator(arr);
  }
  
  iterator end() {
    return iterator(arr + size);
  }
};

int main() {
  using array = Array<int, 5>;
  array arr{1, 3, 4, 22, 3};
  for (auto val : arr) {
    cout << val << endl;
  }
}

相关问题