std::input_iterator_tag, std::output_iterator_tag, std::forward_iterator_tag, std::bidirectional_iterator_tag, std::random_access_iterator_tag, std::contiguous_iterator_tag

< cpp‎ | iterator
在标头 <iterator> 定义
struct input_iterator_tag {};
(1)
struct output_iterator_tag {};
(2)
struct forward_iterator_tag : public input_iterator_tag {};
(3)
struct bidirectional_iterator_tag : public forward_iterator_tag {};
(4)
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
(5)
struct contiguous_iterator_tag : public random_access_iterator_tag {};
(6) (C++20 起)

定义迭代器的分类。每个标签均为空类型。

迭代器类别

对于每个老式迭代器 (LegacyIterator) 类型 Ittypedef std::iterator_traits<It>::iterator_category 必须定义为这些标签类型之一的别名,以指示 It 所在的最特定的类别。

  1. input_iterator_tag 对应老式输入迭代器 (LegacyInputIterator)
  2. output_iterator_tag 对应老式输出迭代器 (LegacyOutputIterator)
  3. forward_iterator_tag 对应老式向前迭代器 (LegacyForwardIterator)
  4. bidirectional_iterator_tag 对应老式双向迭代器 (LegacyBidirectionalIterator)
  5. random_access_iterator_tag 对应老式随机访问迭代器 (LegacyRandomAccessIterator)

迭代器分类标签携带信息,可以用于根据这一分类所蕴含的特定要求集合选择最高效算法。

迭代器概念

对每个 input_iterator 类型 It,可以声明 It::iterator_concept(若 std::iterator_traits<It> 从主模板生成)或 std::iterator_traits<It>::iterator_concept(若 std::iterator_traits<It> 被特化)为这些标签之一的别名,以指示 It 有意实现的最强迭代器概念。

  1. input_iterator_tag 对应 input_iterator
  2. forward_iterator_tag 对应 forward_iterator
  3. bidirectional_iterator_tag 对应 bidirectional_iterator
  4. random_access_iterator_tag 对应 random_access_iterator
  5. contiguous_iterator_tag 对应 contiguous_iterator

若未提供 iterator_concept,则以 iterator_category 为后备。若亦未提供 iterator_category(即 It老式迭代器 (LegacyIterator) ),且未特化 std::iterator_traits<It>,则假设为 random_access_iterator_tag

任何情况下,若不支持要求的操作则不满足各个概念,无关乎标签。

(C++20 起)

注解

没有用于老式连续迭代器 (LegacyContiguousIterator) 的独立标签。即不可能基于其 iterator_category 分辨老式连续迭代器 (LegacyContiguousIterator)要定义用于连续迭代器的特化算法,须使用 contiguous_iterator 概念。 (C++20 起)

output_iterator_tagoutput_iterator 概念之间没有对应关系。将 iterator_concept 设为 output_iterator_tag 只表明该类型并不实现 input_iterator

示例

如果需要根据迭代器分类标签选择算法,常用做法是使用分发函数(也可以通过 std::enable_if 实现)。各迭代器标签类也用于在相应的概念定义中表示要求,它们无法单独基于使用模式予以表达。 (C++20 起)

#include <iostream>
#include <iterator>
#include <list>
#include <vector>
 
// 使用概念(标签检查是概念自身的一部分)
 
template<std::bidirectional_iterator BDIter>
void alg(BDIter, BDIter)
{
    std::cout << "1. alg() \t 为双向迭代器调用\n";
}
 
template<std::random_access_iterator RAIter>
void alg(RAIter, RAIter)
{
    std::cout << "2. alg() \t 为随机访问迭代器调用\n";
}
 
// 遗留,使用标签派发
 
 
namespace legacy
{
    // 经常把实现细节隐藏于专门的命名空间
    namespace implementation_details
    {
        template<class BDIter>
        void alg(BDIter, BDIter, std::bidirectional_iterator_tag)
        {
            std::cout << "3. legacy::alg() 为双向迭代器调用\n";
        }
 
        template<class RAIter>
        void alg(RAIter, RAIter, std::random_access_iterator_tag)
        {
            std::cout << "4. legacy::alg() 为随机访问迭代器调用\n";
        }
    } // namespace implementation_details
 
    template<class Iter>
    void alg(Iter first, Iter last)
    {
        implementation_details::alg(first, last,
            typename std::iterator_traits<Iter>::iterator_category());
    }
} // namespace legacy
 
int main()
{
    std::list<int> l;
    alg(l.begin(), l.end()); // 1.
    legacy::alg(l.begin(), l.end()); // 3.
 
    std::vector<int> v;
    alg(v.begin(), v.end()); // 2.
    legacy::alg(v.begin(), v.end()); // 4.
 
//  std::istreambuf_iterator<char> i1(std::cin), i2;
//  alg(i1, i2);         // 编译错误:没有匹配的函数可以调用
//  legacy::alg(i1, i2); // 编译错误:没有匹配的函数可以调用
}

输出:

1. alg()        为双向迭代器调用
3. legacy::alg() 为双向迭代器调用
2. alg()         为随机访问迭代器调用
4. legacy::alg() 为随机访问迭代器调用

参阅

(C++17 中弃用)
用于简化简单的迭代器的必要类型定义的基类
(类模板)
为迭代器各项性质提供统一接口
(类模板)