std:: distance
|
Определено в заголовочном файле
<iterator>
|
||
|
template
<
class
InputIt
>
typename
std::
iterator_traits
<
InputIt
>
::
difference_type
|
(constexpr начиная с C++17) | |
Возвращает количество переходов от first до last .
Если
InputIt
не является
LegacyRandomAccessIterator
, поведение не определено, если
last
не является
достижимым
из
first
.
Если
InputIt
является
LegacyRandomAccessIterator
, поведение не определено, если
first
и
last
недостижимы друг из друга.
Содержание |
Параметры
| first | - | итератор, указывающий на первый элемент |
| last | - | итератор, указывающий на конец диапазона |
| Требования к типам | ||
-
InputIt
должен соответствовать требованиям
LegacyInputIterator
. Операция более эффективна, если
InputIt
дополнительно соответствует требованиям
LegacyRandomAccessIterator
.
|
||
Возвращаемое значение
Количество инкрементов, необходимых для перехода от first к last .
|
Значение может быть отрицательным, если используются итераторы произвольного доступа и first достижим из last . |
(since 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 | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 940 | C++98 | формулировка была неясной для случая, когда first достижим из last | прояснено |
Смотрите также
|
перемещает итератор на заданное расстояние
(шаблон функции) |
|
|
возвращает количество элементов, удовлетворяющих заданным критериям
(шаблон функции) |
|
|
(C++20)
|
возвращает расстояние между итератором и стражем, или между началом и концом диапазона
(функциональный объект алгоритма) |