CppDS.com

C++ 98 11 14 17 20 手册

std::iterator_traits

来自cppreference.com
< cpp‎ | iterator
 
 
迭代器库
迭代器概念
迭代器原语
算法概念与工具
间接可调用概念
常用算法要求
工具
迭代器适配器
流迭代器
迭代器定制点
迭代器操作
(C++11)
(C++11)
范围访问
(C++11)(C++14)
(C++11)(C++14)
(C++17)(C++20)
(C++14)(C++14)
(C++14)(C++14)
(C++17)
(C++17)
 
定义于头文件 <iterator>
template< class Iter >
struct iterator_traits;
template< class T >
struct iterator_traits<T*>;
template< class T >
struct iterator_traits<const T*>;
(C++20 前)

std::iterator_traits 是类型特性类,为迭代器类型的属性提供统一的接口,使得能够仅针对迭代器实现算法。

该类定义了如下类型,与 std::iterator 中的类型定义相对应:

  • difference_type - 可用来标识迭代器间距离的有符号整数类型
  • value_type - 迭代器解除引用后所得到的值的类型。对于输出迭代器,该类型为 void
  • pointer - 指向被迭代类型 (value_type) 的指针
  • reference - 被迭代类型 (value_type) 的引用类型
  • iterator_category - 迭代器类别。必须是迭代器类别标签之一。

可以针对用户自定义迭代器特化该模版,这样,即便该类型没有提供一般的类型定义,也能获取关于该迭代器的信息。

模版形参

Iter - 需要取得与之相关属性的迭代器类型

成员类型

 
成员类型 定义
difference_type Iter::difference_type
value_type Iter::value_type
pointer Iter::pointer
reference Iter::reference
iterator_category Iter::iterator_category

Iter 没有全部五个成员类型 difference_typevalue_typepointerreferenceiterator_category ,则此模板无任何有那些名称的成员( std::iterator_traits 对 SFINAE 友好)

(C++17 起)
(C++20 前)

Iterpointer ,但拥有全部其他四个成员类型,则按如下方式声明成员类型:

 
成员类型 定义
difference_type Iter::difference_type
value_type Iter::value_type
pointer void
reference Iter::reference
iterator_category Iter::iterator_category

否则,若 Iter 满足仅为说明的概念 __LegacyInputIterator ,则按如下方式声明成员类型:

 
成员类型 定义
difference_type std::incrementable_traits<Iter>::difference_type
value_type std::indirectly_readable_traits<Iter>::value_type
pointer 若合法则为 Iter::pointer ,否则若合法则为 decltype(std::declval<Iter&>().operator->()) ,否则为 void
reference 若合法则为 Iter::reference ,否则为 std::iter_reference_t<Iter>
iterator_category 若合法则为 Iter::iterator_category
否则若 Iter 满足 __LegacyRandomAccessIterator

则为 std::random_access_iterator_tag
否则若 Iter 满足 __LegacyBidirectionalIterator 则为 std::bidirectional_iterator_tag
否则若 Iter 满足 __LegacyForwardIterator 则为 std::forward_iterator_tag
否则为 std::input_iterator_tag

否则,若 Iter 满足仅为说明的概念 __LegacyIterator ,则按如下方式声明成员类型:

 
成员类型 定义
difference_type 若合法则为 std::incrementable_traits<Iter>::difference_type ,否则为 void
value_type void
pointer void
reference void
iterator_category std::output_iterator_tag

否则,此模板无任何有这些名称的成员此模板无任何有那些名称的成员( std::iterator_traits 对 SFINAE 友好)。

(C++20 起)

特化

如果要把用户提供的类型作为迭代器使用,该类型特征可以针对这一类型进行特化。标准库中提供了针对指针类型 T * 的两种偏特化,使得可以在任何需要迭代器的算法里使用裸指针。

T * 特化成员类型

仅若 std::is_object_v<T>true 才特化。

(C++20 起)
 
成员类型 定义
difference_type std::ptrdiff_t
value_type T (C++20 前)std::remove_cv_t<T> (C++20 起)
pointer T*
reference T&
iterator_category std::random_access_iterator_tag
iterator_concept(C++20 起) std::contiguous_iterator_tag

const T * 特化成员类型

 
成员类型 定义
difference_type std::ptrdiff_t
value_type T
pointer const T*
reference const T&
iterator_category std::random_access_iterator_tag
(C++20 前)

示例

下列使用展示对双向迭代器的通用 reverse() 实现

#include <iostream>
#include <iterator>
#include <vector>
#include <list>
 
template<class BidirIt>
void my_reverse(BidirIt first, BidirIt last)
{
    typename std::iterator_traits<BidirIt>::difference_type n = std::distance(first, last);
    --n;
    while(n > 0) {
        typename std::iterator_traits<BidirIt>::value_type tmp = *first;
        *first++ = *--last;
        *last = tmp;
        n -= 2;
    }
}
 
int main()
{
    std::vector<int> v{1, 2, 3, 4, 5};
    my_reverse(v.begin(), v.end());
    for (int n : v) {
        std::cout << n << ' ';
    }
    std::cout << '\n';
 
    std::list<int> l{1, 2, 3, 4, 5};
    my_reverse(l.begin(), l.end());
    for (auto n : l) {
        std::cout << n << ' ';
    }
    std::cout << '\n';
 
    int a[] = {1, 2, 3, 4, 5};
    my_reverse(a, a+5);
    for (int i=0; i<5; ++i) {
        std::cout << a[i] << ' ';
    }
    std::cout << '\n';
 
//    std::istreambuf_iterator<char> i1(std::cin), i2;
//    my_reverse(i1, i2); // 编译错误
 
}

输出:

5 4 3 2 1
5 4 3 2 1
5 4 3 2 1

参阅

(C++17 中弃用)
用于简化简单的迭代器的必要类型定义的基类
(类模板)
用于指示迭代器类别的空类类型
(类)
关闭