简体   繁体   English

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

[英]Why is std::iterator deprecated?

Template class std::iterator is set to be deprecated in C++17. Why so?模板 class std::iterator设置为在 C++17 中弃用。为什么会这样? It has been a handy way to make surestd::iterator_traits works, especially if you can make use of the default template arguments. Is there some other way of doing it in C++17?这是确保std::iterator_traits工作的便捷方法,特别是如果您可以使用默认模板 arguments。在 C++17 中是否有其他方法可以做到这一点?

From the proposal that suggested its deprecation : 建议弃用的提案中

As an aid to writing iterator classes, the original standard library supplied the iterator class template to automate the declaration of the five typedefs expected of every iterator by iterator_traits. 作为编写迭代器类的辅助工具,原始标准库提供了迭代器类模板,以通过iterator_traits自动声明每个迭代器所需的五个typedef。 This was then used in the library itself, for instance in the specification of std::ostream_iterator : 然后在库本身中使用它,例如在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>; 

The long sequence of void arguments is much less clear to the reader than simply providing the expected typedefs in the class definition itself, which is the approach taken by the current working draft, following the pattern set in C++14 where we deprecated the derivation throughout the library of functors from unary_function and binary_function . 对于读者而言,很长的void参数序列不仅仅是简单地在类定义本身中提供期望的typedef,这是当前工作草案采用的方法,遵循C ++ 14中设置的模式,我们不推荐使用它们。整个函数库来自unary_functionbinary_function

In addition to the reduced clarity, the iterator template also lays a trap for the unwary, as in typical usage it will be a dependent base class, which means it will not be looking into during name lookup from within the class or its member functions. 除了降低清晰度之外,迭代器模板还为不谨慎的人设置陷阱,因为在典型的用法中它将是依赖的基类,这意味着它不会在类或其成员函数的名称查找期间查看。 This leads to surprised users trying to understand why the following simple usage does not work: 这会导致惊讶的用户试图理解为什么以下简单用法不起作用:

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

The reason of clarity alone was sufficient to persuade the LWG to update the standard library specification to no longer mandate the standard iterator adapators as deriving from std::iterator , so there is no further use of this template within the standard itself. 单凭清晰度的原因足以说服LWG更新标准库规范,不再要求标准迭代器适配器从std::iterator派生,因此在标准本身内不再使用此模板。 Therefore, it looks like a strong candidate for deprecation. 因此,它看起来像是一个强烈的弃用候选人。

You can also see STL's reasoning in LWG 2438 . 您还可以在LWG 2438中看到STL的推理。 (h/t TC ) (h / t TC


As for some other way of doing it, not really. 至于其他一些做法,不是真的。 You could basically implement your own version of std::iterator (which isn't too hard) or manually write out all of those typedefs (which isn't too hard either, and I actually prefer it for clarity). 您基本上可以实现自己的std::iterator版本(这不是太难)或者手动写出所有这些typedef(这也不是太难,为了清晰起见,我实际上更喜欢它)。

As Barry states, the working group has decided that explicitly declaring the types in the class is more readable and leads to less surprises than inheriting from std::iterator .正如 Barry 所述,工作组已决定在 class 中显式声明类型比从std::iterator继承更具可读性并且导致的意外更少。

It's not too hard, though, to convert to the explicit types (below example taken from www.fluentcpp.com here ).不过,转换为显式类型并不难(下面的示例取自www.fluentcpp.com here )。 Given a class that was declared like so:给定如下声明的 class:

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

The class without std::iterator becomes:没有std::iterator的 class 变为:

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

    // ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM