为什么 std::iterator 被弃用?

问题描述 投票:0回答:2

模板类

std::iterator
在 C++17 中已被弃用。 为什么会这样呢? 这是确保
std::iterator_traits
工作的便捷方法,特别是如果您可以使用默认模板参数的话。 在 C++17 中还有其他方法吗?

c++ c++17
2个回答
34
投票

来自建议弃用的提案

作为编写迭代器类的辅助工具,原始标准库提供了迭代器类模板,以通过 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>;

长序列的

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 ...
};

仅出于清晰度的原因就足以说服 LWG 更新标准库规范,不再强制要求标准迭代器适配器派生自

std::iterator
,因此标准本身中不再使用此模板。因此,它看起来很适合弃用。

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


至于其他一些方法,则不然。您基本上可以实现自己的

std::iterator
版本(这并不太难)或手动写出所有这些 typedef(这也不是太难,为了清晰起见,我实际上更喜欢它)。


11
投票

正如 Barry 所说,工作组已经决定,与从

std::iterator
继承相比,显式声明类中的类型更具可读性,并且不会产生意外。

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

class MyIterator
  : public std::iterator<std::forward_iterator_tag, int, int, int*, int&>
{
  ...

没有

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&;

    // ...
© www.soinside.com 2019 - 2024. All rights reserved.