std::distance
| Definiert in Header <iterator> |
||
| template< class InputIt > typename std::iterator_traits<InputIt>::difference_type |
(constexpr seit C++17) | |
Gibt die Anzahl der Schritte von first nach last zurück.
Wenn InputIt kein LegacyRandomAccessIterator ist, ist das Verhalten undefiniert, wenn last von first aus nicht erreichbar ist.
Wenn InputIt ein LegacyRandomAccessIterator ist, ist das Verhalten undefiniert, wenn first und last nicht gegenseitig erreichbar sind.
Inhalt |
[edit] Parameter
| first | - | Iterator, der auf das erste Element zeigt |
| last | - | Iterator, der auf das Ende des Bereichs zeigt |
| Typanforderungen | ||
-InputIt muss die Anforderungen eines LegacyInputIterator erfüllen. Die Operation ist effizienter, wenn InputIt zusätzlich die Anforderungen eines LegacyRandomAccessIterator erfüllt. | ||
[edit] Rückgabewert
Die Anzahl der Inkremente, die benötigt werden, um von first nach last zu gelangen.
|
Der Wert kann negativ sein, wenn Random-Access-Iteratoren verwendet werden und first von last aus erreichbar ist. |
(seit C++11) |
[edit] Komplexität
Linear.
Wenn InputIt zusätzlich die Anforderungen von LegacyRandomAccessIterator erfüllt, ist die Komplexität konstant.
[edit] Mögliche Implementierung
Siehe auch die Implementierungen in libstdc++ und libc++.
| C++98-Implementierung über Tag-Dispatch, ohne 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-Implementierung über 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; } } |
[edit] Beispiel
#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); }
Ausgabe
distance(first, last) = 3 distance(last, first) = -3
[edit] Defect Reports
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 940 | C++98 | die Formulierung war unklar für den Fall, dass first von last aus erreichbar ist | wurde klargestellt |
[edit] Siehe auch
| bewegt einen Iterator um die angegebene Distanz vorwärts (Funktionsvorlage) | |
| Gibt die Anzahl der Elemente zurück, die bestimmte Kriterien erfüllen (Funktionstempelat) | |
| (C++20) |
gibt die Distanz zwischen einem Iterator und einem Sentinel zurück oder die Distanz zwischen dem Anfang und dem Ende eines Bereichs (Algorithmus-Funktionsobjekt) |