命名空间
变体
操作

std::ranges::rend

来自 cppreference.cn
< cpp‎ | ranges
 
 
范围库
范围适配器
 
定义于头文件 <ranges>
定义于头文件 <iterator>
inline namespace /* unspecified */ {

    inline constexpr /* unspecified */ rend = /* unspecified */;

}
(since C++20)
(定制点对象)
调用签名
template< class T >

    requires /* see below */
constexpr std::sentinel_for<

    decltype(ranges::rbegin(std::declval<T>()))> auto rend( T&& t );
(since C++20)

返回指示反向范围末尾的 sentinel。

range-rbegin-rend.svg

如果 T 是数组类型且 std::remove_all_extents_t<std::remove_reference_t<T>> 是不完整的,则调用 ranges::rend 是非良构的,无需诊断。

如果实参是左值或 ranges::enable_borrowed_range<std::remove_cv_t<T>>true,则调用 ranges::rend 等价于表达式

  1. decay-copy(t.rend())(until C++23)auto(t.rend())(since C++23),如果该表达式有效且其类型符合 std::sentinel_for<decltype(ranges::rbegin(std::declval<T>()))> 的模型。
  2. 否则,decay-copy(rend(t))(until C++23)auto(rend(t))(since C++23),如果 T 是类或枚举类型,则该表达式有效且其类型符合 std::sentinel_for<decltype(ranges::rbegin(std::declval<T>()))> 的模型,其中 rend 的含义建立为如同仅执行实参依赖查找一样。
  3. 否则,如果 std::make_reverse_iterator(ranges::begin(t)) ,如果 ranges::begin(t)ranges::end(t) 都是有效表达式,具有相同类型,并且该类型符合 std::bidirectional_iterator 的模型。

在所有其他情况下,调用 ranges::rend 都是非良构的,当 ranges::rend(t) 出现在模板实例化的直接语境中时,可能导致替换失败

内容

定制点对象

名称 ranges::rend 表示一个定制点对象,它是一个 const 函数对象,属于 字面量 semiregular 类类型。为了阐述目的,其类型的 cv-非限定版本表示为 __rend_fn

__rend_fn 的所有实例都相等。在相同实参上调用 __rend_fn 类型的不同实例的效果是等效的,无论表示实例的表达式是左值还是右值,以及是否是 const 限定的(但是,不要求可调用 volatile 限定的实例)。因此,ranges::rend 可以自由复制,并且其副本可以互换使用。

给定类型集合 Args...,如果 std::declval<Args>()... 满足上述 ranges::rend 实参的要求,则 __rend_fn 符合

否则,__rend_fn 的任何函数调用运算符都不参与重载决议。

[编辑] 注解

如果实参是右值(即 T 是对象类型)且 ranges::enable_borrowed_range<std::remove_cv_t<T>>false,或者它是未知边界的数组类型,则调用 ranges::rend 是非良构的,这也导致替换失败。

如果 ranges::rend(std::forward<T>(t)) 有效,则 decltype(ranges::rend(std::forward<T>(t)))decltype(ranges::begin(std::forward<T>(t))) 在所有情况下都符合 std::sentinel_for 的模型,而 T 符合 std::ranges::range 的模型。

C++20 标准要求,如果底层 rend 函数调用返回 prvalue,则返回值是从物化临时对象移动构造的。所有实现都直接返回 prvalue。后 C++20 提案 P0849R8 修正了该要求以匹配实现。

[编辑] 示例

#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
 
int main()
{
    std::vector<int> v = {3, 1, 4};
    namespace ranges = std::ranges;
    if (ranges::find(ranges::rbegin(v), ranges::rend(v), 5) != ranges::rend(v))
        std::cout << "found a 5 in vector v!\n";
 
    int a[] = {5, 10, 15};
    if (ranges::find(ranges::rbegin(a), ranges::rend(a), 5) != ranges::rend(a))
        std::cout << "found a 5 in array a!\n";
}

输出

found a 5 in array a!

[编辑] 缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

DR 应用于 已发布行为 正确行为
P2602R2 C++20 存在禁止通过 ADL 找到的某些非成员 rend 的机制 移除了此类机制

[编辑] 参见

返回只读范围的反向末尾迭代器
(定制点对象)[编辑]
返回范围的反向迭代器
(定制点对象)[编辑]
(C++14)
返回容器或数组的反向末尾迭代器
(函数模板) [编辑]