From cppreference.com
Defined in header
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
(informally known as niebloids), that is:
Explicit template argument lists cannot be specified when calling any of them.
None of them are visible to
.
When any of them are found by
as the name to the left of the function-call operator,
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
C++20 overload (1) takes iterator by value, thus move-only
iterator lvalue with a sized sentinel was rejected added overload (2)
C++20 the resolution of
made
ranges::distance reject array arguments accepts them See also