Namespaces
Variants

std:: distance

From cppreference.net
Iterator library
Iterator concepts
Iterator primitives
Algorithm concepts and utilities
Indirect callable concepts
Common algorithm requirements
(C++20)
(C++20)
(C++20)
Utilities
(C++20)
Iterator adaptors
Range access
(C++11) (C++14)
(C++14) (C++14)
(C++11) (C++14)
(C++14) (C++14)
(C++17) (C++20)
(C++17)
(C++17)
ヘッダー <iterator> で定義
template < class InputIt >

typename std:: iterator_traits < InputIt > :: difference_type

distance ( InputIt first, InputIt last ) ;
(constexpr C++17以降)

first から last までのホップ数を返します。

InputIt LegacyRandomAccessIterator でない場合、 last first から 到達可能 でないとき、動作は未定義です。

InputIt LegacyRandomAccessIterator である場合、 first last が互いに到達可能でない場合、動作は未定義です。

目次

パラメータ

first - 最初の要素を指すイテレータ
last - 範囲の終端を指すイテレータ
型要件
-
InputIt LegacyInputIterator の要件を満たさなければならない。 InputIt が追加で LegacyRandomAccessIterator の要件も満たす場合、操作はより効率的になる。

戻り値

first から last まで移動するために必要なインクリメント回数。

ランダムアクセスイテレータが使用され、かつ first last から到達可能である場合、値は負になる可能性があります。

(C++11以降)

計算量

線形。

ただし、 InputIt がさらに LegacyRandomAccessIterator の要件を満たす場合、計算量は定数時間となります。

実装例

実装については libstdc++ および libc++ も参照してください。

C++98 タグディスパッチによる実装、 constexpr を除去
namespace detail
{
    template<class It>
    constexpr // required since 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 // required since 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 // since 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());
}
C++17 if constexpr による実装
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';
              // 動作は未定義(LWG940まで)
    static constexpr auto il = {3, 1, 4};
    // C++17以降、`distance`はconstexprコンテキストで使用可能
    static_assert(std::distance(il.begin(), il.end()) == 3);
    static_assert(std::distance(il.end(), il.begin()) == -3);
}

出力:

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

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 940 C++98 first last から到達可能な場合の記述が不明確であった 明確化された

関連項目

イテレータを指定された距離だけ進める
(関数テンプレート)
特定の条件を満たす要素の数を返す
(関数テンプレート)
イテレータとセンチネル間、または範囲の先頭と終端間の距離を返す
(アルゴリズム関数オブジェクト)