c++ - 我可以/应该从 STL 迭代器继承吗?

标签 c++ stl iterator

我可以/应该继承STL迭代器来实现我自己的迭代器类吗?如果不是,为什么不呢?

最佳答案

简短回答

许多人认为,与常规类型别名相比,类 std::iterator 并没有提供太多功能,甚至通过不显式提供名称并依赖于模板参数的顺序来稍微混淆它们反而。它在 C++17 中已被弃用,并且可能会在几年内消失。

这意味着您不应再使用std::iterator。如果您对整个故事感兴趣,可以阅读下面的整篇文章(有一点冗余,因为它是在弃用提案之前开始的)。

<小时/>

旧答案

如果您对历史不感兴趣,可以忽略下面的所有内容。以下片段甚至多次自相矛盾。

从今天(C++11/C++14)开始,该标准似乎暗示从 std::iterator 继承来实现自定义迭代器不再是一个好主意。这里有一个简单的解释,来自N3931 :

Although the Standard has made this mistake almost a dozen times, I recommend not depicting directory_iterator and recursive_directory_iterator as deriving from std::iterator, since that's a binding requirement on implementations. Instead they should be depicted as having the appropriate typedefs, and leave it up to implementers to decide how to provide them. (The difference is observable to users with is_base_of, not that they should be asking that question.)

[2014-02-08 Daniel comments and provides wording]

This issue is basically similar to the kind of solution that had been used to remove the requirement to derive from unary_function and friends as described by N3198 and I'm strongly in favour to follow that spirit here as well. I'd like to add that basically all "newer" iterator types (such as the regex related iterator) don't derive from std::iterator either.

论文引用了N3198它本身声明它遵循 N3145 中讨论的弃用。 。弃用仅提供 typedef 的类的原因如下:

Our experience with concepts gives us confidence that it is rarely necessary to depend on specific base class-derived class relations, if availability of types and functions is sufficient. The new language tools allow us even in the absence of language-supported concepts to deduce the existence of typenames in class types, which would introduce a much weaker coupling among them. Another advantage of replacing inheritance by associated types is the fact, that this will reduce the number of cases, where ambiguities arise: This can easily happen, if a type would inherit both from unary_function and binary_function (This makes sense, if a functor is both an unary and a binary function object).

tl;dr:仅提供 typedef 的类现在被认为是无用的。此外,它们会在不需要时增加耦合,更加冗长,并且在某些极端情况下可能会产生不必要的副作用(请参阅前面的引用)。

<小时/>

更新: issue 2438 from N4245似乎实际上与我之前的断言相矛盾:

For LWG convenience, nine STL iterators are depicted as deriving from std::iterator to get their iterator_category/etc. typedefs. Unfortunately (and unintentionally), this also mandates the inheritance, which is observable (not just through is_base_of, but also overload resolution). This is unfortunate because it confuses users, who can be misled into thinking that their own iterators must derive from std::iterator, or that overloading functions to take std::iterator is somehow meaningful. This is also unintentional because the STL's most important iterators, the container iterators, aren't required to derive from std::iterator. (Some are even allowed to be raw pointers.) Finally, this unnecessarily constrains implementers, who may not want to derive from std::iterator. (For example, to simplify debugger views.)

总而言之,我错了,@aschepler 是对的:它可以可以使用,但它肯定不是必需的 - 也不劝阻它。整个“让我们删除 std::iterator” 的存在是为了让标准不限制标准库实现者。

<小时/>

第三轮: P0174R0建议弃用 std::iterator 以便将来可能删除。该提案已经很好地解释了为什么应该弃用它,所以我们开始:

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.

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. Therefore, it looks like a strong candidate for deprecation.

这变得有点累,而且似乎并不是每个人都同意,所以我会让你得出自己的结论。如果委员会最终决定应弃用 std::iterator,那么它将非常清楚地表明您不应再使用它。请注意 follow-up paper突出显示对删除 std::iterator 的大力支持:

Update from Jacksonville, 2016:

Poll: Deprecate iterator for C++17??
SF  F   N   A   SA
6    10  1    0   0

在上述投票结果中,SFFNASA 代表强烈支持赞成中立反对强烈反对>.

Update from Oulu, 2016:

Poll: Still want to deprecate std::iterator?
SF F N A SA
3   6  3  2  0

P0619R1建议尽快从 C++20 开始删除 std::iterator,并且还建议增强 std::iterator_traits 以便它可以自动推导类型 difference_typepointerreferencestd::iterator 在未明确提供时的方式相同。

关于c++ - 我可以/应该从 STL 迭代器继承吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6471019/

相关文章:

C++ 数组操作(类似 python 的操作)

c++ - 模板函数中的默认 const char* 模板参数

c++ - 未捕获的 std::exception 在核心中不正确的堆栈跟踪

c++ - 普通数组上的 std::lower_bound 和 std::find

接受对抽象类的 const 引用的 C++ 构造函数无法初始化 std::map

c++ - 在不移动数据的情况下在 CUDA 中实现 realloc

serialization - 将枚举值向量转换为另一个向量

c++ - Visual C++ 2010 std::set 查找损坏

c++ - 迭代 vector 对并使用 std::copy 打印结果

c++ - STL迭代器包装器