# std::distance

< cpp‎ | iterator

定义于头文件 `<iterator>` |  |
template< class InputIt > typename std::iterator_traits<InputIt>::difference_type distance( InputIt first, InputIt last ); |  | (C++17 起为 `constexpr`)

返回从 `first` 到 `last` 的路程。

若 `last` 不可从 `first` 通过（可以重复）自增 `first` 抵达，则行为未定义。 | (C++11 前)
若 `InputIt` 不是老式随机访问迭代器 (LegacyRandomAccessIterator) ，则若 `last` 不可从 `first` 通过（可以重复）自增 `first` 抵达，则行为未定义。 若 `InputIt` 是老式随机访问迭代器 (LegacyRandomAccessIterator) ，则若 `last` 不可从 `first` 抵达且 `first` 不可从 `last` 抵达，则行为未定义。 | (C++11 起)

### 参数

first | - | 指向首元素的迭代器
last | - | 指向范围尾的迭代器
类型要求
- `InputIt` 必须满足老式输入迭代器 (LegacyInputIterator) 的要求。若 `InputIt` 额外满足老式随机访问迭代器 (LegacyRandomAccessIterator) 的要求则操作更高效

### 返回值

从 `first` 走到 `last` 所需的自增数。若使用随机访问迭代器且 `first` 可从 `last` 抵达，则值可能为负。 (C++11 起)

### 复杂度

线性。

然而，若 `InputIt` 额外满足老式随机访问迭代器 (LegacyRandomAccessIterator) 的要求，则复杂度是常数。

### 可能的实现

参阅 libstdc++ 与 libc++ 中的实现。

版本一
    // 经由标签派发的实现，移除 constexpr 后可用于 C++98
    namespace detail {

    template<class It>
    constexpr // C++17 起要求
    typename std::iterator_traits<It>::difference_type
        do_distance(It first, It last, std::input_iterator_tag)
    {
        typename std::iterator_traits<It>::difference_type result = 0;
        while (first != last) {
            ++first;
            ++result;
        }
        return result;
    }

    template<class It>
    constexpr // C++17 起要求
    typename std::iterator_traits<It>::difference_type
        do_distance(It first, It last, std::random_access_iterator_tag)
    {
        return last - first;
    }

    } // namespace detail

    template<class It>
    constexpr // C++17 起
    typename std::iterator_traits<It>::difference_type
        distance(It first, It last)
    {
        return detail::do_distance(first, last,
                                   typename std::iterator_traits<It>::iterator_category());
    }
版本二
    // 经由 constexpr if 的实现，可用于 C++17
    template<class It>
    constexpr typename std::iterator_traits<It>::difference_type
        distance(It first, It last)
    {
        using category = typename std::iterator_traits<It>::iterator_category;
        static_assert(std::is_base_of_v<std::input_iterator_tag, category>);

        if constexpr (std::is_base_of_v<std::random_access_iterator_tag, category>)
            return last - first;
        else {
            typename std::iterator_traits<It>::difference_type result = 0;
            while (first != last) {
                ++first;
                ++result;
            }
            return result;
        }
    }

### 示例

    #include <iostream>
    #include <iterator>
    #include <vector>

    int main()
    {
        std::vector<int> v{ 3, 1, 4 };
        std::cout << "distance(first, last) = "
                  << std::distance(v.begin(), v.end()) << '\n'
                  << "distance(last, first) = "
                  << std::distance(v.end(), v.begin()) << '\n';
    }

输出：

    distance(first, last) = 3
    distance(last, first) = -3

### 参阅

advance | 令迭代器前进给定的距离 (函数模板)