Spec-Zone.ru › C++

std::ranges::rend

Определено в заголовке <ranges>
Определено в заголовке <iterator>
inline namespace /* unspecified */ {
    inline constexpr /* unspecified */ rend = /* unspecified */;
}
(с C++20)
(объект точки кастомизации)
Подпись вызова
template< class T >
    requires /* see below */
constexpr std::sentinel_for<
    decltype(ranges::rbegin(std::declval<T>()))> auto rend( T&& t );
(с C++20)

Возвращает конечный маркер, обозначающий конец обратного диапазона.

range-rbegin-rend.svg

Если T является типом массива и std::remove_all_extents_t<std::remove_reference_t<T>> неполна, то вызов ranges::rend некорректен, диагностика не требуется.

Если аргумент является lvalue или ranges::enable_borrowed_range<std::remove_cv_t<T>> является true, то вызов ranges::rend эквивалентен:

  1. decay-copy(t.rend())(до C++23)auto(t.rend())(с C++23), если это выражение корректно и его тип соответствует std::sentinel_for<decltype(ranges::rbegin(std::declval<T>()))>.
  2. В противном случае, decay-copy(rend(t))(до C++23)auto(rend(t))(с 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 обозначает объект точки кастомизации, который является константным функциональным объектом литерального semiregular типа класса. Для наглядности, неквалифицированная версия его типа обозначается как __rend_fn.

Все экземпляры __rend_fn равны. Эффекты вызова различных экземпляров типа __rend_fn на одних и тех же аргументах эквивалентны, независимо от того, является ли выражение, обозначающее экземпляр, lvalue или rvalue, и квалифицировано ли оно как const или нет (хотя экземпляр с квалификатором volatile не обязан быть вызываемым). Таким образом, ranges::rend можно свободно копировать, а его копии могут использоваться взаимозаменяемо.

Учитывая набор типов Args..., если std::declval<Args>()... удовлетворяют требованиям аргументов для ranges::rend выше, __rend_fn моделирует

  • std::invocable<__rend_fn, Args...>,
  • std::invocable<const __rend_fn, Args...>,
  • std::invocable<__rend_fn&, Args...>, и
  • std::invocable<const __rend_fn&, Args...>.

В противном случае, ни один оператор вызова функции __rend_fn не участвует в разрешении перегрузки.

Примечания

Если аргумент является rvalue (т.е. 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, значение возврата создавалось с помощью move-конструктора из объекта-временной переменной. Все реализации непосредственно возвращают prvalue вместо этого. Требование исправлено предложением P0849R8 после C++20, чтобы соответствовать реализациям.

Пример

#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 существует механизм для запрета определённых нечленных rend найденных с помощью ADL такой механизм удалён

См. также

ranges::crend
(C++20)
возвращает обратный итератор конца для чтения только диапазона
(объект точки кастомизации)
ranges::rbegin
(C++20)
возвращает обратный итератор начала диапазона
(объект точки кастомизации)
rendcrend
(C++14)
возвращает обратный конечный итератор для контейнера или массива
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/ranges/rend

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API