矢量迭代器的复制构造函数如何使用 SFINAE 允许迭代器到 const_iterator 转换?

How vector iterator's copy-constructor use SFINAE to allow for iterator to const_iterator conversion?

在研究各种 std::vector 的迭代器实现时,我注意到这个复制构造函数使用 SFINAE 允许从非常量迭代器初始化常量迭代器,反之亦然:

// Allow iterator to const_iterator conversion
// ...
      // N.B. _Container::pointer is not actually in container requirements,
      // but is present in std::vector and std::basic_string.
      template<typename _Iter>
        __normal_iterator(const __normal_iterator<_Iter,
              typename __enable_if<
           (std::__are_same<_Iter, typename _Container::pointer>::__value),
              _Container>::__type>& __i) : _M_current(__i.base()) { }

众所周知,向量的迭代器是这样定义的:

      typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
      typedef __gnu_cxx::__normal_iterator<const_pointer, vector>
      const_iterator;

我不明白根据 Iter 检查容器的 pointer 类型如何允许转换。如果我传递一个常量迭代器,Iter 应该是 const_pointer,那会不会使 enable_if<> 检查失败并从集合中丢弃这个构造函数?那要用哪一个呢?

你能解释一下这个构造函数是如何工作的吗?也许可以举一个这种替换的例子?

P.S。 另一个问题是为什么 std::list 不使用通过像这样声明迭代器来避免代码重复的相同技术。对于两个版本的迭代器,它都有两个单独的 类。我想知道是否有可能以与 vector

完全相同的方式实现列表的迭代器

If I pass a constant iterator, Iter should be const_pointer, won't that fail the enable_if<> check and discard this constructor from the set? Which one will be used then?

是的,这正是发生的情况,因为该定义将是默认(隐式)复制构造函数的模糊重载。这些额外的构造函数允许 隐式 仅从非常量迭代器到 const 迭代器,以及从类指针类型到迭代器的显式转换。

至于std::list,我不知道!它可能只是一个任意的实现细节,或者这种方式被认为更 readable/maintainable.