命名空间
变体
操作

std::ranges::distance

来自 cppreference.com
< cpp‎ | iterator
 
 
迭代器库
迭代器概念
迭代器原语
算法概念和实用程序
间接可调用概念
常见算法要求
(C++20)
(C++20)
(C++20)
实用程序
(C++20)
迭代器适配器
迭代器操作
(C++11)  
(C++11)
ranges::distance
(C++20)
范围访问
(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) (自 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) (自 C++20 起)
template< ranges::range R >

constexpr ranges::range_difference_t<R>

    distance( R&& r );
(3) (自 C++20 起)
1,2) 返回从 firstlast 的跃点数。
3) 返回 r 的大小,表示为带符号整数。

此页面上描述的类似函数的实体是 niebloids,即

实际上,它们可能作为函数对象实现,或使用特殊的编译器扩展。

内容

[编辑] 参数

first - 指向第一个元素的迭代器
last - 表示范围结束的哨兵 first 是指向
r - 要计算其距离的范围

[编辑] 返回值

1)firstlast 所需的增量次数。
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{};

[编辑] 示例

#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) 按值获取迭代器,因此是仅可移动的
具有大小哨兵的迭代器左值被拒绝
添加了重载 (2)
LWG 3664 C++20 解决LWG 问题 3392 的决议
使 ranges::distance 拒绝数组参数
接受它们

[编辑] 另请参阅

将迭代器向前移动给定距离或移动到给定边界
(niebloid)[编辑]
返回满足特定条件的元素数量
(niebloid)[编辑]
返回两个迭代器之间的距离
(函数模板) [编辑]