std::ranges::distance - cppreference.com

From cppreference.com

Defined in header

<iterator>

Call signature

template<classI,std::sentinel_for<I>S>requires(!std::sized_sentinel_for<S,I>)constexprstd::iter_difference_t<I>distance(Ifirst,Slast); (1) (since C++20)template<classI,std::sized_sentinel_for<std::decay_t<I>>S>constexprstd::iter_difference_t<std::decay_t<I>>distance(I&&first,Slast); (2) (since C++20)template<ranges::rangeR>constexprranges::range_difference_t<R>distance(R&&r); (3) (since C++20)1,2) Returns the number of hops from first to last.

3) Returns the size of r as a signed integer.

The function-like entities described on this page are

algorithm function objects

(informally known as niebloids), that is:

Explicit template argument lists cannot be specified when calling any of them.

None of them are visible to

argument-dependent lookup

.

When any of them are found by

normal unqualified lookup

as the name to the left of the function-call operator,

argument-dependent lookup

is inhibited.

Parameters

first - iterator pointing to the first element last - sentinel denoting the end of the range first is an iterator to r - range to calculate the distance of Return value

1) The number of increments needed to go from first to last.

2)last-static_cast<conststd::decay_t<I>&>(first).

3) If R models ranges::sized_range, returns ranges::size(r); otherwise ranges::distance(ranges::begin(r),ranges::end(r)).

Complexity

1) Linear.

2) Constant.

3) If R models ranges::sized_range or if std::sized_sentinel_for<ranges::sentinel_t<R>,ranges::iterator_t<R>> is modeled, complexity is constant; otherwise linear.

Possible implementation

structdistance_fn{template<classI,std::sentinel_for<I>S>requires(!std::sized_sentinel_for<S,I>)constexprstd::iter_difference_t<I>operator()(Ifirst,Slast)const{std::iter_difference_t<I>result=0;while(first!=last){++first;++result;}returnresult;}template<classI,std::sized_sentinel_for<std::decay<I>>S>constexprstd::iter_difference_t<I>operator()(constI&first,Slast)const{returnlast-first;}template<ranges::rangeR>constexprranges::range_difference_t<R>operator()(R&&r)const{ifconstexpr(ranges::sized_range<std::remove_cvref_t<R>>)returnstatic_cast<ranges::range_difference_t<R>>(ranges::size(r));elsereturn(*this)(ranges::begin(r),ranges::end(r));}};inlineconstexprautodistance=distance_fn{};Example

Run this code

#include<cassert>#include<forward_list>#include<iterator>#include<vector>intmain(){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 rangeautosize=std::ranges::distance(l);// OK, but aware O(N) complexityassert(size==3);}Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior

LWG 3392

C++20 overload (1) takes iterator by value, thus move-only
iterator lvalue with a sized sentinel was rejected added overload (2)

LWG 3664

C++20 the resolution of

LWG issue 3392

made
ranges::distance reject array arguments accepts them See also