为什么不推荐使用std :: iterator?

asc*_*ler 39 c++ c++17

模板类std::iterator设置为在C++ 17中弃用.为什么这样?它是确保std::iterator_traits工作的一种方便方法,特别是如果您可以使用默认模板参数.在C++ 17中还有其他一些方法吗?

Bar*_*rry 26

建议弃用的提案中:

作为编写迭代器类的辅助工具,原始标准库提供了迭代器类模板,以通过iterator_traits自动声明每个迭代器所需的五个typedef.然后将其用于库本身,例如在以下规范中std::ostream_iterator:

template <class T, class charT = char, class traits = char_traits<charT> >
class ostream_iterator:
  public iterator<output_iterator_tag, void, void, void, void>;
Run Code Online (Sandbox Code Playgroud)

对于void读者来说,很长的参数序列不仅仅是简单地在类定义本身中提供预期的typedef,这是当前工作草案采用的方法,遵循C++ 14中设置的模式,我们在整个过程中不推荐使用来自unary_function和的编写器库binary_function.

除了降低清晰度之外,迭代器模板还为不谨慎的人设置陷阱,因为在典型的用法中它将是依赖的基类,这意味着它不会在类或其成员函数的名称查找期间查看.这会导致惊讶的用户试图理解为什么以下简单用法不起作用:

#include <iterator>

template <typename T>
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> {
   value_type data;  // Error: value_type is not found by name lookup 

   // ... implementations details elided ...
};
Run Code Online (Sandbox Code Playgroud)

单凭清晰度的原因足以说服LWG更新标准库规范,不再强制使用标准迭代器适配器std::iterator,因此标准本身不再使用此模板.因此,它看起来像是一个强烈的弃用候选人.

您还可以在LWG 2438中看到STL的推理.(h/t TC)


至于其他一些做法,不是真的.您基本上可以实现自己的版本std::iterator(这不是太难)或手动写出所有这些typedef(这也不是太难,我实际上更喜欢它的清晰度).

  • STL在[LWG 2438](https://timsong-cpp.github.io/lwg-issues/2438)中的论点似乎也是合理的:这个名称可能误导用户(特别是*ahem*某些其他编程语言)认为派生是强制性的,或者编写接受`std :: iterator`的函数是有意义的. (7认同)
  • 为什么派生类找不到 value_type? (2认同)
  • 可以在[此处](/sf/answers/2667237611/)找到手动编写所需的 5 个 typedef 的示例。 (2认同)

fir*_*ush 9

正如 Barry 所说,工作组已经决定,在类中显式声明类型比继承自std::iterator.

不过,转换为显式类型并不太难(下面的示例取自www.fluencecpp.com 此处)。给定一个这样声明的类:

class MyIterator
  : public std::iterator<std::forward_iterator_tag, int, int, int*, int&>
{
  ...
Run Code Online (Sandbox Code Playgroud)

没有的班级std::iterator变成:

class MyIterator
{
public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = int;
    using difference_type = int;
    using pointer = int*;
    using reference = int&;

    // ...
Run Code Online (Sandbox Code Playgroud)