【问题标题】:Why does reverse_iterator doubly define its nested types?为什么 reverse_iterator 双重定义它的嵌套类型?
【发布时间】:2015-05-20 11:08:14
【问题描述】:

似乎迭代器适配器reverse_iterator 双重定义了它的大部分嵌套类型。特别是,它公开继承自std::iterator,它公开了iterator_categoryvalue_typedifference_typepointerreference。除了iterator_categoryvalue_type,这些都在类定义中再次显式typedef'ed。

24.5.1.1 类模板 reverse_iterator [reverse.iterator]

namespace std {
template <class Iterator>
class reverse_iterator : public
     iterator<typename iterator_traits<Iterator>::iterator_category,
     typename iterator_traits<Iterator>::value_type,
     typename iterator_traits<Iterator>::difference_type,
     typename iterator_traits<Iterator>::pointer,
     typename iterator_traits<Iterator>::reference> {
public:
  typedef Iterator                                            iterator_type;
  typedef typename iterator_traits<Iterator>::difference_type difference_type;
  typedef typename iterator_traits<Iterator>::reference       reference;
  typedef typename iterator_traits<Iterator>::pointer         pointer;
  // ... rest of the class
};

问题:为什么要重复定义?这仅仅是为了说明,还是有更多的意义?为什么不重新定义iterator_categoryvalue_type

【问题讨论】:

  • 它也没有重新定义value_type。无论如何,这个问题很快就会变得没有意义,感谢LWG 2438
  • @T.C.感谢您挖掘该博士。我更新了 Q。如果你把它作为答案,我会接受。
  • 也许它与依赖名称查找有关?从iterator 继承的名称并非在所有情况下都可见,因为它是一个依赖基类。
  • @dyp 可能。我也从我的模板库中提取我使用的类型。
  • 这可能归结为 dependent-name 的基础,这进一步意味着在编写 @ 的定义时,编写 pointer 比编写 typename iterator_traits&lt;Iterator&gt;::pointer 更容易987654339@.

标签: c++ iterator language-lawyer reverse-iterator iterator-traits


【解决方案1】:

一段时间以来,他们已经不再使用 std::iterator 作为基类,而是只指定每个迭代器必须定义正确的类型名称。

当他们在标准中指定基类时,这会限制实现以这种方式实现该类,即使唯一真正的意图是指定迭代器需要定义一些名称。特别是,您可以is_base_of 来确定@​​987654327@ 是否是std::reverse_iterator 的基类。不,没有什么是多态的,所以这样做非常愚蠢和毫无意义,但如果你这样做,当前的标准规定它必须返回 true。

看起来(在我看来)这或多或少是从(或多或少意外)需要使用std::iterator 作为基类的过程中的一个意外的中间点,并且只需指定名称必须在 std::reverse_iterator 中定义(当然还有其他各种迭代器)。

对于那些关心的人,它的历史包括:

N3931
Issue 2438

还有关于弃用 unary_function 和 binary_function 的相关讨论论文:

N3145
N3198

提供这些的原因与 std::iterator 大致相同(即,只是为了在派生类中提供一些 typedef),因此删除它们的原因与停止使用 std::iterator 作为基类相当相关。

【讨论】:

  • 很难调用is_base_of&lt;std::iterator, std::reverse_iterator&gt;,因为两者都不是类型。 ;) 当我自己使用std::iterator 时,我倾向于引入我使用的定义,因为如果我自己是一个模板,我不能在内部使用它们(由于依赖名称查找)。
  • reverse_iterator的定义在C++03 IS中已经是这样了。
  • @dyp:考虑到 Google Groups 的状态,我不确定我能找到它,但我记得一个 Usenet 线程,似乎是在 1996 年左右,已经在争论这些是一个糟糕的主意,应该直接指定 typedef。
  • 所以答案是多余的std::iterator&lt;&gt;,而不是课堂上的typedef
  • @TemplateRex:是的,差不多。
【解决方案2】:

这更像是一种猜测,但所有那些多余的typedefs 声明了在reverse_iterator 的类主体规范中使用的类型。例如(C++03 IS):

pointer operator->() const;
reference operator[](difference_type n) const;

由于iterator&lt;..&gt; 是一个依赖基类,因此不会搜索名称pointerreference。所以typedefing 这些名字使剩下的规范更简单:

typename iterator_traits<Iterator>::pointer operator->() const;
typename iterator_traits<Iterator>::reference operator[](typename iterator_traits<Iterator>::difference_type n) const;

另一方面,value_type 不会出现在类主体中,因此它不需要多余的typedef

【讨论】:

  • 当然,这并不能回答为什么首先要从 iterator 派生的问题。但是一旦给出,typedefs 就是为了方便起见的暗示。
  • operator[] 的返回类型在 C++14 IS 中未指定,顺便说一句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 2022-10-24
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多