std::distance
From cppreference.com
| ヘッダ <iterator> で定義 |
||
| template< class InputIt > typename std::iterator_traits<InputIt>::difference_type |
(C++17 以降 constexpr) | |
firstからlastまでのホップ数を返します。
InputItがLegacyRandomAccessIteratorでない場合、lastがfirstから到達可能でない場合、動作は未定義です。
InputItがLegacyRandomAccessIteratorである場合、firstとlastがお互いに到達可能でない場合、動作は未定義です。
目次 |
[編集] パラメータ
| first | - | 最初の要素を指すイテレータ |
| 最後 | - | 範囲の末尾を指すイテレータ |
| 型要件 | ||
-InputItはLegacyInputIteratorの要件を満たす必要があります。InputItがさらにLegacyRandomAccessIteratorの要件を満たす場合、操作はより効率的になります。 | ||
[編集] 戻り値
firstからlastへ移動するために必要なインクリメント数。
|
ランダムアクセス dinyatakan が使用され、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()); } |
| if constexprによる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'; // the behavior is undefined (until LWG940) static constexpr auto il = {3, 1, 4}; // Since C++17 `distance` can be used in constexpr context. 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から到達可能な場合の記述が不明確でした | 明確化された |
[編集] 関連項目
| イテレータを指定された距離だけ進める (関数テンプレート) | |
| 特定の基準を満たす要素の数を返す (関数テンプレート) | |
| (C++20) |
イテレータと番兵 (sentinel) の間の距離、またはRangeの始点と終点の間の距離を返す (アルゴリズム関数オブジェクト) |