Namespaces
Variants

std::ranges:: 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 I, std:: sentinel_for < I > S >

requires ( ! std:: sized_sentinel_for < S, I > )
constexpr std:: iter_difference_t < I >

distance ( I first, S last ) ;
(1) (since C++20)
template < class I, std:: sized_sentinel_for < std:: decay_t < I >> S >

constexpr std:: iter_difference_t < std:: decay_t < I >>

distance ( I && first, S last ) ;
(2) (since C++20)
template < ranges:: range R >

constexpr ranges:: range_difference_t < R >

distance ( R && r ) ;
(3) (since C++20)
1,2) Возвращает количество переходов от first до last .
3) Возвращает размер r в виде знакового целого числа.

Функциональные сущности, описанные на этой странице, являются algorithm function objects (неформально известными как niebloids ), то есть:

  • Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
  • Ни один из них не видим для argument-dependent lookup .
  • Когда любой из них найден с помощью normal unqualified lookup как имя слева от оператора вызова функции, argument-dependent lookup блокируется.

Содержание

Параметры

first - итератор, указывающий на первый элемент
last - ограничитель, обозначающий конец диапазона first является итератором для
r - диапазон для вычисления расстояния

Возвращаемое значение

1) Количество инкрементов, необходимое для перехода от first к last .
2) last - static_cast < const std:: decay_t < I > & > ( first ) .
3) Если R моделирует ranges:: sized_range , возвращает ranges:: size ( r ) ; иначе ranges :: distance ( ranges:: begin ( r ) , ranges:: end ( r ) ) .

Сложность

1) Линейный.
2) Константа.
3) Если R моделирует ranges:: sized_range или если std:: sized_sentinel_for < ranges:: sentinel_t < R > , ranges:: iterator_t < R >> выполняется, сложность постоянная; в противном случае линейная.

Возможная реализация

struct distance_fn
{
    template<class I, std::sentinel_for<I> S>
        requires (!std::sized_sentinel_for<S, I>)
    constexpr std::iter_difference_t<I> operator()(I first, S last) const
    {
        std::iter_difference_t<I> result = 0;
        while (first != last)
        {
            ++first;
            ++result;
        }
        return result;
    }
    template<class I, std::sized_sentinel_for<std::decay<I>> S>
    constexpr std::iter_difference_t<I> operator()(const I& first, S last) const
    {
        return last - first;
    }
    template<ranges::range R>
    constexpr ranges::range_difference_t<R> operator()(R&& r) const
    {
        if constexpr (ranges::sized_range<std::remove_cvref_t<R>>)
            return static_cast<ranges::range_difference_t<R>>(ranges::size(r));
        else
            return (*this)(ranges::begin(r), ranges::end(r));
    }
};
inline constexpr auto distance = distance_fn{};
**Примечание:** Весь код C++ внутри тегов `
` и `` оставлен без изменений, как и требовалось. HTML-теги и атрибуты также сохранены в оригинальном виде.

Пример

#include <cassert>
#include <forward_list>
#include <iterator>
#include <vector>
int main() 
{
    std::vector<int> v{3, 1, 4};
    assert(std::ranges::distance(v.begin(), v.end()) == 3);
    assert(std::ranges::distance(v.end(), v.begin()) == -3);
    assert(std::ranges::distance(v) == 3);
    std::forward_list<int> l{2, 7, 1};
    // auto size = std::ranges::size(l); // error: not a sizable range
    auto size = std::ranges::distance(l); // OK, but aware O(N) complexity
    assert(size == 3);
}

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 3392 C++20 перегрузка (1) принимает итератор по значению, поэтому lvalue move-only
итератора с размеченным sentinel отклонялось
добавлена перегрузка (2)
LWG 3664 C++20 решение LWG issue 3392 привело к тому, что
ranges::distance отклоняет аргументы-массивы
принимает их

Смотрите также

перемещает итератор на заданное расстояние или до заданной границы
(функциональный объект алгоритма)
возвращает количество элементов, удовлетворяющих заданным критериям
(функциональный объект алгоритма)
возвращает расстояние между двумя итераторами
(шаблон функции)