std::distance
Определён в заголовочном файле <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.
| Значение может быть отрицательным, если используются итераторы произвольного доступа и | (начиная с 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 с помощью ifconstexpr |
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)(C++20) | |
|
(C++20) | возвращает расстояние между итератором и сентинелом либо между началом и концом диапазона (функциональный объект алгоритма) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/distance