微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

STL 容器中的迭代器实现

如何解决STL 容器中的迭代器实现

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

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

我无法理解发生了什么。

解决方法

您不能随意使用继承,因为如果您尝试,代码将有一个 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;
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。