首页 > 解决方案 > std::iterator_traits 中的类型别名的“默认值”是否总是正确的?

问题描述

我在cppreference上读过,使用 C++20,可以省略指定类型 aliases referencepointer以及iterator_category在定义新迭代器时。在这种情况下,相应的别名std::iterator_traits将具有“默认”值。这个细节让我有点困惑,所以我试图把这个话题分解成可以回答的问题。所以,我的第一个问题是:这些“默认”别名中的所有(或部分)是否都保证是正确的?

据我了解,这些iterator_category标签基于 C++17 命名要求。如果迭代器满足前向迭代器要求(但不满足双向要求),则其标记应为forward_iterator_tag.

我特别担心forward_iterator_tag和之间的区别input_iterator_tag。前向迭代器必须能够在多通道算法中使用,但我认为编译器不会检查这种情况。在某些情况下我可以知道“默认”别名是正确的(例如,输出迭代器总是被正确分类,或者默认reference别名总是正确的)?

标签: c++iteratorlanguage-lawyerc++20

解决方案


定义“正确”。使用默认值的目的是充分覆盖最常见的情况,同时仍允许在需要时手动覆盖它们。这意味着,在这些情况下,默认值是不合适的。

你能写一个默认值无效的类型吗?reference默认情况下,无论*t返回什么,因此即使对于代理迭代器,默认值也很难出错。

pointer被定义为operator->会产生的东西,但如果不存在这样的东西,它将是void. 但这没关系,因为该pointertrait 并不是真正有用的,因为operator->它甚至不需要被任何迭代器类型支持。

iterator_category的默认值更有可能产生不正确的结果,但这并不常见。输入迭代器不像其他类型那样常见,因此您可以通过在编写输入迭代器时指定标签来轻松避免问题。

还应注意,iterator_category指定符合 C++17 迭代器类别。可以通过提供iterator_concept标记规范来覆盖 C++20 概念。

Note also that the ITER_CONCEPT meta-function in C++20 that extracts the iterator tag for the C++20 concepts explicitly bypasses the defaulting mechanism of iterator_category. That is, it only checks the tag you explicitly specify on the iterator itself (either via iterator_concept or iterator_category as a fallback) or on an iterator_traits specialization, not the default that the primary iterator_traits template would produce. So C++20's concepts requires you to specify the tag in some way, despite iterator_traits::iterator_category having a defaulting mechanism.


推荐阅读