STL/stl/inc/ranges

4414 строки
190 KiB
C++

// ranges standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#pragma once
#ifndef _RANGES_
#define _RANGES_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#ifndef __cpp_lib_ranges
#pragma message("The contents of <ranges> are available only in c++latest mode with concepts support;")
#pragma message("see https://github.com/microsoft/STL/issues/1814 for details.")
#else // ^^^ !defined(__cpp_lib_ranges) / defined(__cpp_lib_ranges) vvv
#include <iosfwd>
#include <iterator>
#include <limits>
#include <span>
#include <string_view>
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN
namespace ranges {
// MUCH machinery defined in <xutility>
// clang-format off
// CONCEPT ranges::viewable_range
template <class _Rng>
concept viewable_range = range<_Rng>
&& ((view<remove_cvref_t<_Rng>> && constructible_from<remove_cvref_t<_Rng>, _Rng>)
|| (!view<remove_cvref_t<_Rng>> && borrowed_range<_Rng>));
template <class _Rng>
concept _Simple_view = view<_Rng> && range<const _Rng>
&& same_as<iterator_t<_Rng>, iterator_t<const _Rng>>
&& same_as<sentinel_t<_Rng>, sentinel_t<const _Rng>>;
template <class _Ty>
concept _Copy_constructible_object = copy_constructible<_Ty> && is_object_v<_Ty>;
template <class _It>
concept _Has_arrow = input_iterator<_It>
&& (is_pointer_v<_It> || _Has_member_arrow<_It&>);
// clang-format on
template <bool _IsConst, class _Ty>
using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>;
template <bool _IsWrapped, class _Ty>
using _Maybe_wrapped = conditional_t<_IsWrapped, _Ty, _Unwrapped_t<_Ty>>;
namespace _Pipe {
// clang-format off
template <class _Left, class _Right>
concept _Can_pipe = requires(_Left&& __l, _Right&& __r) {
static_cast<_Right&&>(__r)(static_cast<_Left&&>(__l));
};
template <class _Left, class _Right>
concept _Can_compose = constructible_from<remove_cvref_t<_Left>, _Left>
&& constructible_from<remove_cvref_t<_Right>, _Right>;
// clang-format on
template <class, class>
struct _Pipeline;
template <class _Derived>
struct _Base {
// clang-format off
template <class _Other>
requires _Can_compose<_Derived, _Other>
constexpr auto operator|(_Base<_Other>&& __r) && noexcept(
noexcept(_Pipeline{static_cast<_Derived&&>(*this), static_cast<_Other&&>(__r)})) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<_Derived&&>(*this), static_cast<_Other&&>(__r)};
}
// clang-format off
template <class _Other>
requires _Can_compose<_Derived, const _Other&>
constexpr auto operator|(const _Base<_Other>& __r) && noexcept(
noexcept(_Pipeline{static_cast<_Derived&&>(*this), static_cast<const _Other&>(__r)})) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<_Derived&&>(*this), static_cast<const _Other&>(__r)};
}
// clang-format off
template <class _Other>
requires _Can_compose<const _Derived&, _Other>
constexpr auto operator|(_Base<_Other>&& __r) const& noexcept(
noexcept(_Pipeline{static_cast<const _Derived&>(*this), static_cast<_Other&&>(__r)})) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<const _Derived&>(*this), static_cast<_Other&&>(__r)};
}
// clang-format off
template <class _Other>
requires _Can_compose<const _Derived&, const _Other&>
constexpr auto operator|(const _Base<_Other>& __r) const& noexcept(
noexcept(_Pipeline{static_cast<const _Derived&>(*this), static_cast<const _Other&>(__r)})) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>);
_STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>);
return _Pipeline{static_cast<const _Derived&>(*this), static_cast<const _Other&>(__r)};
}
template <_Can_pipe<const _Derived&> _Left>
friend constexpr auto operator|(_Left&& __l, const _Base& __r)
#ifdef __EDG__ // TRANSITION, VSO-1222776
noexcept(noexcept(_STD declval<const _Derived&>()(_STD forward<_Left>(__l))))
#else // ^^^ workaround / no workaround vvv
noexcept(noexcept(static_cast<const _Derived&>(__r)(_STD forward<_Left>(__l))))
#endif // TRANSITION, VSO-1222776
{
return static_cast<const _Derived&>(__r)(_STD forward<_Left>(__l));
}
template <_Can_pipe<_Derived> _Left>
friend constexpr auto operator|(_Left&& __l, _Base&& __r)
#ifdef __EDG__ // TRANSITION, VSO-1222776
noexcept(noexcept(_STD declval<_Derived>()(_STD forward<_Left>(__l))))
#else // ^^^ workaround / no workaround vvv
noexcept(noexcept(static_cast<_Derived&&>(__r)(_STD forward<_Left>(__l))))
#endif // TRANSITION, VSO-1222776
{
return static_cast<_Derived&&>(__r)(_STD forward<_Left>(__l));
}
};
template <class _Left, class _Right>
struct _Pipeline : _Base<_Pipeline<_Left, _Right>> {
/* [[no_unique_address]] */ _Left __l;
/* [[no_unique_address]] */ _Right __r;
template <class _Ty1, class _Ty2>
constexpr explicit _Pipeline(_Ty1&& _Val1, _Ty2&& _Val2) noexcept(
is_nothrow_convertible_v<_Ty1, _Left>&& is_nothrow_convertible_v<_Ty2, _Right>)
: __l(_STD forward<_Ty1>(_Val1)), __r(_STD forward<_Ty2>(_Val2)) {}
template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) noexcept(
noexcept(__r(__l(_STD forward<_Ty>(_Val))))) requires requires {
__r(__l(static_cast<_Ty&&>(_Val)));
}
{ return __r(__l(_STD forward<_Ty>(_Val))); }
template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) const
noexcept(noexcept(__r(__l(_STD forward<_Ty>(_Val))))) requires requires {
__r(__l(static_cast<_Ty&&>(_Val)));
}
{ return __r(__l(_STD forward<_Ty>(_Val))); }
};
template <class _Ty1, class _Ty2>
_Pipeline(_Ty1, _Ty2) -> _Pipeline<_Ty1, _Ty2>;
} // namespace _Pipe
template <range _Rng, class _Derived>
class _Cached_position : public view_interface<_Derived> {
static_assert(_Always_false<_Rng>, "A range must be at least forward for position caching to be worthwhile.");
};
template <forward_range _Rng, class _Derived>
class _Cached_position<_Rng, _Derived> : public view_interface<_Derived> {
private:
using _It = iterator_t<_Rng>;
/* [[no_unique_address]] */ _It _Pos{};
bool _Cached = false;
protected:
_Cached_position() = default;
~_Cached_position() = default;
// a copied iterator doesn't point into a copied range, so cache values must not propagate via copy
constexpr _Cached_position(const _Cached_position&) noexcept(is_nothrow_default_constructible_v<_It>) {}
constexpr _Cached_position& operator=(const _Cached_position&) noexcept(
is_nothrow_default_constructible_v<_It>) {
_Pos = _It{};
_Cached = false;
return *this;
}
_NODISCARD constexpr bool _Has_cache() const noexcept { // Is there a cached position?
return _Cached;
}
_NODISCARD constexpr _It _Get_cache(_Rng&) const noexcept(is_nothrow_copy_constructible_v<_It>) {
_STL_INTERNAL_CHECK(_Cached);
return _Pos;
}
_NODISCARD constexpr void _Set_cache(_Rng&, _It _Iter) noexcept(is_nothrow_move_assignable_v<_It>) {
_Pos = _STD move(_Iter);
_Cached = true;
}
};
template <random_access_range _Rng, class _Derived>
class _Cached_position<_Rng, _Derived> : public view_interface<_Derived> {
private:
using _It = iterator_t<_Rng>;
range_difference_t<_Rng> _Off = -1;
protected:
_Cached_position() = default;
~_Cached_position() = default;
// Offsets are oblivious to copying, so cache values _do_ propagate via copying.
_Cached_position(const _Cached_position&) = default;
_Cached_position& operator=(const _Cached_position&) = default;
_NODISCARD constexpr bool _Has_cache() const noexcept { // Is there a cached position?
return _Off >= range_difference_t<_Rng>{0};
}
_NODISCARD constexpr _It _Get_cache(_Rng& _Range) const noexcept(noexcept(_RANGES begin(_Range) + _Off)) {
_STL_INTERNAL_CHECK(_Has_cache());
return _RANGES begin(_Range) + _Off;
}
_NODISCARD constexpr void _Set_cache(_Rng& _Range, const _It& _Iter) noexcept(
noexcept(_Off = _Iter - _RANGES begin(_Range))) {
_Off = _Iter - _RANGES begin(_Range);
}
};
template <bool _Enable, class _Rng, class _Derived>
using _Cached_position_t = conditional_t<_Enable, _Cached_position<_Rng, _Derived>, view_interface<_Derived>>;
// CLASS TEMPLATE ranges::_Copyable_box
template <_Copy_constructible_object _Ty>
class _Copyable_box { // a simplified optional that augments copy_constructible types with full copyability
public:
constexpr _Copyable_box() noexcept(is_nothrow_default_constructible_v<_Ty>) requires default_initializable<_Ty>
: _Val(), _Engaged{true} {}
template <class... _Types>
constexpr _Copyable_box(in_place_t, _Types&&... _Args) noexcept(
is_nothrow_constructible_v<_Ty, _Types...>) // strengthened
: _Val(_STD forward<_Types>(_Args)...), _Engaged{true} {}
// clang-format off
~_Copyable_box() requires is_trivially_destructible_v<_Ty> = default;
// clang-format on
constexpr ~_Copyable_box() {
if (_Engaged) {
_Val.~_Ty();
}
}
// clang-format off
_Copyable_box(const _Copyable_box&) requires is_trivially_copy_constructible_v<_Ty> = default;
// clang-format on
constexpr _Copyable_box(const _Copyable_box& _That) : _Engaged{_That._Engaged} {
if (_That._Engaged) {
_Construct_in_place(_Val, _That._Val);
}
}
// clang-format off
_Copyable_box(_Copyable_box&&) requires is_trivially_move_constructible_v<_Ty> = default;
// clang-format on
constexpr _Copyable_box(_Copyable_box&& _That) : _Engaged{_That._Engaged} {
if (_That._Engaged) {
_Construct_in_place(_Val, _STD move(_That._Val));
}
}
// clang-format off
_Copyable_box& operator=(const _Copyable_box&) noexcept
requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty> = default;
// clang-format on
constexpr _Copyable_box& operator=(const _Copyable_box& _That) noexcept(
is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_copy_assignable_v<_Ty>) // strengthened
requires copyable<_Ty> {
if (_Engaged) {
if (_That._Engaged) {
_Val = _That._Val;
} else {
_Val.~_Ty();
_Engaged = false;
}
} else {
if (_That._Engaged) {
_Construct_in_place(_Val, _That._Val);
_Engaged = true;
} else {
// nothing to do
}
}
return *this;
}
constexpr _Copyable_box& operator=(const _Copyable_box& _That) noexcept(is_nothrow_copy_constructible_v<_Ty>) {
if (_STD addressof(_That) == this) {
return *this;
}
if (_Engaged) {
_Val.~_Ty();
_Engaged = false;
}
if (_That._Engaged) {
_Construct_in_place(_Val, _That._Val);
_Engaged = true;
}
return *this;
}
// clang-format off
_Copyable_box& operator=(_Copyable_box&&) noexcept
requires movable<_Ty> && is_trivially_move_assignable_v<_Ty> = default;
// clang-format on
constexpr _Copyable_box& operator=(_Copyable_box&& _That) noexcept(
is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) // strengthened
requires movable<_Ty> {
if (_Engaged) {
if (_That._Engaged) {
_Val = _STD move(_That._Val);
} else {
_Val.~_Ty();
_Engaged = false;
}
} else {
if (_That._Engaged) {
_Construct_in_place(_Val, _STD move(_That._Val));
_Engaged = true;
} else {
// nothing to do
}
}
return *this;
}
constexpr _Copyable_box& operator=(_Copyable_box&& _That) noexcept(is_nothrow_move_constructible_v<_Ty>) {
if (_STD addressof(_That) == this) {
return *this;
}
if (_Engaged) {
_Val.~_Ty();
_Engaged = false;
}
if (_That._Engaged) {
_Construct_in_place(_Val, _STD move(_That._Val));
_Engaged = true;
}
return *this;
}
constexpr explicit operator bool() const noexcept {
return _Engaged;
}
_NODISCARD constexpr _Ty& operator*() noexcept {
_STL_INTERNAL_CHECK(_Engaged);
return _Val;
}
_NODISCARD constexpr const _Ty& operator*() const noexcept {
_STL_INTERNAL_CHECK(_Engaged);
return _Val;
}
private:
union {
_Nontrivial_dummy_type _Dummy;
_Ty _Val;
};
bool _Engaged;
};
// clang-format off
template <_Copy_constructible_object _Ty>
requires (copyable<_Ty>
|| (is_nothrow_copy_constructible_v<_Ty>
&& (movable<_Ty> || is_nothrow_move_constructible_v<_Ty>)))
class _Copyable_box<_Ty> { // provide the same API more efficiently when we can avoid the disengaged state
// clang-format on
public:
// clang-format off
_Copyable_box() requires default_initializable<_Ty> = default;
// clang-format on
template <class... _Types>
constexpr _Copyable_box(in_place_t, _Types&&... _Args) noexcept(
is_nothrow_constructible_v<_Ty, _Types...>) // strengthened
: _Val(_STD forward<_Types>(_Args)...) {}
_Copyable_box(const _Copyable_box&) = default;
_Copyable_box(_Copyable_box&&) = default;
// clang-format off
_Copyable_box& operator=(const _Copyable_box&) requires copyable<_Ty> = default;
_Copyable_box& operator=(_Copyable_box&&) requires movable<_Ty> = default;
// clang-format on
constexpr _Copyable_box& operator=(const _Copyable_box& _That) noexcept {
if (_STD addressof(_That) != this) {
_Val.~_Ty();
_Construct_in_place(_Val, _That._Val);
}
return *this;
}
constexpr _Copyable_box& operator=(_Copyable_box&& _That) noexcept {
if (_STD addressof(_That) != this) {
_Val.~_Ty();
_Construct_in_place(_Val, _STD move(_That._Val));
}
return *this;
}
constexpr explicit operator bool() const noexcept {
return true;
}
_NODISCARD constexpr _Ty& operator*() noexcept {
return _Val;
}
_NODISCARD constexpr const _Ty& operator*() const noexcept {
return _Val;
}
private:
/* [[no_unique_address]] */ _Ty _Val = _Ty();
};
// CLASS TEMPLATE ranges::_Defaultabox
template <movable _Ty>
class _Defaultabox { // a simplified optional that augments movable types with default-constructibility
public:
constexpr _Defaultabox() noexcept : _Dummy{} {}
// clang-format off
~_Defaultabox() requires is_trivially_destructible_v<_Ty> = default;
// clang-format on
constexpr ~_Defaultabox() {
if (_Engaged) {
_Val.~_Ty();
}
}
// clang-format off
_Defaultabox(const _Defaultabox&)
requires copy_constructible<_Ty> && is_trivially_copy_constructible_v<_Ty> = default;
// clang-format on
constexpr _Defaultabox(const _Defaultabox& _That) requires copy_constructible<_Ty> : _Engaged{_That._Engaged} {
if (_That._Engaged) {
_Construct_in_place(_Val, _That._Val);
}
}
// clang-format off
_Defaultabox(_Defaultabox&&) requires is_trivially_move_constructible_v<_Ty> = default;
// clang-format on
constexpr _Defaultabox(_Defaultabox&& _That) : _Engaged{_That._Engaged} {
if (_That._Engaged) {
_Construct_in_place(_Val, _STD move(_That._Val));
}
}
// clang-format off
_Defaultabox& operator=(const _Defaultabox&) noexcept
requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty> = default;
// clang-format on
constexpr _Defaultabox& operator=(const _Defaultabox& _That) noexcept(
is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_copy_assignable_v<_Ty>) // strengthened
requires copyable<_Ty> {
if (_Engaged) {
if (_That._Engaged) {
_Val = _That._Val;
} else {
_Val.~_Ty();
_Engaged = false;
}
} else {
if (_That._Engaged) {
_Construct_in_place(_Val, _That._Val);
_Engaged = true;
} else {
// nothing to do
}
}
return *this;
}
// clang-format off
_Defaultabox& operator=(_Defaultabox&&) noexcept requires is_trivially_move_assignable_v<_Ty> = default;
// clang-format on
constexpr _Defaultabox& operator=(_Defaultabox&& _That) noexcept(
is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) /* strengthened */ {
if (_Engaged) {
if (_That._Engaged) {
_Val = _STD move(_That._Val);
} else {
_Val.~_Ty();
_Engaged = false;
}
} else {
if (_That._Engaged) {
_Construct_in_place(_Val, _STD move(_That._Val));
_Engaged = true;
} else {
// nothing to do
}
}
return *this;
}
constexpr _Defaultabox& operator=(_Ty&& _That) noexcept(
is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) {
if (_Engaged) {
_Val = _STD move(_That);
} else {
_Construct_in_place(_Val, _STD move(_That));
_Engaged = true;
}
return *this;
}
constexpr _Defaultabox& operator=(const _Ty& _That) noexcept(
is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_copy_assignable_v<_Ty>) requires copyable<_Ty> {
if (_Engaged) {
_Val = _That;
} else {
_Construct_in_place(_Val, _That);
_Engaged = true;
}
return *this;
}
constexpr explicit operator bool() const noexcept {
return _Engaged;
}
_NODISCARD constexpr _Ty& operator*() noexcept {
_STL_INTERNAL_CHECK(_Engaged);
return _Val;
}
_NODISCARD constexpr const _Ty& operator*() const noexcept {
_STL_INTERNAL_CHECK(_Engaged);
return _Val;
}
constexpr void _Reset() noexcept {
if (_Engaged) {
_Val.~_Ty();
_Engaged = false;
}
}
_NODISCARD constexpr bool operator==(const _Defaultabox& _That) const noexcept(noexcept(_Val == _That._Val)) {
_STL_INTERNAL_STATIC_ASSERT(equality_comparable<_Ty>);
return _Engaged == _That._Engaged && (!_Engaged || _Val == _That._Val);
}
private:
union {
_Nontrivial_dummy_type _Dummy;
_Ty _Val;
};
bool _Engaged = false;
};
// clang-format off
template <movable _Ty>
requires default_initializable<_Ty>
class _Defaultabox<_Ty> { // provide the same API more efficiently for default-constructible types
// clang-format on
public:
constexpr _Defaultabox& operator=(const _Ty& _Right) noexcept(
is_nothrow_copy_assignable_v<_Ty>) requires copyable<_Ty> {
_Value = _Right;
return *this;
}
constexpr _Defaultabox& operator=(_Ty&& _Right) noexcept(is_nothrow_move_assignable_v<_Ty>) {
_Value = _STD move(_Right);
return *this;
}
constexpr explicit operator bool() const noexcept {
return true;
}
_NODISCARD constexpr _Ty& operator*() noexcept {
return _Value;
}
_NODISCARD constexpr const _Ty& operator*() const noexcept {
return _Value;
}
constexpr void _Reset() noexcept(noexcept(_Value = _Ty{})) {
_Value = _Ty{};
}
_NODISCARD bool operator==(const _Defaultabox&) const = default;
private:
/* [[no_unique_address]] */ _Ty _Value{};
};
// CLASS TEMPLATE ranges::empty_view
// clang-format off
template <class _Ty>
requires is_object_v<_Ty>
class empty_view : public view_interface<empty_view<_Ty>> {
// clang-format on
public:
_NODISCARD static constexpr _Ty* begin() noexcept {
return nullptr;
}
_NODISCARD static constexpr _Ty* end() noexcept {
return nullptr;
}
_NODISCARD static constexpr _Ty* data() noexcept {
return nullptr;
}
_NODISCARD static constexpr size_t size() noexcept {
return 0;
}
_NODISCARD static constexpr bool empty() noexcept {
return true;
}
};
namespace views {
// VARIABLE TEMPLATE views::empty
template <class _Ty>
inline constexpr empty_view<_Ty> empty;
} // namespace views
// CLASS TEMPLATE ranges::single_view
// clang-format off
template <copy_constructible _Ty>
requires is_object_v<_Ty>
class single_view : public view_interface<single_view<_Ty>> {
// clang-format on
public:
// clang-format off
single_view() requires default_initializable<_Ty> = default;
// clang-format on
constexpr explicit single_view(const _Ty& _Val_) noexcept(is_nothrow_copy_constructible_v<_Ty>) // strengthened
: _Val{in_place, _Val_} {}
constexpr explicit single_view(_Ty&& _Val_) noexcept(is_nothrow_move_constructible_v<_Ty>) // strengthened
: _Val{in_place, _STD move(_Val_)} {}
// clang-format off
template <class... _Types>
requires constructible_from<_Ty, _Types...>
constexpr explicit single_view(in_place_t, _Types&&... _Args) noexcept(
is_nothrow_constructible_v<_Ty, _Types...>) // strengthened
// clang-format on
: _Val{in_place, _STD forward<_Types>(_Args)...} {}
_NODISCARD constexpr _Ty* begin() noexcept {
return data();
}
_NODISCARD constexpr const _Ty* begin() const noexcept {
return data();
}
_NODISCARD constexpr _Ty* end() noexcept {
return data() + 1;
}
_NODISCARD constexpr const _Ty* end() const noexcept {
return data() + 1;
}
_NODISCARD static constexpr size_t size() noexcept {
return 1;
}
_NODISCARD constexpr _Ty* data() noexcept {
return _STD addressof(*_Val);
}
_NODISCARD constexpr const _Ty* data() const noexcept {
return _STD addressof(*_Val);
}
private:
/* [[no_unique_address]] */ _Copyable_box<_Ty> _Val{};
};
namespace views {
// VARIABLE views::single
struct _Single_fn {
// clang-format off
template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(
noexcept(single_view{_STD forward<_Ty>(_Val)})) requires requires {
single_view{static_cast<_Ty&&>(_Val)};
} {
return single_view{_STD forward<_Ty>(_Val)};
}
// clang-format on
};
inline constexpr _Single_fn single;
} // namespace views
// CLASS TEMPLATE ranges::iota_view
template <class _Ty>
using _Iota_diff_t = conditional_t<is_integral_v<_Ty>, conditional_t<(sizeof(_Ty) < sizeof(int)), int, long long>,
iter_difference_t<_Ty>>;
// clang-format off
template <class _Ty>
concept _Decrementable = incrementable<_Ty> && requires(_Ty __t) {
{ --__t } -> same_as<_Ty&>;
{ __t-- } -> same_as<_Ty>;
};
template <class _Ty>
concept _Advanceable = _Decrementable<_Ty> && totally_ordered<_Ty>
&& requires(_Ty __i, const _Ty __j, const _Iota_diff_t<_Ty> __n) {
{ __i += __n } -> same_as<_Ty&>;
{ __i -= __n } -> same_as<_Ty&>;
_Ty(__j + __n);
_Ty(__n + __j);
_Ty(__j - __n);
{ __j - __j } -> convertible_to<_Iota_diff_t<_Ty>>;
};
template <weakly_incrementable _Wi>
requires copyable<_Wi>
struct _Ioterator {
// clang-format on
/* [[no_unique_address]] */ _Wi _Current;
using iterator_concept = conditional_t<_Advanceable<_Wi>, random_access_iterator_tag,
conditional_t<_Decrementable<_Wi>, bidirectional_iterator_tag,
conditional_t<incrementable<_Wi>, forward_iterator_tag, input_iterator_tag>>>;
using iterator_category = input_iterator_tag;
using value_type = _Wi;
using difference_type = _Iota_diff_t<_Wi>;
_NODISCARD constexpr _Wi operator*() const noexcept(is_nothrow_copy_constructible_v<_Wi>) {
return _Current;
}
constexpr _Ioterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ {
++_Current;
return *this;
}
constexpr auto operator++(int) noexcept(
noexcept(++_Current) && (!incrementable<_Wi> || is_nothrow_copy_constructible_v<_Wi>) ) /* strengthened */ {
if constexpr (incrementable<_Wi>) {
auto _Tmp = *this;
++_Current;
return _Tmp;
} else {
++_Current;
}
}
constexpr _Ioterator& operator--() noexcept(
noexcept(--_Current)) /* strengthened */ requires _Decrementable<_Wi> {
--_Current;
return *this;
}
constexpr _Ioterator operator--(int) noexcept(is_nothrow_copy_constructible_v<_Wi>&& noexcept(
--_Current)) /* strengthened */ requires _Decrementable<_Wi> {
auto _Tmp = *this;
--_Current;
return _Tmp;
}
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, DevCom-1347136
private :
template <class _Left, class _Right>
static constexpr bool _Nothrow_plus_equal = noexcept(_STD declval<_Left&>() += _STD declval<const _Right&>());
template <_Integer_like _Left, class _Right>
static constexpr bool _Nothrow_plus_equal<_Left, _Right> = true;
template <class _Left, class _Right>
static constexpr bool _Nothrow_minus_equal = noexcept(_STD declval<_Left&>() -= _STD declval<const _Right&>());
template <_Integer_like _Left, class _Right>
static constexpr bool _Nothrow_minus_equal<_Left, _Right> = true;
public:
#endif // TRANSITION, DevCom-1347136
constexpr _Ioterator& operator+=(const difference_type _Off)
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-1347136
noexcept(noexcept(_Current += _Off)) /* strengthened */
#else // ^^^ no workaround / workaround vvv
noexcept(_Nothrow_plus_equal<_Wi, difference_type>) /* strengthened */
#endif // TRANSITION, DevCom-1347136
requires _Advanceable<_Wi> {
if constexpr (_Integer_like<_Wi>) {
if constexpr (_Signed_integer_like<_Wi>) {
_Current = static_cast<_Wi>(_Current + _Off);
} else {
if (_Off >= difference_type{0}) {
_Current += static_cast<_Wi>(_Off);
} else {
_Current -= static_cast<_Wi>(-_Off);
}
}
} else {
_Current += _Off;
}
return *this;
}
constexpr _Ioterator& operator-=(const difference_type _Off)
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-1347136
noexcept(noexcept(_Current -= _Off)) /* strengthened */
#else // ^^^ no workaround / workaround vvv
noexcept(_Nothrow_minus_equal<_Wi, difference_type>) /* strengthened */
#endif // TRANSITION, DevCom-1347136
requires _Advanceable<_Wi> {
if constexpr (_Integer_like<_Wi>) {
if constexpr (_Signed_integer_like<_Wi>) {
_Current = static_cast<_Wi>(_Current - _Off);
} else {
if (_Off >= difference_type{0}) {
_Current -= static_cast<_Wi>(_Off);
} else {
_Current += static_cast<_Wi>(-_Off);
}
}
} else {
_Current -= _Off;
}
return *this;
}
_NODISCARD constexpr _Wi operator[](const difference_type _Idx) const
noexcept(noexcept(static_cast<_Wi>(_Current + _Idx))) /* strengthened */ requires _Advanceable<_Wi> {
if constexpr (_Integer_like<_Wi>) {
return static_cast<_Wi>(_Current + static_cast<_Wi>(_Idx));
} else {
return static_cast<_Wi>(_Current + _Idx);
}
}
// clang-format off
_NODISCARD friend constexpr bool operator==(
const _Ioterator&, const _Ioterator&) requires equality_comparable<_Wi> = default;
// clang-format on
_NODISCARD friend constexpr bool operator<(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires totally_ordered<_Wi> {
return _Left._Current < _Right._Current;
}
_NODISCARD friend constexpr bool operator>(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(
noexcept(_Right._Current < _Left._Current)) /* strengthened */ requires totally_ordered<_Wi> {
return _Right._Current < _Left._Current;
}
_NODISCARD friend constexpr bool operator<=(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(
noexcept(!(_Right._Current < _Left._Current))) /* strengthened */ requires totally_ordered<_Wi> {
return !(_Right._Current < _Left._Current);
}
_NODISCARD friend constexpr bool operator>=(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(
noexcept(!(_Left._Current < _Right._Current))) /* strengthened */ requires totally_ordered<_Wi> {
return !(_Left._Current < _Right._Current);
}
// clang-format off
_NODISCARD friend constexpr auto operator<=>(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(
noexcept(_Left._Current <=> _Right._Current)) /* strengthened */
requires totally_ordered<_Wi> && three_way_comparable<_Wi> {
// clang-format on
return _Left._Current <=> _Right._Current;
}
_NODISCARD friend constexpr _Ioterator operator+(_Ioterator _It, const difference_type _Off) noexcept(
noexcept(static_cast<_Wi>(_It._Current + _Off))) /* strengthened */ requires _Advanceable<_Wi> {
return _Ioterator{static_cast<_Wi>(_It._Current + _Off)};
}
_NODISCARD friend constexpr _Ioterator operator+(const difference_type _Off, _Ioterator _It) noexcept(
noexcept(static_cast<_Wi>(_It._Current + _Off))) /* strengthened */ requires _Advanceable<_Wi> {
return _Ioterator{static_cast<_Wi>(_It._Current + _Off)};
}
_NODISCARD friend constexpr _Ioterator operator-(_Ioterator _It, const difference_type _Off) noexcept(
noexcept(static_cast<_Wi>(_It._Current - _Off))) /* strengthened */ requires _Advanceable<_Wi> {
return _Ioterator{static_cast<_Wi>(_It._Current - _Off)};
}
_NODISCARD friend constexpr difference_type
operator-(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(
noexcept(_Left._Current - _Right._Current)) /* strengthened */ requires _Advanceable<_Wi> {
return static_cast<difference_type>(_Left._Current - _Right._Current);
}
};
// clang-format off
template <weakly_incrementable _Wi, semiregular _Bo>
requires _Weakly_equality_comparable_with<_Wi, _Bo> && copyable<_Wi>
struct _Iotinel {
// clang-format on
private:
using _It = _Ioterator<_Wi>;
_NODISCARD constexpr bool _Equal(const _It& _That) const noexcept(noexcept(_That._Current == _Last)) {
return _That._Current == _Last;
}
_NODISCARD constexpr iter_difference_t<_Wi> _Delta(const _It& _That) const
noexcept(noexcept(_Last - _That._Current)) {
_STL_INTERNAL_STATIC_ASSERT(sized_sentinel_for<_Bo, _Wi>);
return _Last - _That._Current;
}
public:
/* [[no_unique_address]] */ _Bo _Last{};
_NODISCARD friend constexpr bool operator==(const _It& _Left, const _Iotinel& _Right) noexcept(
noexcept(_Right._Equal(_Left))) /* strengthened */ {
return _Right._Equal(_Left);
}
_NODISCARD friend constexpr iter_difference_t<_Wi> operator-(const _It& _Left, const _Iotinel& _Right) noexcept(
noexcept(_Right._Delta(_Left))) /* strengthened */ requires sized_sentinel_for<_Bo, _Wi> {
return -_Right._Delta(_Left);
}
_NODISCARD friend constexpr iter_difference_t<_Wi> operator-(const _Iotinel& _Left, const _It& _Right) noexcept(
noexcept(_Left._Delta(_Right))) /* strengthened */ requires sized_sentinel_for<_Bo, _Wi> {
return _Left._Delta(_Right);
}
};
// clang-format off
template <weakly_incrementable _Wi, semiregular _Bo = unreachable_sentinel_t>
requires _Weakly_equality_comparable_with<_Wi, _Bo> && copyable<_Wi>
class iota_view : public view_interface<iota_view<_Wi, _Bo>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Wi _Value{};
/* [[no_unique_address]] */ _Bo _Bound{};
using _It = _Ioterator<_Wi>;
using _Se = conditional_t<same_as<_Wi, _Bo>, _It,
conditional_t<same_as<_Bo, unreachable_sentinel_t>, _Bo, _Iotinel<_Wi, _Bo>>>;
_NODISCARD static constexpr _Bo& _Bound_from(_Se& _Last) noexcept {
if constexpr (same_as<_Wi, _Bo>) {
return _Last._Current;
} else if constexpr (same_as<_Bo, unreachable_sentinel_t>) {
return _Last;
} else {
return _Last._Last;
}
}
public:
// clang-format off
iota_view() requires default_initializable<_Wi> = default;
// clang-format on
constexpr explicit iota_view(_Wi _Value_) noexcept(
is_nothrow_move_constructible_v<_Wi>&& is_nothrow_default_constructible_v<_Bo>) // strengthened
: _Value(_STD move(_Value_)) {}
constexpr iota_view(type_identity_t<_Wi> _Value_, type_identity_t<_Bo> _Bound_) noexcept(
is_nothrow_move_constructible_v<_Wi>&& is_nothrow_move_constructible_v<_Bo>) // strengthened
: _Value(_STD move(_Value_)), _Bound(_STD move(_Bound_)) {
if constexpr (totally_ordered_with<_Wi, _Bo>) {
_STL_ASSERT(_Value_ <= _Bound_, "Per N4878 [range.iota.view]/8, the first argument must precede the "
"second when their types are totally ordered.");
}
}
constexpr iota_view(_It _First, _Se _Last) noexcept(
is_nothrow_move_constructible_v<_Wi>&& is_nothrow_move_constructible_v<_Bo>) // strengthened
: _Value(_STD move(_First._Current)), _Bound(_STD move(_Bound_from(_Last))) {}
_NODISCARD constexpr _It begin() const noexcept(is_nothrow_copy_constructible_v<_Wi>) /* strengthened */ {
return _It{_Value};
}
_NODISCARD constexpr _Se end() const noexcept(is_nothrow_copy_constructible_v<_Bo>) /* strengthened */ {
if constexpr (same_as<_Bo, unreachable_sentinel_t>) {
return unreachable_sentinel;
} else {
return _Se{_Bound};
}
}
// clang-format off
_NODISCARD constexpr auto size() const noexcept(noexcept(_Bound - _Value)) /* strengthened */
requires (same_as<_Wi, _Bo> && _Advanceable<_Wi>)
|| (integral<_Wi> && integral<_Bo>)
|| sized_sentinel_for<_Bo, _Wi> {
// clang-format on
if constexpr (_Integer_like<_Wi> && _Integer_like<_Bo>) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
return (_Value < 0) ? ((_Bound < 0) ? (_To_unsigned_like(-_Value) - _To_unsigned_like(-_Bound))
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
: (_To_unsigned_like(_Bound) + _To_unsigned_like(-_Value)))
: (_To_unsigned_like(_Bound) - _To_unsigned_like(_Value));
} else {
return _To_unsigned_like(_Bound - _Value);
}
}
};
// clang-format off
template <class _Wi, class _Bo>
requires (!_Integer_like<_Wi> || !_Integer_like<_Bo>
|| (_Signed_integer_like<_Wi> == _Signed_integer_like<_Bo>))
iota_view(_Wi, _Bo) -> iota_view<_Wi, _Bo>;
// clang-format on
template <class _Wi, class _Bo>
inline constexpr bool enable_borrowed_range<iota_view<_Wi, _Bo>> = true;
namespace views {
// VARIABLE views::iota
struct _Iota_fn {
template <class _Ty>
_NODISCARD constexpr auto operator()(_Ty&& _Val) const
noexcept(noexcept(iota_view{static_cast<_Ty&&>(_Val)})) requires requires {
iota_view{static_cast<_Ty&&>(_Val)};
}
{ return iota_view{static_cast<_Ty&&>(_Val)}; }
template <class _Ty1, class _Ty2>
_NODISCARD constexpr auto operator()(_Ty1&& _Val1, _Ty2&& _Val2) const noexcept(
noexcept(iota_view{static_cast<_Ty1&&>(_Val1), static_cast<_Ty2&&>(_Val2)})) requires requires {
iota_view{static_cast<_Ty1&&>(_Val1), static_cast<_Ty2&&>(_Val2)};
}
{ return iota_view{static_cast<_Ty1&&>(_Val1), static_cast<_Ty2&&>(_Val2)}; }
};
inline constexpr _Iota_fn iota;
} // namespace views
// CLASS TEMPLATE ranges::istream_view
template <class _Ty, class _Elem, class _Traits>
concept _Stream_extractable = requires(basic_istream<_Elem, _Traits>& __is, _Ty& __t) {
__is >> __t;
};
// clang-format off
template <movable _Ty, class _Elem, class _Traits = char_traits<_Elem>>
requires default_initializable<_Ty> && _Stream_extractable<_Ty, _Elem, _Traits>
class basic_istream_view : public view_interface<basic_istream_view<_Ty, _Elem, _Traits>> {
// clang-format on
private:
class _Iterator {
private:
basic_istream_view* _Parent;
public:
using iterator_concept = input_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = _Ty;
constexpr explicit _Iterator(basic_istream_view& _Parent_) noexcept : _Parent{_STD addressof(_Parent_)} {}
_Iterator(const _Iterator&) = delete;
_Iterator(_Iterator&&) = default;
_Iterator& operator=(const _Iterator&) = delete;
_Iterator& operator=(_Iterator&&) = default;
_Iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
// Per LWG-3489
_STL_VERIFY(!_Parent->_Stream_at_end(), "cannot increment istream_view iterator at end of stream");
#endif // _ITERATOR_DEBUG_LEVEL != 0
*_Parent->_Stream >> _Parent->_Val;
return *this;
}
void operator++(int) {
++*this;
}
_NODISCARD _Ty& operator*() const noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
// Per LWG-3489
_STL_VERIFY(!_Parent->_Stream_at_end(), "cannot dereference istream_view iterator at end of stream");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Parent->_Val;
}
_NODISCARD friend bool operator==(const _Iterator& _Left, default_sentinel_t) noexcept /* strengthened */ {
return _Left._Parent->_Stream_at_end();
}
};
basic_istream<_Elem, _Traits>* _Stream;
_Ty _Val = _Ty{}; // Per LWG issue submitted but unnumbered as of 2021-06-15
public:
constexpr explicit basic_istream_view(basic_istream<_Elem, _Traits>& _Stream_) noexcept(
is_nothrow_default_constructible_v<_Ty>) // strengthened
: _Stream{_STD addressof(_Stream_)} {}
_NODISCARD constexpr auto begin() {
*_Stream >> _Val;
return _Iterator{*this};
}
_NODISCARD constexpr default_sentinel_t end() const noexcept {
return default_sentinel;
}
_NODISCARD constexpr bool _Stream_at_end() const noexcept {
return !*_Stream;
}
};
template <class _Ty, class _Elem, class _Traits>
_NODISCARD basic_istream_view<_Ty, _Elem, _Traits> istream_view(basic_istream<_Elem, _Traits>& _Stream) noexcept(
is_nothrow_default_constructible_v<_Ty>) /* strengthened */ {
return basic_istream_view<_Ty, _Elem, _Traits>{_Stream};
}
// CLASS TEMPLATE ranges::ref_view
// clang-format off
template <range _Rng>
requires is_object_v<_Rng>
class ref_view : public view_interface<ref_view<_Rng>> {
// clang-format on
private:
_Rng* _Range;
static void _Rvalue_poison(_Rng&);
static void _Rvalue_poison(_Rng&&) = delete;
public:
// clang-format off
template <_Not_same_as<ref_view> _OtherRng>
constexpr ref_view(_OtherRng&& _Other) noexcept(
noexcept(static_cast<_Rng&>(_STD forward<_OtherRng>(_Other)))) // strengthened
requires convertible_to<_OtherRng, _Rng&> && requires {
_Rvalue_poison(static_cast<_OtherRng&&>(_Other));
} : _Range{_STD addressof(static_cast<_Rng&>(_STD forward<_OtherRng>(_Other)))} {}
// clang-format on
_NODISCARD constexpr _Rng& base() const noexcept /* strengthened */ {
return *_Range;
}
_NODISCARD constexpr iterator_t<_Rng> begin() const
noexcept(noexcept(_RANGES begin(*_Range))) /* strengthened */ {
return _RANGES begin(*_Range);
}
_NODISCARD constexpr sentinel_t<_Rng> end() const noexcept(noexcept(_RANGES end(*_Range))) /* strengthened */ {
return _RANGES end(*_Range);
}
_NODISCARD constexpr bool empty() const noexcept(noexcept(_RANGES empty(*_Range))) /* strengthened */
requires _Can_empty<_Rng> {
return _RANGES empty(*_Range);
}
_NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(*_Range))) /* strengthened */
requires sized_range<_Rng> {
return _RANGES size(*_Range);
}
_NODISCARD constexpr auto data() const noexcept(noexcept(_RANGES data(*_Range))) /* strengthened */
requires contiguous_range<_Rng> {
return _RANGES data(*_Range);
}
};
template <class _Rng>
ref_view(_Rng&) -> ref_view<_Rng>;
template <class _Rng>
inline constexpr bool enable_borrowed_range<ref_view<_Rng>> = true;
namespace views {
// VARIABLE views::all
template <class _Rng>
concept _Can_ref_view = requires(_Rng&& __r) {
ref_view{static_cast<_Rng&&>(__r)};
};
template <class _Rng>
concept _Can_subrange = requires(_Rng&& __r) {
subrange{static_cast<_Rng&&>(__r)};
};
class _All_fn : public _Pipe::_Base<_All_fn> {
private:
enum class _St { _None, _View, _Ref, _Subrange };
template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (view<remove_cvref_t<_Rng>>) {
if constexpr (constructible_from<remove_cvref_t<_Rng>, _Rng>) {
return {_St::_View, is_nothrow_constructible_v<remove_cvref_t<_Rng>, _Rng>};
}
} else if constexpr (_Can_ref_view<_Rng>) {
return {_St::_Ref, noexcept(ref_view{_STD declval<_Rng>()})};
} else if constexpr (_Can_subrange<_Rng>) {
return {_St::_Subrange, noexcept(subrange{_STD declval<_Rng>()})};
}
return {_St::_None};
}
template <class _Rng>
static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>();
public:
// clang-format off
template <viewable_range _Rng>
requires (_Choice<_Rng>._Strategy != _St::_None)
_NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) {
// clang-format on
constexpr _St _Strat = _Choice<_Rng>._Strategy;
if constexpr (_Strat == _St::_View) {
return _STD forward<_Rng>(_Range);
} else if constexpr (_Strat == _St::_Ref) {
return ref_view{_STD forward<_Rng>(_Range)};
} else if constexpr (_Strat == _St::_Subrange) {
return subrange{_STD forward<_Rng>(_Range)};
} else {
static_assert(_Always_false<_Rng>, "Should be unreachable");
}
}
};
inline constexpr _All_fn all;
// ALIAS TEMPLATE views::all_t
template <viewable_range _Rng>
using all_t = decltype(all(_STD declval<_Rng>()));
} // namespace views
// CLASS TEMPLATE ranges::filter_view
// clang-format off
template <input_range _Vw, indirect_unary_predicate<iterator_t<_Vw>> _Pr>
requires view<_Vw> && is_object_v<_Pr>
class filter_view : public _Cached_position_t<forward_range<_Vw>, _Vw, filter_view<_Vw, _Pr>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
/* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred{};
template <class _Traits> // TRANSITION, LWG-3289
struct _Category_base {};
// clang-format off
template <_Has_member_iterator_category _Traits>
struct _Category_base<_Traits> {
// clang-format on
using iterator_category =
conditional_t<derived_from<typename _Traits::iterator_category, bidirectional_iterator_tag>,
bidirectional_iterator_tag,
conditional_t<derived_from<typename _Traits::iterator_category, forward_iterator_tag>,
forward_iterator_tag, input_iterator_tag>>;
};
class _Iterator : public _Category_base<iterator_traits<iterator_t<_Vw>>> {
private:
/* [[no_unique_address]] */ iterator_t<_Vw> _Current{};
filter_view* _Parent{};
#if _ITERATOR_DEBUG_LEVEL != 0
constexpr void _Check_dereference() const noexcept {
_STL_VERIFY(_Parent != nullptr, "cannot dereference value-initialized filter_view iterator");
_STL_VERIFY(_Current != _RANGES end(_Parent->_Range), "cannot dereference end filter_view iterator");
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
public:
using iterator_concept = conditional_t<bidirectional_range<_Vw>, bidirectional_iterator_tag,
conditional_t<forward_range<_Vw>, forward_iterator_tag, input_iterator_tag>>;
using value_type = range_value_t<_Vw>;
using difference_type = range_difference_t<_Vw>;
// clang-format off
_Iterator() requires default_initializable<iterator_t<_Vw>> = default;
// clang-format on
constexpr _Iterator(filter_view& _Parent_, iterator_t<_Vw> _Current_) noexcept(
is_nothrow_move_constructible_v<iterator_t<_Vw>>) // strengthened
: _Current(_STD move(_Current_)), _Parent{_STD addressof(_Parent_)} {
#if _ITERATOR_DEBUG_LEVEL != 0
_Adl_verify_range(_Current, _RANGES end(_Parent_._Range));
if constexpr (forward_range<_Vw>) {
_Adl_verify_range(_RANGES begin(_Parent_._Range), _Current);
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
}
_NODISCARD constexpr iterator_t<_Vw> base() const& noexcept(
is_nothrow_copy_constructible_v<iterator_t<_Vw>>) // strengthened
requires copyable<iterator_t<_Vw>> {
return _Current;
}
_NODISCARD constexpr iterator_t<_Vw> base() && noexcept(
is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */ {
return _STD move(_Current);
}
_NODISCARD constexpr range_reference_t<_Vw> operator*() const
noexcept(noexcept(*_Current)) /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
_Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
return *_Current;
}
// clang-format off
_NODISCARD constexpr iterator_t<_Vw> operator->() const
noexcept(is_nothrow_copy_constructible_v<iterator_t<_Vw>>) /* strengthened */
requires _Has_arrow<iterator_t<_Vw>> && copyable<iterator_t<_Vw>> {
// clang-format on
#if _ITERATOR_DEBUG_LEVEL != 0
_Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Current;
}
constexpr _Iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Parent != nullptr, "cannot increment value-initialized filter_view iterator");
_STL_VERIFY(_Current != _RANGES end(_Parent->_Range), "cannot increment filter_view iterator past end");
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current =
_RANGES find_if(_STD move(++_Current), _RANGES end(_Parent->_Range), _STD ref(*_Parent->_Pred));
return *this;
}
constexpr decltype(auto) operator++(int) {
if constexpr (forward_range<_Vw>) {
auto _Tmp = *this;
++*this;
return _Tmp;
} else {
++*this;
}
}
constexpr _Iterator& operator--() requires bidirectional_range<_Vw> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Parent != nullptr, "cannot decrement value-initialized filter_view iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
do {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Current != _RANGES begin(_Parent->_Range),
"cannot decrement filter_view iterator before begin");
#endif // _ITERATOR_DEBUG_LEVEL != 0
--_Current;
} while (!_STD invoke(*_Parent->_Pred, *_Current));
return *this;
}
constexpr _Iterator operator--(int) requires bidirectional_range<_Vw> {
auto _Tmp = *this;
--*this;
return _Tmp;
}
_NODISCARD friend constexpr bool operator==(
const _Iterator& _Left, const _Iterator& _Right) requires equality_comparable<iterator_t<_Vw>> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(
_Left._Parent == _Right._Parent, "cannot compare incompatible filter_view iterators for equality");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current == _Right._Current;
}
_NODISCARD friend constexpr range_rvalue_reference_t<_Vw> iter_move(const _Iterator& _It) noexcept(
noexcept(_RANGES iter_move(_It._Current))) {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _RANGES iter_move(_It._Current);
}
friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) noexcept(noexcept(
_RANGES iter_swap(_Left._Current, _Right._Current))) requires indirectly_swappable<iterator_t<_Vw>> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Check_dereference();
_Right._Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _RANGES iter_swap(_Left._Current, _Right._Current);
}
_NODISCARD constexpr bool _Equal(const sentinel_t<_Vw>& _Last) const {
return _Current == _Last;
}
};
class _Sentinel {
private:
/* [[no_unique_address]] */ sentinel_t<_Vw> _Last{};
public:
_Sentinel() = default;
constexpr explicit _Sentinel(filter_view& _Parent) noexcept(
noexcept(_RANGES end(_Parent._Range))
&& is_nothrow_move_constructible_v<sentinel_t<_Vw>>) // strengthened
: _Last(_RANGES end(_Parent._Range)) {}
_NODISCARD constexpr sentinel_t<_Vw> base() const
noexcept(is_nothrow_copy_constructible_v<sentinel_t<_Vw>>) /* strengthened */ {
return _Last;
}
_NODISCARD friend constexpr bool operator==(const _Iterator& _It, const _Sentinel& _Se) {
return _It._Equal(_Se._Last);
}
};
public:
// clang-format off
filter_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default;
// clang-format on
constexpr filter_view(_Vw _Range_, _Pr _Pred_) noexcept(
is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened
: _Range(_STD move(_Range_)), _Pred{in_place, _STD move(_Pred_)} {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
_NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pred, "filter_view has no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return *_Pred;
}
_NODISCARD constexpr _Iterator begin() {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(
_Pred, "N4861 [range.filter.view]/3 forbids calling begin on a filter_view that holds no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
if constexpr (forward_range<_Vw>) {
if (this->_Has_cache()) {
return _Iterator{*this, this->_Get_cache(_Range)};
}
}
auto _First = _RANGES find_if(_Range, _STD ref(*_Pred));
if constexpr (forward_range<_Vw>) {
this->_Set_cache(_Range, _First);
}
return _Iterator{*this, _STD move(_First)};
}
_NODISCARD constexpr auto end() {
if constexpr (common_range<_Vw>) {
return _Iterator{*this, _RANGES end(_Range)};
} else {
return _Sentinel{*this};
}
}
};
template <class _Rng, class _Pr>
filter_view(_Rng&&, _Pr) -> filter_view<views::all_t<_Rng>, _Pr>;
namespace views {
// VARIABLE views::filter
class _Filter_fn {
private:
template <class _Pr>
struct _Partial : _Pipe::_Base<_Partial<_Pr>> {
/* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred;
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept(
noexcept(filter_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires {
filter_view{static_cast<_Rng&&>(_Range), *_Pred};
}
{ return filter_view{_STD forward<_Rng>(_Range), *_Pred}; }
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(
noexcept(filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires {
filter_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)};
}
{ return filter_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; }
};
public:
// clang-format off
template <viewable_range _Rng, class _Pr>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const noexcept(noexcept(
filter_view{_STD forward<_Rng>(_Range), _STD move(_Pred)})) requires requires {
filter_view{static_cast<_Rng&&>(_Range), _STD move(_Pred)};
} {
// clang-format on
return filter_view{_STD forward<_Rng>(_Range), _STD move(_Pred)};
}
template <_Copy_constructible_object _Pr>
_NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) {
return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}};
}
};
inline constexpr _Filter_fn filter;
} // namespace views
// CLASS TEMPLATE ranges::transform_view
// clang-format off
template <class _Rng, class _Fn> // TRANSITION, LLVM-47414
concept _Can_const_transform = range<const _Rng> && regular_invocable<const _Fn&, range_reference_t<const _Rng>>;
#if _ITERATOR_DEBUG_LEVEL == 0
#define _NOEXCEPT_IDL0(...) noexcept(__VA_ARGS__)
#else
#define _NOEXCEPT_IDL0(...)
#endif // _ITERATOR_DEBUG_LEVEL == 0
template <input_range _Vw, copy_constructible _Fn>
requires view<_Vw> && is_object_v<_Fn>
&& regular_invocable<_Fn&, range_reference_t<_Vw>>
&& _Can_reference<invoke_result_t<_Fn&, range_reference_t<_Vw>>>
class transform_view : public view_interface<transform_view<_Vw, _Fn>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
/* [[no_unique_address]] */ _Copyable_box<_Fn> _Fun{};
template <bool _Const>
class _Sentinel;
template <class _Traits, class _Base> // TRANSITION, LWG-3289
struct _Category_base {};
// clang-format off
template <_Has_member_iterator_category _Traits, class _Base>
struct _Category_base<_Traits, _Base> {
// clang-format on
using iterator_category =
conditional_t<is_lvalue_reference_v<invoke_result_t<_Fn&, range_reference_t<_Base>>>,
conditional_t<derived_from<typename _Traits::iterator_category, contiguous_iterator_tag>,
random_access_iterator_tag, typename _Traits::iterator_category>,
input_iterator_tag>;
};
template <bool _Const>
class _Iterator : public _Category_base<iterator_traits<iterator_t<_Vw>>, _Maybe_const<_Const, _Vw>> {
private:
template <bool>
friend class _Iterator;
template <bool>
friend class _Sentinel;
using _Parent_t = _Maybe_const<_Const, transform_view>;
using _Base = _Maybe_const<_Const, _Vw>;
iterator_t<_Base> _Current{};
_Parent_t* _Parent{};
#if _ITERATOR_DEBUG_LEVEL != 0
constexpr void _Check_dereference() const {
_STL_VERIFY(_Parent != nullptr, "cannot dereference value-initialized transform_view iterator");
_STL_VERIFY(_Current != _RANGES end(_Parent->_Range), "cannot dereference end transform_view iterator");
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
#if _ITERATOR_DEBUG_LEVEL != 0
constexpr void _Same_range(const _Iterator& _Right) const noexcept {
_STL_VERIFY(_Parent == _Right._Parent, "cannot compare incompatible transform_view iterators");
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
public:
using iterator_concept = conditional_t<random_access_range<_Base>, random_access_iterator_tag,
conditional_t<bidirectional_range<_Base>, bidirectional_iterator_tag,
conditional_t<forward_range<_Base>, forward_iterator_tag, input_iterator_tag>>>;
using value_type = remove_cvref_t<invoke_result_t<_Fn&, range_reference_t<_Base>>>;
using difference_type = range_difference_t<_Base>;
// clang-format off
_Iterator() requires default_initializable<iterator_t<_Base>> = default;
// clang-format on
constexpr _Iterator(_Parent_t& _Parent_, iterator_t<_Base> _Current_) noexcept(
is_nothrow_move_constructible_v<iterator_t<_Base>>) // strengthened
: _Current{_STD move(_Current_)}, _Parent{_STD addressof(_Parent_)} {
#if _ITERATOR_DEBUG_LEVEL != 0
_Adl_verify_range(_Current, _RANGES end(_Parent_._Range));
if constexpr (forward_range<_Base>) {
_Adl_verify_range(_RANGES begin(_Parent_._Range), _Current);
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
}
// clang-format off
constexpr _Iterator(_Iterator<!_Const> _It)
noexcept(is_nothrow_constructible_v<iterator_t<_Base>, iterator_t<_Vw>>) // strengthened
requires _Const && convertible_to<iterator_t<_Vw>, iterator_t<_Base>>
: _Current{_STD move(_It._Current)}, _Parent{_It._Parent} {}
// clang-format on
_NODISCARD constexpr iterator_t<_Base> base() const& noexcept(
is_nothrow_copy_constructible_v<iterator_t<_Base>>) // strengthened
requires copyable<iterator_t<_Base>> {
return _Current;
}
_NODISCARD constexpr iterator_t<_Base> base() && noexcept(
is_nothrow_move_constructible_v<iterator_t<_Base>>) /* strengthened */ {
return _STD move(_Current);
}
_NODISCARD constexpr decltype(auto) operator*() const
_NOEXCEPT_IDL0(noexcept(_STD invoke(*_Parent->_Fun, *_Current))) /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
_Check_dereference();
_STL_VERIFY(
_Parent->_Fun, "Cannot dereference iterator into transform_view with no transformation function");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _STD invoke(*_Parent->_Fun, *_Current);
}
constexpr _Iterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Parent != nullptr, "Cannot increment value-initialized transform_view iterator");
_STL_VERIFY(
_Current != _RANGES end(_Parent->_Range), "Cannot increment transform_view iterator past end");
#endif // _ITERATOR_DEBUG_LEVEL != 0
++_Current;
return *this;
}
constexpr decltype(auto) operator++(int) noexcept(
noexcept(++_Current)
&& (!forward_range<_Base> || is_nothrow_copy_constructible_v<iterator_t<_Base>>) ) /* strengthened */ {
if constexpr (forward_range<_Base>) {
auto _Tmp = *this;
++*this;
return _Tmp;
} else {
++*this;
}
}
constexpr _Iterator& operator--() noexcept(
noexcept(--_Current)) /* strengthened */ requires bidirectional_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Parent != nullptr, "Cannot decrement value-initialized transform_view iterator");
if constexpr (forward_range<_Vw>) {
_STL_VERIFY(_Current != _RANGES begin(_Parent->_Range),
"Cannot decrement transform_view iterator before begin");
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
--_Current;
return *this;
}
constexpr _Iterator operator--(int) noexcept(
noexcept(--_Current) && is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires bidirectional_range<_Base> {
auto _Tmp = *this;
--*this;
return _Tmp;
}
constexpr void _Verify_offset(const difference_type _Off) const requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL == 0
(void) _Off;
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv
_STL_VERIFY(_Off == 0 || _Parent, "cannot seek value-initialized transform_view iterator");
if constexpr (_Offset_verifiable_v<iterator_t<_Base>>) {
_Current._Verify_offset(_Off);
} else {
if (_Off < 0) {
if constexpr (sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>) {
_STL_VERIFY(_Off >= _RANGES begin(_Parent->_Range) - _Current,
"cannot seek transform_view iterator before begin");
}
} else if (_Off > 0) {
if constexpr (sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>) {
_STL_VERIFY(_Off <= _RANGES end(_Parent->_Range) - _Current,
"cannot seek transform_view iterator after end");
} else if constexpr (sized_sentinel_for<iterator_t<_Base>,
iterator_t<_Base>> && sized_range<_Base>) {
const auto _Size = _RANGES distance(_Parent->_Range);
_STL_VERIFY(_Off <= _Size - (_Current - _RANGES begin(_Parent->_Range)),
"cannot seek transform_view iterator after end");
}
}
}
#endif // _ITERATOR_DEBUG_LEVEL == 0
}
constexpr _Iterator& operator+=(const difference_type _Off)
_NOEXCEPT_IDL0(noexcept(_Current += _Off)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current += _Off;
return *this;
}
constexpr _Iterator& operator-=(const difference_type _Off)
_NOEXCEPT_IDL0(noexcept(_Current -= _Off)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(-_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current -= _Off;
return *this;
}
_NODISCARD constexpr decltype(auto) operator[](const difference_type _Idx) const
_NOEXCEPT_IDL0(noexcept(_STD invoke(*_Parent->_Fun, _Current[_Idx]))) /* strengthened */
requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Idx);
_STL_VERIFY(
_Parent->_Fun, "Cannot dereference iterator into transform_view with no transformation function");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _STD invoke(*_Parent->_Fun, _Current[_Idx]);
}
_NODISCARD friend constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current
== _Right._Current)) /* strengthened */ requires equality_comparable<iterator_t<_Base>> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current == _Right._Current;
}
_NODISCARD friend constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current < _Right._Current;
}
_NODISCARD friend constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
return _Right < _Left;
}
_NODISCARD friend constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
return !(_Right < _Left);
}
_NODISCARD friend constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
return !(_Left < _Right);
}
// clang-format off
_NODISCARD friend constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current <=> _Right._Current)) /* strengthened */
requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> {
// clang-format on
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current <=> _Right._Current;
}
_NODISCARD friend constexpr _Iterator operator+(_Iterator _It, difference_type _Off)
_NOEXCEPT_IDL0(noexcept(_It._Current += _Off)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Verify_offset(_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_It._Current += _Off;
return _It;
}
_NODISCARD friend constexpr _Iterator operator+(difference_type _Off, _Iterator _It)
_NOEXCEPT_IDL0(noexcept(_It._Current += _Off)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Verify_offset(_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_It._Current += _Off;
return _It;
}
_NODISCARD friend constexpr _Iterator operator-(_Iterator _It, difference_type _Off)
_NOEXCEPT_IDL0(noexcept(_It._Current -= _Off)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Verify_offset(-_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_It._Current -= _Off;
return _It;
}
_NODISCARD friend constexpr difference_type operator-(const _Iterator& _Left,
const _Iterator& _Right) noexcept(noexcept(_Left._Current - _Right._Current)) /* strengthened */
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current - _Right._Current;
}
_NODISCARD friend constexpr decltype(auto) iter_move(const _Iterator& _It) noexcept(noexcept(*_It)) {
if constexpr (is_lvalue_reference_v<decltype(*_It)>) {
return _STD move(*_It);
} else {
return *_It;
}
}
friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) _NOEXCEPT_IDL0(noexcept(
_RANGES iter_swap(_Left._Current, _Right._Current))) requires indirectly_swappable<iterator_t<_Base>> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Check_dereference();
_Right._Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
_RANGES iter_swap(_Left._Current, _Right._Current);
}
};
template <bool _Const>
class _Sentinel {
private:
template <bool>
friend class _Sentinel;
using _Parent_t = _Maybe_const<_Const, transform_view>;
using _Base = _Maybe_const<_Const, _Vw>;
template <bool _OtherConst>
using _Maybe_const_iter = iterator_t<_Maybe_const<_OtherConst, _Vw>>;
sentinel_t<_Base> _Last{};
template <bool _OtherConst>
_NODISCARD static constexpr const _Maybe_const_iter<_OtherConst>& _Get_current(
const _Iterator<_OtherConst>& _It) noexcept {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(
_It._Parent != nullptr, "cannot compare transform_view sentinel with value-initialized iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _It._Current;
}
public:
_Sentinel() = default;
constexpr explicit _Sentinel(sentinel_t<_Base> _Last_) noexcept(
is_nothrow_move_constructible_v<sentinel_t<_Base>>) // strengthened
: _Last(_STD move(_Last_)) {}
// clang-format off
constexpr _Sentinel(_Sentinel<!_Const> _Se)
noexcept(is_nothrow_constructible_v<sentinel_t<_Base>, sentinel_t<_Vw>>) // strengthened
requires _Const && convertible_to<sentinel_t<_Vw>, sentinel_t<_Base>>
: _Last(_STD move(_Se._Last)) {}
// clang-format on
_NODISCARD constexpr sentinel_t<_Base> base() const
noexcept(is_nothrow_copy_constructible_v<sentinel_t<_Base>>) /* strengthened */ {
return _Last;
}
// clang-format off
template <bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr bool operator==(const _Iterator<_OtherConst>& _Left,
const _Sentinel& _Right) noexcept(noexcept(_Get_current(_Left) == _Right._Last)) /* strengthened */ {
return _Get_current(_Left) == _Right._Last;
}
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>>
operator-(const _Iterator<_OtherConst>& _Left, const _Sentinel& _Right) noexcept(
noexcept(_Get_current(_Left) - _Right._Last)) /* strengthened */ {
return _Get_current(_Left) - _Right._Last;
}
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>>
operator-(const _Sentinel& _Left, const _Iterator<_OtherConst>& _Right) noexcept(
noexcept(_Left._Last - _Get_current(_Right))) /* strengthened */ {
return _Left._Last - _Get_current(_Right);
}
};
public:
transform_view() requires default_initializable<_Vw> && default_initializable<_Fn> = default;
// clang-format on
constexpr transform_view(_Vw _Range_, _Fn _Fun_) noexcept(
is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Fn>) // strengthened
: _Range(_STD move(_Range_)), _Fun{in_place, _STD move(_Fun_)} {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
_NODISCARD constexpr _Iterator<false> begin() noexcept(
noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */ {
return _Iterator<false>{*this, _RANGES begin(_Range)};
}
// clang-format off
_NODISCARD constexpr _Iterator<true> begin() const noexcept(noexcept(
_RANGES begin(_Range)) && is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */
#ifdef __clang__ // TRANSITION, LLVM-47414
requires _Can_const_transform<_Vw, _Fn>
#else // ^^^ workaround / no workaround vvv
requires range<const _Vw> && regular_invocable<const _Fn&, range_reference_t<const _Vw>>
#endif // TRANSITION, LLVM-47414
{
// clang-format on
return _Iterator<true>{*this, _RANGES begin(_Range)};
}
// clang-format off
_NODISCARD constexpr auto end() noexcept(noexcept(
_RANGES end(_Range)) && is_nothrow_move_constructible_v<decltype(_RANGES end(_Range))>) /* strengthened */ {
// clang-format on
if constexpr (common_range<_Vw>) {
return _Iterator<false>{*this, _RANGES end(_Range)};
} else {
return _Sentinel<false>{_RANGES end(_Range)};
}
}
// clang-format off
_NODISCARD constexpr auto end() const noexcept(noexcept(
_RANGES end(_Range)) && is_nothrow_move_constructible_v<decltype(_RANGES end(_Range))>) /* strengthened */
#ifdef __clang__ // TRANSITION, LLVM-47414
requires _Can_const_transform<_Vw, _Fn>
#else // ^^^ workaround / no workaround vvv
requires range<const _Vw> && regular_invocable<const _Fn&, range_reference_t<const _Vw>>
#endif // TRANSITION, LLVM-47414
{
// clang-format on
if constexpr (common_range<_Vw>) {
return _Iterator<true>{*this, _RANGES end(_Range)};
} else {
return _Sentinel<true>{_RANGES end(_Range)};
}
}
_NODISCARD constexpr auto size() noexcept(
noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range<_Vw> {
return _RANGES size(_Range);
}
_NODISCARD constexpr auto size() const
noexcept(noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range<const _Vw> {
return _RANGES size(_Range);
}
};
#undef _NOEXCEPT_IDL0
template <class _Rng, class _Fn>
transform_view(_Rng&&, _Fn) -> transform_view<views::all_t<_Rng>, _Fn>;
namespace views {
// VARIABLE views::transform
class _Transform_fn {
private:
template <class _Fn>
struct _Partial : _Pipe::_Base<_Partial<_Fn>> {
/* [[no_unique_address]] */ _Copyable_box<_Fn> _Fun;
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept(
noexcept(transform_view{_STD forward<_Rng>(_Range), *_Fun})) requires requires {
transform_view{static_cast<_Rng&&>(_Range), *_Fun};
}
{ return transform_view{_STD forward<_Rng>(_Range), *_Fun}; }
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(
noexcept(transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)})) requires requires {
transform_view{static_cast<_Rng&&>(_Range), _STD move(*_Fun)};
}
{ return transform_view{_STD forward<_Rng>(_Range), _STD move(*_Fun)}; }
};
public:
// clang-format off
template <viewable_range _Rng, class _Fn>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Fn _Fun) const noexcept(noexcept(
transform_view{_STD forward<_Rng>(_Range), _STD move(_Fun)})) requires requires {
transform_view{static_cast<_Rng&&>(_Range), _STD move(_Fun)};
} {
// clang-format on
return transform_view{_STD forward<_Rng>(_Range), _STD move(_Fun)};
}
template <_Copy_constructible_object _Fn>
_NODISCARD constexpr auto operator()(_Fn _Fun) const noexcept(is_nothrow_move_constructible_v<_Fn>) {
return _Partial<_Fn>{._Fun = {in_place, _STD move(_Fun)}};
}
};
inline constexpr _Transform_fn transform;
} // namespace views
// CLASS TEMPLATE ranges::take_view
template <view _Vw>
class take_view : public view_interface<take_view<_Vw>> {
private:
/* [[no_unique_address]] */ _Vw _Range{};
range_difference_t<_Vw> _Count = 0;
template <bool _Const, bool _Wrapped = true>
class _Sentinel {
private:
template <bool, bool>
friend class _Sentinel;
using _Base_t = _Maybe_const<_Const, _Vw>;
using _Base_sentinel = _Maybe_wrapped<_Wrapped, sentinel_t<_Base_t>>;
template <bool _OtherConst>
using _Base_iterator = _Maybe_wrapped<_Wrapped, iterator_t<_Maybe_const<_OtherConst, _Vw>>>;
template <bool _OtherConst>
using _Counted_iter = counted_iterator<_Base_iterator<_OtherConst>>;
_Base_sentinel _Last{};
public:
_Sentinel() = default;
constexpr explicit _Sentinel(_Base_sentinel _Last_) noexcept(
is_nothrow_move_constructible_v<_Base_sentinel>) // strengthened
: _Last(_STD move(_Last_)) {}
// clang-format off
constexpr _Sentinel(_Sentinel<!_Const, _Wrapped> _That) noexcept(
is_nothrow_constructible_v<_Base_sentinel, _Maybe_wrapped<_Wrapped, sentinel_t<_Vw>>>) // strengthened
requires _Const && convertible_to<_Maybe_wrapped<_Wrapped, sentinel_t<_Vw>>, _Base_sentinel>
: _Last(_STD move(_That._Last)) {}
// clang-format on
_NODISCARD constexpr _Base_sentinel base() const
noexcept(is_nothrow_copy_constructible_v<_Base_sentinel>) /* strengthened */ {
return _Last;
}
_NODISCARD friend constexpr bool operator==(const _Counted_iter<_Const>& _Left, const _Sentinel& _Right) {
return _Left.count() == 0 || _Left.base() == _Right._Last;
}
// clang-format off
template <bool _OtherConst = !_Const>
requires sentinel_for<_Base_sentinel, _Base_iterator<_OtherConst>>
_NODISCARD friend constexpr bool operator==(
const _Counted_iter<_OtherConst>& _Left, const _Sentinel& _Right) {
// clang-format on
return _Left.count() == 0 || _Left.base() == _Right._Last;
}
using _Prevent_inheriting_unwrap = _Sentinel;
// clang-format off
_NODISCARD constexpr auto _Unwrapped() const&
requires _Wrapped && _Unwrappable_v<const iterator_t<_Base_t>&> {
// clang-format on
return _Sentinel<_Const, false>{_Get_unwrapped(_Last)};
}
// clang-format off
_NODISCARD constexpr auto _Unwrapped() && requires _Wrapped && _Unwrappable_v<iterator_t<_Base_t>> {
// clang-format on
return _Sentinel<_Const, false>{_Get_unwrapped(_STD move(_Last))};
}
static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v<iterator_t<_Base_t>>;
constexpr void _Seek_to(const _Sentinel<_Const, false>& _That) requires _Wrapped {
_Seek_wrapped(_Last, _That._Last);
}
constexpr void _Seek_to(_Sentinel<_Const, false>&& _That) requires _Wrapped {
_Seek_wrapped(_Last, _STD move(_That._Last));
}
};
public:
// clang-format off
take_view() requires default_initializable<_Vw> = default;
// clang-format on
constexpr take_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept(
is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Range(_STD move(_Range_)), _Count{_Count_} {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
// clang-format off
_NODISCARD constexpr auto begin() requires (!_Simple_view<_Vw>) {
// clang-format on
if constexpr (sized_range<_Vw>) {
if constexpr (random_access_range<_Vw>) {
return _RANGES begin(_Range);
} else {
const auto _Size = static_cast<range_difference_t<_Vw>>(size());
return counted_iterator{_RANGES begin(_Range), _Size};
}
} else {
return counted_iterator{_RANGES begin(_Range), _Count};
}
}
_NODISCARD constexpr auto begin() const requires range<const _Vw> {
if constexpr (sized_range<const _Vw>) {
if constexpr (random_access_range<const _Vw>) {
return _RANGES begin(_Range);
} else {
const auto _Size = static_cast<range_difference_t<_Vw>>(size());
return counted_iterator{_RANGES begin(_Range), _Size};
}
} else {
return counted_iterator{_RANGES begin(_Range), _Count};
}
}
// clang-format off
_NODISCARD constexpr auto end() requires (!_Simple_view<_Vw>) {
// clang-format on
if constexpr (sized_range<_Vw>) {
if constexpr (random_access_range<_Vw>) {
return _RANGES begin(_Range) + static_cast<range_difference_t<_Vw>>(size());
} else {
return default_sentinel;
}
} else {
return _Sentinel<false>{_RANGES end(_Range)};
}
}
_NODISCARD constexpr auto end() const requires range<const _Vw> {
if constexpr (sized_range<const _Vw>) {
if constexpr (random_access_range<const _Vw>) {
return _RANGES begin(_Range) + static_cast<range_difference_t<_Vw>>(size());
} else {
return default_sentinel;
}
} else {
return _Sentinel<true>{_RANGES end(_Range)};
}
}
_NODISCARD constexpr auto size() requires sized_range<_Vw> {
const auto _Length = _RANGES size(_Range);
return (_STD min) (_Length, static_cast<decltype(_Length)>(_Count));
}
_NODISCARD constexpr auto size() const requires sized_range<const _Vw> {
const auto _Length = _RANGES size(_Range);
return (_STD min) (_Length, static_cast<decltype(_Length)>(_Count));
}
};
template <class _Rng>
take_view(_Rng&&, range_difference_t<_Rng>) -> take_view<views::all_t<_Rng>>;
template <class _Rng>
inline constexpr bool enable_borrowed_range<take_view<_Rng>> = enable_borrowed_range<_Rng>;
namespace views {
// VARIABLE views::take
template <class>
inline constexpr bool _Is_subrange = false;
template <class _It, class _Se, subrange_kind _Ki>
inline constexpr bool _Is_subrange<subrange<_It, _Se, _Ki>> = true;
// clang-format off
template <class _Rng>
concept _Random_sized_range = random_access_range<_Rng> && sized_range<_Rng>;
// clang-format on
class _Take_fn {
private:
enum class _St {
_Empty,
_Reconstruct_span,
_Reconstruct_string_view,
_Reconstruct_iota_view,
_Reconstruct_subrange,
_Take_view
};
template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
using _Ty = remove_cvref_t<_Rng>;
if constexpr (_Is_specialization_v<_Ty, empty_view>) {
return {_St::_Empty, true};
} else if constexpr (_Is_span_v<_Ty>) {
return {_St::_Reconstruct_span, true};
} else if constexpr (_Is_specialization_v<_Ty, basic_string_view>) {
return {_St::_Reconstruct_string_view, true};
} else if constexpr (_Random_sized_range<_Ty> && _Is_specialization_v<_Ty, iota_view>) {
return {_St::_Reconstruct_iota_view,
noexcept(_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>()))};
} else if constexpr (_Random_sized_range<_Ty> && _Is_subrange<_Ty>) {
return {_St::_Reconstruct_subrange,
noexcept(subrange{_RANGES begin(_STD declval<_Rng&>()),
_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>())})};
} else {
return {_St::_Take_view, noexcept(take_view{_STD declval<_Rng>(), range_difference_t<_Rng>{0}})};
}
}
template <class _Rng>
static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>();
template <class _Ty>
struct _Partial : _Pipe::_Base<_Partial<_Ty>> {
_Ty _Length;
// clang-format off
template <viewable_range _Rng>
requires convertible_to<_Ty&, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) &
noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _Length))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Take_fn{}(_STD forward<_Rng>(_Range), _Length);
}
// clang-format off
template <viewable_range _Rng>
requires convertible_to<const _Ty&, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const&
noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _Length))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Take_fn{}(_STD forward<_Rng>(_Range), _Length);
}
// clang-format off
template <viewable_range _Rng>
requires convertible_to<_Ty, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) &&
noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length));
}
// clang-format off
template <viewable_range _Rng>
requires convertible_to<const _Ty, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const&&
noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length));
}
};
public:
// clang-format off
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const noexcept(
_Choice<_Rng>._No_throw) {
// clang-format on
constexpr _St _Strat = _Choice<_Rng>._Strategy;
if constexpr (_Strat == _St::_Empty) {
// it's an empty_view: return another empty view
return remove_cvref_t<_Rng>{};
} else if constexpr (_Strat == _St::_Take_view) {
return take_view{_STD forward<_Rng>(_Range), _Count};
} else {
// it's a "reconstructible range"; return the same kind of range with a restricted extent
_Count = (_STD min) (_RANGES distance(_Range), _Count);
const auto _First = _RANGES begin(_Range);
// The following are all per the proposed resolution of LWG-3407
if constexpr (_Strat == _St::_Reconstruct_span) {
return span{_First, _First + _Count};
} else if constexpr (_Strat == _St::_Reconstruct_string_view) {
return remove_cvref_t<_Rng>{_First, _First + _Count};
} else if constexpr (_Strat == _St::_Reconstruct_iota_view) {
using _Vt = range_value_t<_Rng>;
return iota_view<_Vt, _Vt>{_First, _First + _Count};
} else if constexpr (_Strat == _St::_Reconstruct_subrange) {
return subrange{_First, _First + _Count};
} else {
static_assert(_Always_false<_Rng>, "Should be unreachable");
}
}
}
template <move_constructible _Ty>
_NODISCARD constexpr auto operator()(_Ty _Length) const noexcept {
return _Partial<_Ty>{._Length = _STD move(_Length)};
}
};
inline constexpr _Take_fn take;
} // namespace views
// CLASS TEMPLATE ranges::take_while_view
// clang-format off
template <view _Vw, class _Pr>
requires input_range<_Vw> && is_object_v<_Pr> && indirect_unary_predicate<const _Pr, iterator_t<_Vw>>
class take_while_view : public view_interface<take_while_view<_Vw, _Pr>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
/* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred{};
template <bool _Const, bool _Wrapped = true>
class _Sentinel {
private:
template <bool, bool>
friend class _Sentinel;
using _Base_t = _Maybe_const<_Const, _Vw>;
using _Base_iterator = _Maybe_wrapped<_Wrapped, iterator_t<_Base_t>>;
using _Base_sentinel = _Maybe_wrapped<_Wrapped, sentinel_t<_Base_t>>;
template <bool _OtherConst>
using _Maybe_const_iter = _Maybe_wrapped<_Wrapped, iterator_t<_Maybe_const<_OtherConst, _Vw>>>;
/* [[no_unique_address]] */ _Base_sentinel _Last{};
const _Pr* _Pred = nullptr;
public:
_Sentinel() = default;
constexpr explicit _Sentinel(_Base_sentinel _Last_, const _Pr* const _Pred_) noexcept(
is_nothrow_move_constructible_v<_Base_sentinel>) // strengthened
: _Last(_STD move(_Last_)), _Pred(_Pred_) {}
// clang-format off
constexpr _Sentinel(_Sentinel<!_Const, _Wrapped> _That) noexcept(
is_nothrow_constructible_v<_Base_sentinel, _Maybe_wrapped<_Wrapped, sentinel_t<_Vw>>>) // strengthened
requires _Const && convertible_to<_Maybe_wrapped<_Wrapped, sentinel_t<_Vw>>, _Base_sentinel>
: _Last(_STD move(_That._Last)), _Pred(_That._Pred) {}
// clang-format on
_NODISCARD constexpr _Base_sentinel base() const
noexcept(is_nothrow_copy_constructible_v<_Base_sentinel>) /* strengthened */ {
return _Last;
}
_NODISCARD friend constexpr bool operator==(const _Base_iterator& _Left, const _Sentinel& _Right) {
return _Right._Last == _Left || !_STD invoke(*_Right._Pred, *_Left);
}
// clang-format off
template <bool _OtherConst = !_Const>
requires sentinel_for<_Base_sentinel, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr bool operator==(
const _Maybe_const_iter<_OtherConst>& _Left, const _Sentinel& _Right) {
// clang-format on
return _Right._Last == _Left || !_STD invoke(*_Right._Pred, *_Left);
}
using _Prevent_inheriting_unwrap = _Sentinel;
// clang-format off
_NODISCARD constexpr auto _Unwrapped() const&
requires _Wrapped && _Unwrappable_v<const iterator_t<_Base_t>&> {
// clang-format on
return _Sentinel<_Const, false>{_Get_unwrapped(_Last), _Pred};
}
// clang-format off
_NODISCARD constexpr auto _Unwrapped() && requires _Wrapped && _Unwrappable_v<iterator_t<_Base_t>> {
// clang-format on
return _Sentinel<_Const, false>{_Get_unwrapped(_STD move(_Last)), _Pred};
}
static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v<iterator_t<_Base_t>>;
constexpr void _Seek_to(const _Sentinel<_Const, false>& _That) requires _Wrapped {
_Seek_wrapped(_Last, _That._Last);
}
constexpr void _Seek_to(_Sentinel<_Const, false>&& _That) requires _Wrapped {
_Seek_wrapped(_Last, _STD move(_That._Last));
}
};
public:
// clang-format off
take_while_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default;
// clang-format on
constexpr take_while_view(_Vw _Range_, _Pr _Pred_) noexcept(
is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened
: _Range(_STD move(_Range_)), _Pred{in_place, _STD move(_Pred_)} {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
_NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pred, "take_while_view has no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return *_Pred;
}
// clang-format off
_NODISCARD constexpr auto begin() noexcept(
noexcept(_RANGES begin(_Range))) /* strengthened */ requires (!_Simple_view<_Vw>) {
// clang-format on
return _RANGES begin(_Range);
}
// clang-format off
_NODISCARD constexpr auto begin() const noexcept(
noexcept(_RANGES begin(_Range))) /* strengthened */ requires range<const _Vw>
&& indirect_unary_predicate<const _Pr, iterator_t<const _Vw>> {
// clang-format on
return _RANGES begin(_Range);
}
// clang-format off
_NODISCARD constexpr auto end() noexcept(
noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel<false>>) /* strengthened */
requires (!_Simple_view<_Vw>) {
// clang-format on
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Sentinel<false>{_RANGES end(_Range), _STD addressof(*_Pred)};
}
// clang-format off
_NODISCARD constexpr auto end() const noexcept(
noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel<true>>) /* strengthened */
requires range<const _Vw> && indirect_unary_predicate<const _Pr, iterator_t<const _Vw>> {
// clang-format on
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Sentinel<true>{_RANGES end(_Range), _STD addressof(*_Pred)};
}
};
template <class _Rng, class _Pr>
take_while_view(_Rng&&, _Pr) -> take_while_view<views::all_t<_Rng>, _Pr>;
namespace views {
// VARIABLE views::take_while
class _Take_while_fn {
private:
template <class _Pr>
struct _Partial : _Pipe::_Base<_Partial<_Pr>> {
/* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred;
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept(
noexcept(take_while_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires {
take_while_view{static_cast<_Rng&&>(_Range), *_Pred};
}
{ return take_while_view{_STD forward<_Rng>(_Range), *_Pred}; }
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(
noexcept(take_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires {
take_while_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)};
}
{ return take_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; }
};
public:
template <viewable_range _Rng, class _Pr>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const
noexcept(noexcept(take_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)})) requires requires {
take_while_view{static_cast<_Rng&&>(_Range), _STD move(_Pred)};
}
{ return take_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)}; }
template <_Copy_constructible_object _Pr>
_NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) {
return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}};
}
};
inline constexpr _Take_while_fn take_while;
} // namespace views
// CLASS TEMPLATE ranges::drop_view
template <view _Vw>
class drop_view : public _Cached_position_t<forward_range<_Vw> && !(random_access_range<_Vw> && sized_range<_Vw>),
_Vw, drop_view<_Vw>> {
private:
/* [[no_unique_address]] */ _Vw _Range{};
range_difference_t<_Vw> _Count = 0;
_NODISCARD constexpr auto _Find_first() {
if constexpr (sized_range<_Vw>) {
_STL_INTERNAL_STATIC_ASSERT(!random_access_range<_Vw>);
auto _Offset = _RANGES distance(_Range);
if constexpr (bidirectional_range<_Vw> && common_range<_Vw>) {
if (_Count >= _Offset / 2) {
auto _Result = _RANGES end(_Range);
while (_Offset > _Count) {
--_Offset;
--_Result;
}
return _Result;
}
}
if (_Offset > _Count) {
_Offset = _Count;
}
return _RANGES next(_RANGES begin(_Range), _Offset);
} else {
return _RANGES next(_RANGES begin(_Range), _Count, _RANGES end(_Range));
}
}
public:
// clang-format off
drop_view() requires default_initializable<_Vw> = default;
// clang-format on
constexpr drop_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept(
is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Range(_STD move(_Range_)), _Count{_Count_} {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Count_ >= 0, "Numer of elements to drop must be non-negative (N4861 [range.drop.view]/1");
#endif // _CONTAINER_DEBUG_LEVEL > 0
}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
// clang-format off
_NODISCARD constexpr auto begin()
requires (!(_Simple_view<_Vw> && random_access_range<const _Vw> && sized_range<const _Vw>)) {
// clang-format on
if constexpr (sized_range<_Vw> && random_access_range<_Vw>) {
const auto _Offset = (_STD min) (_RANGES distance(_Range), _Count);
return _RANGES begin(_Range) + _Offset;
} else {
if constexpr (forward_range<_Vw>) {
if (this->_Has_cache()) {
return this->_Get_cache(_Range);
}
}
same_as<iterator_t<_Vw>> auto _Result = _Find_first();
if constexpr (forward_range<_Vw>) {
this->_Set_cache(_Range, _Result);
}
return _Result;
}
}
// clang-format off
_NODISCARD constexpr auto begin() const
requires random_access_range<const _Vw> && sized_range<const _Vw> {
// clang-format on
const auto _Offset = (_STD min) (_RANGES distance(_Range), _Count);
return _RANGES begin(_Range) + _Offset;
}
// clang-format off
_NODISCARD constexpr auto end() requires (!_Simple_view<_Vw>) {
// clang-format on
return _RANGES end(_Range);
}
_NODISCARD constexpr auto end() const requires range<const _Vw> {
return _RANGES end(_Range);
}
_NODISCARD constexpr auto size() requires sized_range<_Vw> {
const auto _Size = _RANGES size(_Range);
const auto _Count_as_size = static_cast<range_size_t<_Vw>>(_Count);
if (_Size < _Count_as_size) {
return range_size_t<_Vw>{0};
} else {
return static_cast<range_size_t<_Vw>>(_Size - _Count_as_size);
}
}
_NODISCARD constexpr auto size() const requires sized_range<const _Vw> {
const auto _Size = _RANGES size(_Range);
const auto _Count_as_size = static_cast<range_size_t<_Vw>>(_Count);
if (_Size < _Count_as_size) {
return range_size_t<_Vw>{0};
} else {
return static_cast<range_size_t<_Vw>>(_Size - _Count_as_size);
}
}
};
template <class _Rng>
drop_view(_Rng&&, range_difference_t<_Rng>) -> drop_view<views::all_t<_Rng>>;
template <class _Rng>
inline constexpr bool enable_borrowed_range<drop_view<_Rng>> = enable_borrowed_range<_Rng>;
namespace views {
// VARIABLE views::drop
class _Drop_fn {
private:
enum class _St { _Empty, _Reconstruct_span, _Reconstruct_subrange, _Reconstruct_other, _Drop_view };
template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
using _Ty = remove_cvref_t<_Rng>;
if constexpr (_Is_specialization_v<_Ty, empty_view>) {
return {_St::_Empty, true};
} else if constexpr (_Is_span_v<_Ty>) {
return {_St::_Reconstruct_span, true};
} else if constexpr (_Is_specialization_v<_Ty, basic_string_view>) {
return {_St::_Reconstruct_other, true};
} else if constexpr (_Random_sized_range<_Ty> && _Is_subrange<_Ty>) {
if constexpr (sized_sentinel_for<sentinel_t<_Ty>, iterator_t<_Ty>>) {
return {_St::_Reconstruct_subrange,
noexcept(_Ty{_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>()),
_RANGES end(_STD declval<_Rng&>())})};
} else {
return {_St::_Reconstruct_subrange,
noexcept(_Ty{_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>()),
_RANGES end(_STD declval<_Rng&>()), range_difference_t<_Rng>{0}})};
}
} else if constexpr (_Random_sized_range<_Ty> && _Is_specialization_v<_Ty, iota_view>) {
return {_St::_Reconstruct_other,
noexcept(_Ty{_RANGES begin(_STD declval<_Rng&>()) + _RANGES distance(_STD declval<_Rng&>()),
_RANGES end(_STD declval<_Rng&>())})};
} else {
return {_St::_Drop_view, noexcept(drop_view{_STD declval<_Rng>(), range_difference_t<_Rng>{0}})};
}
}
template <class _Rng>
static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>();
template <class _Ty>
struct _Partial : _Pipe::_Base<_Partial<_Ty>> {
_Ty _Length;
// clang-format off
template <viewable_range _Rng>
requires convertible_to<_Ty&, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) &
noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _Length))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Drop_fn{}(_STD forward<_Rng>(_Range), _Length);
}
// clang-format off
template <viewable_range _Rng>
requires convertible_to<const _Ty&, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const&
noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _Length))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Drop_fn{}(_STD forward<_Rng>(_Range), _Length);
}
// clang-format off
template <viewable_range _Rng>
requires convertible_to<_Ty, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) &&
noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length));
}
// clang-format off
template <viewable_range _Rng>
requires convertible_to<const _Ty, range_difference_t<_Rng>>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const&&
noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) {
// clang-format on
_STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>);
return _Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length));
}
};
public:
// clang-format off
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const noexcept(
_Choice<_Rng>._No_throw) {
// clang-format on
constexpr _St _Strat = _Choice<_Rng>._Strategy;
if constexpr (_Strat == _St::_Empty) {
// it's an empty_view: return another empty view
return remove_cvref_t<_Rng>{};
} else if constexpr (_Strat == _St::_Drop_view) {
return drop_view{_STD forward<_Rng>(_Range), _Count};
} else {
// it's a "reconstructible range"; return the same kind of range with a restricted extent
_Count = (_STD min) (_RANGES distance(_Range), _Count);
// The following are all per the proposed resolution of LWG-3407
if constexpr (_Strat == _St::_Reconstruct_span) {
return span{_Ubegin(_Range) + _Count, _Uend(_Range)};
} else if constexpr (_Strat == _St::_Reconstruct_subrange) {
if constexpr (sized_sentinel_for<sentinel_t<_Rng>, iterator_t<_Rng>>) {
return remove_cvref_t<_Rng>{_RANGES begin(_Range) + _Count, _RANGES end(_Range)};
} else {
return remove_cvref_t<_Rng>{
_RANGES begin(_Range) + _Count, _RANGES end(_Range), _RANGES size(_Range) - _Count};
}
} else if constexpr (_Strat == _St::_Reconstruct_other) {
return remove_cvref_t<_Rng>{_RANGES begin(_Range) + _Count, _RANGES end(_Range)};
} else {
static_assert(_Always_false<_Rng>, "Should be unreachable");
}
}
}
template <move_constructible _Ty>
_NODISCARD constexpr auto operator()(_Ty _Length) const noexcept {
return _Partial<_Ty>{._Length = _STD move(_Length)};
}
};
inline constexpr _Drop_fn drop;
} // namespace views
// CLASS TEMPLATE ranges::drop_while_view
// clang-format off
template <view _Vw, class _Pr>
requires input_range<_Vw> && is_object_v<_Pr> && indirect_unary_predicate<const _Pr, iterator_t<_Vw>>
class drop_while_view : public _Cached_position_t<forward_range<_Vw>, _Vw, drop_while_view<_Vw, _Pr>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
/* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred{};
public:
// clang-format off
drop_while_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default;
// clang-format on
constexpr drop_while_view(_Vw _Range_, _Pr _Pred_) noexcept(
is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened
: _Range(_STD move(_Range_)), _Pred{in_place, _STD move(_Pred_)} {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
_NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pred, "drop_while_view has no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return *_Pred;
}
_NODISCARD constexpr auto begin() {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(
_Pred, "N4885 [range.drop.while.view] forbids calling begin on a drop_while_view with no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
if constexpr (forward_range<_Vw>) {
if (this->_Has_cache()) {
return this->_Get_cache(_Range);
}
}
auto _First = _RANGES find_if_not(_Range, _STD cref(*_Pred));
if constexpr (forward_range<_Vw>) {
this->_Set_cache(_Range, _First);
}
return _First;
}
_NODISCARD constexpr auto end() noexcept(noexcept(_RANGES end(_Range))) /* strengthened */ {
return _RANGES end(_Range);
}
};
template <class _Rng, class _Pr>
drop_while_view(_Rng&&, _Pr) -> drop_while_view<views::all_t<_Rng>, _Pr>;
template <class _Rng, class _Pr>
inline constexpr bool enable_borrowed_range<drop_while_view<_Rng, _Pr>> = enable_borrowed_range<_Rng>;
namespace views {
// VARIABLE views::drop_while
class _Drop_while_fn {
private:
template <class _Pr>
struct _Partial : _Pipe::_Base<_Partial<_Pr>> {
/* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred;
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept(
noexcept(drop_while_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires {
drop_while_view{static_cast<_Rng&&>(_Range), *_Pred};
}
{ return drop_while_view{_STD forward<_Rng>(_Range), *_Pred}; }
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(
noexcept(drop_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires {
drop_while_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)};
}
{ return drop_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; }
};
public:
template <viewable_range _Rng, class _Pr>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const
noexcept(noexcept(drop_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)})) requires requires {
drop_while_view{static_cast<_Rng&&>(_Range), _STD move(_Pred)};
}
{ return drop_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)}; }
template <_Copy_constructible_object _Pr>
_NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) {
return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}};
}
};
inline constexpr _Drop_while_fn drop_while;
} // namespace views
// CLASS TEMPLATE ranges::join_view
// clang-format off
template <input_range _Vw>
requires (view<_Vw> && input_range<range_reference_t<_Vw>>
&& (is_reference_v<range_reference_t<_Vw>> || view<range_value_t<_Vw>>))
class join_view;
// clang-format on
template <class _Vw>
class _Join_view_base : public view_interface<join_view<_Vw>> {
protected:
/* [[no_unique_address]] */ _Defaultabox<views::all_t<range_reference_t<_Vw>>> _Inner{};
};
// clang-format off
template <class _Vw>
requires is_reference_v<range_reference_t<_Vw>>
class _Join_view_base<_Vw> : public view_interface<join_view<_Vw>> {};
template <input_range _Vw>
requires (view<_Vw> && input_range<range_reference_t<_Vw>>
&& (is_reference_v<range_reference_t<_Vw>> || view<range_value_t<_Vw>>))
class join_view : public _Join_view_base<_Vw> {
// clang-format on
private:
template <bool _Const>
using _InnerRng = range_reference_t<_Maybe_const<_Const, _Vw>>;
/* [[no_unique_address]] */ _Vw _Range{};
template <bool _Const>
class _Sentinel;
template <class _OuterTraits, class _InnerTraits, bool _Deref_is_glvalue,
bool _Inner_common> // TRANSITION, LWG-3289
struct _Category_base {};
// clang-format off
template <class _OuterTraits, class _InnerTraits, bool _Deref_is_glvalue, bool _Inner_common>
requires _Has_member_iterator_category<_OuterTraits> && _Has_member_iterator_category<_InnerTraits>
struct _Category_base<_OuterTraits, _InnerTraits, _Deref_is_glvalue, _Inner_common> {
using iterator_category =
conditional_t<_Deref_is_glvalue && _Inner_common // per LWG issue unnumbered as of 2021-03-16
&& derived_from<typename _OuterTraits::iterator_category, bidirectional_iterator_tag>
&& derived_from<typename _InnerTraits::iterator_category, bidirectional_iterator_tag>,
bidirectional_iterator_tag,
conditional_t<_Deref_is_glvalue
&& derived_from<typename _OuterTraits::iterator_category, forward_iterator_tag>
&& derived_from<typename _InnerTraits::iterator_category, forward_iterator_tag>,
forward_iterator_tag,
conditional_t<derived_from<typename _OuterTraits::iterator_category, input_iterator_tag>
&& derived_from<typename _InnerTraits::iterator_category, input_iterator_tag>,
input_iterator_tag,
output_iterator_tag>>>;
};
// clang-format on
template <bool _Const>
class _Iterator : public _Category_base<iterator_traits<iterator_t<_Maybe_const<_Const, _Vw>>>,
iterator_traits<iterator_t<_InnerRng<_Const>>>, is_reference_v<_InnerRng<_Const>>,
common_range<_InnerRng<_Const>>> {
private:
template <bool>
friend class _Iterator;
template <bool>
friend class _Sentinel;
using _Parent_t = _Maybe_const<_Const, join_view>;
using _Base = _Maybe_const<_Const, _Vw>;
using _OuterIter = iterator_t<_Base>;
using _InnerIter = iterator_t<_InnerRng<_Const>>;
// True if and only if the expression *i, where i is an iterator from the outer range, is a glvalue:
static constexpr bool _Deref_is_glvalue = is_reference_v<_InnerRng<_Const>>;
/* [[no_unique_address]] */ _OuterIter _Outer{};
/* [[no_unique_address]] */ _Defaultabox<_InnerIter> _Inner{}; // per LWG issue unfiled as of 2021-06-14
_Parent_t* _Parent{};
constexpr auto& _Update_inner(_InnerRng<_Const> _Range) {
if constexpr (_Deref_is_glvalue) {
return _Range;
} else {
_Parent->_Inner = views::all(_STD move(_Range));
return *_Parent->_Inner;
}
}
constexpr void _Satisfy() {
const auto _Last = _RANGES end(_Parent->_Range);
for (; _Outer != _Last; ++_Outer) {
auto& _Tmp = _Update_inner(*_Outer);
_Inner = _RANGES begin(_Tmp);
if (*_Inner != _RANGES end(_Tmp)) {
return;
}
}
if constexpr (_Deref_is_glvalue) {
_Inner._Reset();
}
}
#if _ITERATOR_DEBUG_LEVEL != 0
constexpr void _Check_dereference() const noexcept {
_STL_VERIFY(_Parent != nullptr, "cannot dereference value-initialized join_view iterator");
_STL_VERIFY(_Outer != _RANGES end(_Parent->_Range), "cannot dereference join_view end iterator");
sentinel_t<_InnerRng<false>> _Last;
if constexpr (_Deref_is_glvalue) {
_Last = _RANGES end(*_Outer);
} else {
_Last = _RANGES end(*_Parent->_Inner);
}
_STL_VERIFY(_Inner && *_Inner != _Last, "cannot dereference join_view end iterator");
}
constexpr void _Same_range(const _Iterator& _Right) const noexcept {
_STL_VERIFY(_Parent == _Right._Parent, "cannot compare incompatible join_view iterators");
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
public:
// clang-format off
// Per LWG issue unnumbered as of 2021-03-16
using iterator_concept = conditional_t<_Deref_is_glvalue
&& bidirectional_range<_Base> && bidirectional_range<_InnerRng<_Const>>
&& common_range<_InnerRng<_Const>>, bidirectional_iterator_tag,
conditional_t<_Deref_is_glvalue && forward_range<_Base> && forward_range<_InnerRng<_Const>>,
forward_iterator_tag, input_iterator_tag>>;
// clang-format on
using value_type = range_value_t<_InnerRng<_Const>>;
using difference_type = common_type_t<range_difference_t<_Base>, range_difference_t<_InnerRng<_Const>>>;
// clang-format off
_Iterator() requires default_initializable<_OuterIter> && default_initializable<_InnerIter> = default;
// clang-format on
constexpr _Iterator(_Parent_t& _Parent_, _OuterIter _Outer_)
: _Outer{_STD move(_Outer_)}, _Parent{_STD addressof(_Parent_)} {
#if _ITERATOR_DEBUG_LEVEL != 0
_Adl_verify_range(_Outer, _RANGES end(_Parent_._Range));
if constexpr (forward_range<_Base>) {
_Adl_verify_range(_RANGES begin(_Parent_._Range), _Outer);
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Satisfy();
}
// clang-format off
constexpr _Iterator(_Iterator<!_Const> _It)
requires _Const && convertible_to<iterator_t<_Vw>, _OuterIter>
&& convertible_to<iterator_t<_InnerRng<false>>, _InnerIter>
: _Outer{_STD move(_It._Outer)}, _Inner{_STD move(_It._Inner)}, _Parent{_It._Parent} {}
// clang-format on
_NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(**_Inner)) /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
_Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
return **_Inner;
}
// clang-format off
_NODISCARD constexpr _InnerIter operator->() const noexcept(is_nothrow_copy_constructible_v<_InnerIter>)
/* strengthened */ requires _Has_arrow<_InnerIter> && copyable<_InnerIter> {
// clang-format on
#if _ITERATOR_DEBUG_LEVEL != 0
_Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
return *_Inner;
}
constexpr _Iterator& operator++() {
if constexpr (_Deref_is_glvalue) {
if (++*_Inner == _RANGES end(*_Outer)) {
++_Outer;
_Satisfy();
}
} else {
if (++*_Inner == _RANGES end(*_Parent->_Inner)) {
++_Outer;
_Satisfy();
}
}
return *this;
}
constexpr decltype(auto) operator++(int) {
if constexpr (_Deref_is_glvalue && forward_range<_Base> && forward_range<_InnerRng<_Const>>) {
auto _Tmp = *this;
++*this;
return _Tmp;
} else {
++*this;
}
}
// clang-format off
constexpr _Iterator& operator--()
requires _Deref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<_InnerRng<_Const>>
&& common_range<_InnerRng<_Const>> {
// clang-format on
if (_Outer == _RANGES end(_Parent->_Range)) {
--_Outer;
_Inner = _RANGES end(*_Outer);
}
while (*_Inner == _RANGES begin(*_Outer)) {
--_Outer;
*_Inner = _RANGES end(*_Outer);
}
--*_Inner;
return *this;
}
// clang-format off
constexpr _Iterator operator--(int)
requires _Deref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<_InnerRng<_Const>>
&& common_range<_InnerRng<_Const>> {
// clang-format on
auto _Tmp = *this;
--*this;
return _Tmp;
}
// clang-format off
_NODISCARD friend constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Implicitly_convert_to<bool>(_Left._Outer == _Right._Outer
&& _Left._Inner == _Right._Inner))) /* strengthened */
requires _Deref_is_glvalue && equality_comparable<_OuterIter> && equality_comparable<_InnerIter> {
// clang-format on
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Outer == _Right._Outer && _Left._Inner == _Right._Inner;
}
_NODISCARD friend constexpr decltype(auto) iter_move(const _Iterator& _It) noexcept(
noexcept(_RANGES iter_move(*_It._Inner))) {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _RANGES iter_move(*_It._Inner);
}
// clang-format off
friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_RANGES iter_swap(*_Left._Inner, *_Right._Inner)))
requires indirectly_swappable<_InnerIter> {
// clang-format on
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Check_dereference();
_Right._Check_dereference();
#endif // _ITERATOR_DEBUG_LEVEL != 0
_RANGES iter_swap(*_Left._Inner, *_Right._Inner);
}
};
template <bool _Const>
class _Sentinel {
private:
template <bool>
friend class _Iterator;
template <bool>
friend class _Sentinel;
using _Parent_t = _Maybe_const<_Const, join_view>;
using _Base = _Maybe_const<_Const, _Vw>;
template <bool _OtherConst>
using _Maybe_const_iter = iterator_t<_Maybe_const<_OtherConst, _Vw>>;
/* [[no_unique_address]] */ sentinel_t<_Base> _Last{};
// clang-format off
template <bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const noexcept(
noexcept(_Implicitly_convert_to<bool>(_It._Outer == _Last))) {
// clang-format on
return _It._Outer == _Last;
}
public:
_Sentinel() = default;
constexpr explicit _Sentinel(_Parent_t& _Parent) noexcept(
noexcept(_RANGES end(_Parent._Range))
&& is_nothrow_move_constructible_v<sentinel_t<_Base>>) // strengthened
: _Last(_RANGES end(_Parent._Range)) {}
// clang-format off
constexpr _Sentinel(_Sentinel<!_Const> _Se)
noexcept(is_nothrow_constructible_v<sentinel_t<_Base>, sentinel_t<_Vw>>) // strengthened
requires _Const && convertible_to<sentinel_t<_Vw>, sentinel_t<_Base>>
: _Last(_STD move(_Se._Last)) {}
template <bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr bool operator==(const _Iterator<_OtherConst>& _Left,
const _Sentinel& _Right) noexcept(noexcept(_Right._Equal(_Left))) /* strengthened */ {
// clang-format on
return _Right._Equal(_Left);
}
};
public:
// clang-format off
join_view() requires default_initializable<_Vw> = default;
// clang-format on
constexpr explicit join_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Range(_STD move(_Range_)) {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
_NODISCARD constexpr auto begin() {
constexpr bool _Use_const = _Simple_view<_Vw> && is_reference_v<_InnerRng<false>>;
return _Iterator<_Use_const>{*this, _RANGES begin(_Range)};
}
// clang-format off
_NODISCARD constexpr _Iterator<true> begin() const
requires input_range<const _Vw> && is_reference_v<_InnerRng<true>> {
// clang-format on
return _Iterator<true>{*this, _RANGES begin(_Range)};
}
// clang-format off
_NODISCARD constexpr auto end() {
if constexpr (forward_range<_Vw> && is_reference_v<_InnerRng<false>>
&& forward_range<_InnerRng<false>> && common_range<_Vw> && common_range<_InnerRng<false>>) {
// clang-format on
return _Iterator<_Simple_view<_Vw>>{*this, _RANGES end(_Range)};
} else {
return _Sentinel<_Simple_view<_Vw>>{*this};
}
}
// clang-format off
_NODISCARD constexpr auto end() const
requires input_range<const _Vw> && is_reference_v<_InnerRng<true>> {
if constexpr (forward_range<const _Vw> && is_reference_v<_InnerRng<true>>
&& forward_range<_InnerRng<true>> && common_range<const _Vw>
&& common_range<_InnerRng<true>>) {
// clang-format on
return _Iterator<true>{*this, _RANGES end(_Range)};
} else {
return _Sentinel<true>{*this};
}
}
};
template <class _Rng>
explicit join_view(_Rng&&) -> join_view<views::all_t<_Rng>>;
namespace views {
// VARIABLE views::join
class _Join_fn : public _Pipe::_Base<_Join_fn> {
public:
// clang-format off
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(noexcept(
join_view<views::all_t<_Rng>>{_STD forward<_Rng>(_Range)})) requires requires {
join_view<views::all_t<_Rng>>{static_cast<_Rng&&>(_Range)};
} {
// clang-format on
return join_view<views::all_t<_Rng>>{_STD forward<_Rng>(_Range)};
}
};
inline constexpr _Join_fn join;
} // namespace views
// CLASS TEMPLATE ranges::split_view
// clang-format off
template <class _Ty>
concept _Tiny_range = sized_range<_Ty>
&& requires { typename _Require_constant<remove_reference_t<_Ty>::size()>; }
&& (remove_reference_t<_Ty>::size() <= 1);
template <input_range _Vw, forward_range _Pat>
requires (view<_Vw> && view<_Pat>
&& indirectly_comparable<iterator_t<_Vw>, iterator_t<_Pat>, _RANGES equal_to>
&& (forward_range<_Vw> || _Tiny_range<_Pat>))
class split_view;
// clang-format on
template <class _Vw, class _Pat>
class _Split_view_base : public view_interface<split_view<_Vw, _Pat>> {
protected:
/* [[no_unique_address]] */ _Defaultabox<iterator_t<_Vw>> _Current{};
};
template <forward_range _Vw, class _Pat>
class _Split_view_base<_Vw, _Pat> : public view_interface<split_view<_Vw, _Pat>> {};
// clang-format off
template <input_range _Vw, forward_range _Pat>
requires (view<_Vw> && view<_Pat>
&& indirectly_comparable<iterator_t<_Vw>, iterator_t<_Pat>, _RANGES equal_to>
&& (forward_range<_Vw> || _Tiny_range<_Pat>))
class split_view : public _Split_view_base<_Vw, _Pat> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
/* [[no_unique_address]] */ _Pat _Pattern{};
template <bool>
class _Inner_iter;
template <class>
class _Outer_iter_base {};
// clang-format off
template <forward_iterator _Iter>
class _Outer_iter_base<_Iter> {
// clang-format on
protected:
_Iter _Current{};
public:
using iterator_category = input_iterator_tag;
_Outer_iter_base() = default;
constexpr explicit _Outer_iter_base(_Iter _Current_) noexcept(is_nothrow_move_constructible_v<_Iter>)
: _Current{_STD move(_Current_)} {}
};
template <bool _Const>
class _Outer_iter : public _Outer_iter_base<iterator_t<_Maybe_const<_Const, _Vw>>> {
private:
template <bool>
friend class _Inner_iter;
friend _Outer_iter<true>;
using _Mybase = _Outer_iter_base<iterator_t<_Maybe_const<_Const, _Vw>>>;
using _ParentTy = _Maybe_const<_Const, split_view>;
using _BaseTy = _Maybe_const<_Const, _Vw>;
_ParentTy* _Parent = nullptr;
_NODISCARD constexpr iterator_t<_BaseTy>& _Get_current() noexcept {
if constexpr (forward_range<_BaseTy>) {
return this->_Current;
} else {
return *_Parent->_Current;
}
}
_NODISCARD constexpr const iterator_t<_BaseTy>& _Get_current() const noexcept {
if constexpr (forward_range<_BaseTy>) {
return this->_Current;
} else {
return *_Parent->_Current;
}
}
_NODISCARD constexpr bool _At_end() const
noexcept(noexcept(_Implicitly_convert_to<bool>(_Get_current() == _RANGES end(_Parent->_Range)))) {
return _Get_current() == _RANGES end(_Parent->_Range);
}
public:
using iterator_concept = conditional_t<forward_range<_BaseTy>, forward_iterator_tag, input_iterator_tag>;
using difference_type = range_difference_t<_BaseTy>;
class value_type : public view_interface<value_type> {
private:
/* [[no_unique_address]] */ _Outer_iter _First{};
public:
value_type() = default;
constexpr explicit value_type(_Outer_iter _First_) noexcept(
is_nothrow_move_constructible_v<_Outer_iter>) // strengthened
: _First{_STD move(_First_)} {}
_NODISCARD constexpr auto begin() const {
return _Inner_iter<_Const>{_First};
}
_NODISCARD constexpr default_sentinel_t end() const noexcept {
return default_sentinel;
}
};
_Outer_iter() = default;
// clang-format off
constexpr explicit _Outer_iter(_ParentTy& _Parent_) noexcept // strengthened
requires (!forward_range<_BaseTy>) : _Parent{_STD addressof(_Parent_)} {}
// clang-format on
constexpr _Outer_iter(_ParentTy& _Parent_, iterator_t<_BaseTy> _Current_) noexcept(
is_nothrow_move_constructible_v<iterator_t<_BaseTy>>) // strengthened
requires forward_range<_BaseTy>
: _Mybase{_STD move(_Current_)}, _Parent{_STD addressof(_Parent_)} {}
// clang-format off
constexpr _Outer_iter(_Outer_iter<!_Const> _It)
requires _Const && convertible_to<iterator_t<_Vw>, iterator_t<_BaseTy>>
: _Mybase{_STD move(_It._Current)}, _Parent{_It._Parent} {}
// clang-format on
_NODISCARD constexpr auto operator*() const noexcept(noexcept(value_type{*this})) /* strengthened */ {
return value_type{*this};
}
constexpr _Outer_iter& operator++() {
const auto _End = _RANGES end(_Parent->_Range);
auto& _Cur = _Get_current();
if (_Cur == _End) {
return *this;
}
const auto _Pat_first = _RANGES begin(_Parent->_Pattern);
const auto _Pat_last = _RANGES end(_Parent->_Pattern);
if (_Pat_first == _Pat_last) {
++_Cur;
} else if constexpr (_Tiny_range<_Pat>) {
_Cur = _RANGES _Find_unchecked(_STD move(_Cur), _End, *_Pat_first);
if (_Cur != _End) {
++_Cur;
}
} else {
do {
auto _Result = _RANGES mismatch(_Cur, _End, _Pat_first, _Pat_last);
if (_Result.in2 == _Pat_last) { // pattern matches
_Cur = _STD move(_Result.in1);
break;
}
} while (++_Cur != _End);
}
return *this;
}
constexpr decltype(auto) operator++(int) {
if constexpr (forward_range<_BaseTy>) {
auto _Tmp = *this;
++*this;
return _Tmp;
} else {
++*this;
}
}
_NODISCARD friend constexpr bool operator==(const _Outer_iter& _Left, const _Outer_iter& _Right) noexcept(
noexcept(_Left._Current == _Right._Current)) /* strengthened */ requires forward_range<_BaseTy> {
return _Left._Current == _Right._Current;
}
_NODISCARD friend constexpr bool operator==(const _Outer_iter& _Left, default_sentinel_t) noexcept(
noexcept(_Left._At_end())) /* strengthened */ {
return _Left._At_end();
}
};
template <class _BaseTy>
class _Inner_iter_base {};
template <forward_range _BaseTy>
class _Inner_iter_base<_BaseTy> {
private:
using _BaseCategory = typename iterator_traits<iterator_t<_BaseTy>>::iterator_category;
public:
using iterator_category =
conditional_t<derived_from<_BaseCategory, forward_iterator_tag>, forward_iterator_tag, _BaseCategory>;
};
template <bool _Const>
class _Inner_iter : public _Inner_iter_base<_Maybe_const<_Const, _Vw>> {
private:
using _BaseTy = _Maybe_const<_Const, _Vw>;
_Outer_iter<_Const> _It{};
bool _Incremented = false;
_NODISCARD constexpr bool _Equal(const _Inner_iter& _Right) const {
return _It._Get_current() == _Right._It._Get_current();
}
_NODISCARD constexpr iterator_t<_BaseTy>& _Get_current() noexcept {
return _It._Get_current();
}
_NODISCARD constexpr const iterator_t<_BaseTy>& _Get_current() const noexcept {
return _It._Get_current();
}
_NODISCARD constexpr bool _At_end() const {
auto _Pat_pos = _RANGES begin(_It._Parent->_Pattern);
const auto _Pat_end = _RANGES end(_It._Parent->_Pattern);
auto _Last = _RANGES end(_It._Parent->_Range);
if constexpr (_Tiny_range<_Pat>) {
const auto& _Cur = _It._Get_current(); // Intentionally a reference. Since _Pat is tiny, this could
// be a move-only iterator type.
if (_Cur == _Last) {
return true;
}
if (_Pat_pos == _Pat_end) {
return _Incremented;
}
return *_Cur == *_Pat_pos;
} else {
auto _Cur = _It._Get_current(); // Intentionally not a reference. _Pat is not tiny, so this is a
// forward (copyable) iterator.
if (_Cur == _Last) {
return true;
}
if (_Pat_pos == _Pat_end) {
return _Incremented;
}
do {
if (*_Cur != *_Pat_pos) {
return false;
}
if (++_Pat_pos == _Pat_end) {
return true;
}
} while (++_Cur != _Last);
return false;
}
}
public:
using iterator_concept = typename _Outer_iter<_Const>::iterator_concept;
using value_type = range_value_t<_BaseTy>;
using difference_type = range_difference_t<_BaseTy>;
_Inner_iter() = default;
constexpr explicit _Inner_iter(_Outer_iter<_Const> _It_) noexcept(
is_nothrow_move_constructible_v<_Outer_iter<_Const>>) // strengthened
: _It{_STD move(_It_)} {}
_NODISCARD constexpr decltype(auto) operator*() const {
return *_It._Get_current();
}
constexpr _Inner_iter& operator++() {
_Incremented = true;
if constexpr (!forward_range<_BaseTy>) {
if constexpr (_Pat::size() == 0) {
return *this;
}
}
++_It._Get_current();
return *this;
}
constexpr decltype(auto) operator++(int) {
if constexpr (forward_range<_BaseTy>) {
auto _Tmp = *this;
++*this;
return _Tmp;
} else {
++*this;
}
}
_NODISCARD friend constexpr bool operator==(
const _Inner_iter& _Left, const _Inner_iter& _Right) requires forward_range<_BaseTy> {
return _Left._Equal(_Right);
}
_NODISCARD friend constexpr bool operator==(const _Inner_iter& _Left, default_sentinel_t) {
return _Left._At_end();
}
_NODISCARD friend constexpr decltype(auto) iter_move(const _Inner_iter& _Iter) noexcept(
noexcept(_RANGES iter_move(_Iter._Get_current()))) {
return _RANGES iter_move(_Iter._Get_current());
}
// clang-format off
friend constexpr void iter_swap(const _Inner_iter& _Left, const _Inner_iter& _Right)
noexcept(noexcept(_RANGES iter_swap(_Left._Get_current(), _Right._Get_current())))
requires indirectly_swappable<iterator_t<_BaseTy>> {
// clang-format on
_RANGES iter_swap(_Left._Get_current(), _Right._Get_current());
}
};
public:
// clang-format off
split_view() requires default_initializable<_Vw> && default_initializable<_Pat> = default;
// clang-format on
constexpr split_view(_Vw _Range_, _Pat _Pattern_) noexcept(
is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pat>) // strengthened
: _Range(_STD move(_Range_)), _Pattern(_STD move(_Pattern_)) {}
// clang-format off
template <input_range _Rng>
requires constructible_from<_Vw, views::all_t<_Rng>>
&& constructible_from<_Pat, single_view<range_value_t<_Rng>>>
constexpr split_view(_Rng&& _Range_, range_value_t<_Rng> _Elem)
noexcept(noexcept(_Vw(views::all(_STD forward<_Rng>(_Range_))))
&& noexcept(_Pat(single_view{_STD move(_Elem)}))) // strengthened
: _Range(views::all(_STD forward<_Rng>(_Range_))), _Pattern(single_view{_STD move(_Elem)}) {}
// clang-format on
_NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) /* strengthened */
requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
_NODISCARD constexpr auto begin() {
if constexpr (forward_range<_Vw>) {
return _Outer_iter<_Simple_view<_Vw>>{*this, _RANGES begin(_Range)};
} else {
this->_Current = _RANGES begin(_Range);
return _Outer_iter<false>{*this};
}
}
// clang-format off
_NODISCARD constexpr auto begin() const requires forward_range<_Vw> && forward_range<const _Vw> {
// clang-format on
return _Outer_iter<true>{*this, _RANGES begin(_Range)};
}
// clang-format off
_NODISCARD constexpr auto end() requires forward_range<_Vw> && common_range<_Vw> {
// clang-format on
return _Outer_iter<_Simple_view<_Vw>>{*this, _RANGES end(_Range)};
}
_NODISCARD constexpr auto end() const {
if constexpr (forward_range<_Vw> && forward_range<const _Vw> && common_range<const _Vw>) {
return _Outer_iter<true>{*this, _RANGES end(_Range)};
} else {
return default_sentinel;
}
}
};
template <class _Rng, class _Pat>
split_view(_Rng&&, _Pat&&) -> split_view<views::all_t<_Rng>, views::all_t<_Pat>>;
template <input_range _Rng>
split_view(_Rng&&, range_value_t<_Rng>) -> split_view<views::all_t<_Rng>, single_view<range_value_t<_Rng>>>;
namespace views {
// VARIABLE views::split
class _Split_fn {
private:
template <class _Delim>
struct _Partial : _Pipe::_Base<_Partial<_Delim>> {
/* [[no_unique_address]] */ _Delim _Delimiter;
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept(
noexcept(split_view{_STD forward<_Rng>(_Range), _Delimiter})) requires requires {
split_view{static_cast<_Rng&&>(_Range), _Delimiter};
}
{ return split_view{_STD forward<_Rng>(_Range), _Delimiter}; }
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(noexcept(
split_view{_STD forward<_Rng>(_Range), _STD forward<_Delim>(_Delimiter)})) requires requires {
split_view{static_cast<_Rng&&>(_Range), static_cast<_Delim&&>(_Delimiter)};
}
{ return split_view{_STD forward<_Rng>(_Range), _STD forward<_Delim>(_Delimiter)}; }
};
public:
// clang-format off
template <viewable_range _Rng, class _Pat>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Pat&& _Pattern) const noexcept(noexcept(
split_view{_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)})) requires requires {
split_view{static_cast<_Rng&&>(_Range), static_cast<_Pat&&>(_Pattern)};
} {
// clang-format on
return split_view{_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)};
}
// clang-format off
template <class _Delim>
requires is_lvalue_reference_v<_Delim> || move_constructible<_Delim>
_NODISCARD constexpr auto operator()(_Delim&& _Delimiter) const
noexcept(is_lvalue_reference_v<_Delim> || is_nothrow_move_constructible_v<_Delim>) {
// clang-format on
return _Partial<_Delim>{._Delimiter = _STD forward<_Delim>(_Delimiter)};
}
};
inline constexpr _Split_fn split;
// VARIABLE views::counted
class _Counted_fn {
private:
enum class _St { _Span, _Subrange, _Subrange_counted };
template <class _It>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
_STL_INTERNAL_STATIC_ASSERT(input_or_output_iterator<_It>);
if constexpr (contiguous_iterator<_It>) {
return {_St::_Span, noexcept(span{_STD to_address(_STD declval<_It>()), iter_difference_t<_It>{}})};
} else if constexpr (random_access_iterator<_It>) {
return {_St::_Subrange,
noexcept(subrange{_STD declval<_It>(), _STD declval<_It>() + iter_difference_t<_It>{}})};
} else {
return {_St::_Subrange_counted,
noexcept(subrange{
counted_iterator{_STD declval<_It>(), iter_difference_t<_It>{}}, default_sentinel})};
}
}
template <class _It>
static constexpr _Choice_t<_St> _Choice = _Choose<_It>();
public:
// clang-format off
template <class _It>
requires input_or_output_iterator<decay_t<_It>>
_NODISCARD constexpr auto operator()(_It&& _First, const iter_difference_t<decay_t<_It>> _Count) const
noexcept(_Choice<decay_t<_It>>._No_throw) {
// clang-format on
_STL_ASSERT(_Count >= 0, "The size passed to views::counted must be non-negative");
constexpr _St _Strat = _Choice<decay_t<_It>>._Strategy;
if constexpr (_Strat == _St::_Span) {
return span{_STD to_address(_STD forward<_It>(_First)), static_cast<size_t>(_Count)};
} else if constexpr (_Strat == _St::_Subrange) {
return subrange{_First, _First + _Count};
} else if constexpr (_Strat == _St::_Subrange_counted) {
return subrange{counted_iterator{_STD forward<_It>(_First), _Count}, default_sentinel};
}
}
};
inline constexpr _Counted_fn counted;
} // namespace views
// CLASS TEMPLATE ranges::common_view
// clang-format off
template <view _Vw>
requires (!common_range<_Vw> && copyable<iterator_t<_Vw>>)
class common_view : public view_interface<common_view<_Vw>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Base{};
public:
// clang-format off
common_view() requires default_initializable<_Vw> = default;
// clang-format on
constexpr explicit common_view(_Vw _Base_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Base(_STD move(_Base_)) {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Base;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Base);
}
_NODISCARD constexpr auto begin() noexcept(
noexcept(_RANGES begin(_Base)) && is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */ {
if constexpr (random_access_range<_Vw> && sized_range<_Vw>) {
return _RANGES begin(_Base);
} else {
return common_iterator<iterator_t<_Vw>, sentinel_t<_Vw>>{_RANGES begin(_Base)};
}
}
_NODISCARD constexpr auto begin() const noexcept(
noexcept(_RANGES begin(_Base))
&& is_nothrow_move_constructible_v<iterator_t<const _Vw>>) /* strengthened */ requires range<const _Vw> {
if constexpr (random_access_range<const _Vw> && sized_range<const _Vw>) {
return _RANGES begin(_Base);
} else {
return common_iterator<iterator_t<const _Vw>, sentinel_t<const _Vw>>{_RANGES begin(_Base)};
}
}
_NODISCARD constexpr auto end() {
if constexpr (random_access_range<_Vw> && sized_range<_Vw>) {
return _RANGES begin(_Base) + _RANGES size(_Base);
} else {
return common_iterator<iterator_t<_Vw>, sentinel_t<_Vw>>{_RANGES end(_Base)};
}
}
_NODISCARD constexpr auto end() const requires range<const _Vw> {
if constexpr (random_access_range<const _Vw> && sized_range<const _Vw>) {
return _RANGES begin(_Base) + _RANGES size(_Base);
} else {
return common_iterator<iterator_t<const _Vw>, sentinel_t<const _Vw>>{_RANGES end(_Base)};
}
}
_NODISCARD constexpr auto size() noexcept(
noexcept(_RANGES size(_Base))) /* strengthened */ requires sized_range<_Vw> {
return _RANGES size(_Base);
}
_NODISCARD constexpr auto size() const
noexcept(noexcept(_RANGES size(_Base))) /* strengthened */ requires sized_range<const _Vw> {
return _RANGES size(_Base);
}
};
template <class _Rng>
common_view(_Rng&&) -> common_view<views::all_t<_Rng>>;
template <class _Rng>
inline constexpr bool enable_borrowed_range<common_view<_Rng>> = enable_borrowed_range<_Rng>;
namespace views {
// VARIABLE views::common
class _Common_fn : public _Pipe::_Base<_Common_fn> {
private:
enum class _St { _None, _All, _Common };
template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (common_range<_Rng>) {
return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))};
} else if constexpr (copyable<iterator_t<_Rng>>) {
return {_St::_Common, noexcept(common_view{_STD declval<_Rng>()})};
} else {
return {_St::_None};
}
}
template <class _Rng>
static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>();
public:
// clang-format off
template <viewable_range _Rng>
requires (_Choice<_Rng>._Strategy != _St::_None)
_NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) {
// clang-format on
constexpr _St _Strat = _Choice<_Rng>._Strategy;
if constexpr (_Strat == _St::_All) {
return views::all(_STD forward<_Rng>(_Range));
} else if constexpr (_Strat == _St::_Common) {
return common_view{_STD forward<_Rng>(_Range)};
} else {
static_assert(_Always_false<_Rng>, "Should be unreachable");
}
}
};
inline constexpr _Common_fn common;
} // namespace views
// CLASS TEMPLATE ranges::reverse_view
// clang-format off
template <view _Vw>
requires bidirectional_range<_Vw>
class reverse_view : public _Cached_position_t<!common_range<_Vw>, _Vw, reverse_view<_Vw>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
template <class _Rng>
using _Rev_iter = reverse_iterator<iterator_t<_Rng>>;
public:
// clang-format off
reverse_view() requires default_initializable<_Vw> = default;
// clang-format on
constexpr explicit reverse_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Range(_STD move(_Range_)) {}
_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
_NODISCARD constexpr _Rev_iter<_Vw> begin() {
if constexpr (common_range<_Vw>) {
return _Rev_iter<_Vw>{_RANGES end(_Range)};
} else {
if (this->_Has_cache()) {
return _Rev_iter<_Vw>{this->_Get_cache(_Range)};
}
iterator_t<_Vw> _First;
if constexpr (sized_range<_Vw>) {
_First = _RANGES next(_RANGES begin(_Range), _RANGES distance(_Range));
} else {
_First = _RANGES next(_RANGES begin(_Range), _RANGES end(_Range));
}
this->_Set_cache(_Range, _First);
return _Rev_iter<_Vw>{_STD move(_First)};
}
}
_NODISCARD constexpr auto begin() const noexcept(
noexcept(_Rev_iter<const _Vw>{_RANGES end(_Range)})) /* strengthened */ requires common_range<const _Vw> {
return _Rev_iter<const _Vw>{_RANGES end(_Range)};
}
_NODISCARD constexpr _Rev_iter<_Vw> end() noexcept(
noexcept(_Rev_iter<_Vw>{_RANGES begin(_Range)})) /* strengthened */ {
return _Rev_iter<_Vw>{_RANGES begin(_Range)};
}
_NODISCARD constexpr auto end() const noexcept(
noexcept(_Rev_iter<const _Vw>{_RANGES begin(_Range)})) /* strengthened */ requires common_range<const _Vw> {
return _Rev_iter<const _Vw>{_RANGES begin(_Range)};
}
_NODISCARD constexpr auto size() noexcept(
noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range<_Vw> {
return _RANGES size(_Range);
}
_NODISCARD constexpr auto size() const
noexcept(noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range<const _Vw> {
return _RANGES size(_Range);
}
};
template <class _Rng>
reverse_view(_Rng&&) -> reverse_view<views::all_t<_Rng>>;
template <class _Rng>
inline constexpr bool enable_borrowed_range<reverse_view<_Rng>> = enable_borrowed_range<_Rng>;
namespace views {
// VARIABLE views::reverse
template <class _Rng>
concept _Can_extract_base = requires(_Rng&& __r) {
static_cast<_Rng&&>(__r).base();
};
template <class _Rng>
concept _Can_reverse = requires(_Rng&& __r) {
reverse_view{static_cast<_Rng&&>(__r)};
};
class _Reverse_fn : public _Pipe::_Base<_Reverse_fn> {
private:
enum class _St { _None, _Base, _Subrange_unsized, _Subrange_sized, _Reverse };
template <class>
static constexpr auto _Reversed_subrange = -1;
template <class _It, subrange_kind _Ki>
static constexpr auto
_Reversed_subrange<subrange<reverse_iterator<_It>, reverse_iterator<_It>, _Ki>> = static_cast<int>(_Ki);
template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (bidirectional_range<_Rng>) {
if constexpr (_Is_specialization_v<_Rng, reverse_view>) {
if constexpr (_Can_extract_base<_Rng>) {
return {_St::_Base, noexcept(_STD declval<_Rng>().base())};
}
} else if constexpr (_Reversed_subrange<remove_cvref_t<_Rng>> == 0) {
using _It = decltype(_STD declval<_Rng&>().begin().base());
return {_St::_Subrange_unsized,
noexcept(subrange<_It, _It, subrange_kind::unsized>{
_STD declval<_Rng&>().end().base(), _STD declval<_Rng&>().begin().base()})};
} else if constexpr (_Reversed_subrange<remove_cvref_t<_Rng>> == 1) {
using _It = decltype(_STD declval<_Rng&>().begin().base());
return {_St::_Subrange_sized,
noexcept(subrange<_It, _It, subrange_kind::sized>{_STD declval<_Rng&>().end().base(),
_STD declval<_Rng&>().begin().base(), _STD declval<_Rng&>().size()})};
} else if constexpr (_Can_reverse<_Rng>) {
return {_St::_Reverse, noexcept(reverse_view{_STD declval<_Rng>()})};
}
}
return {_St::_None};
}
template <class _Rng>
static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>();
public:
// clang-format off
template <viewable_range _Rng>
requires (_Choice<_Rng>._Strategy != _St::_None)
_NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) {
// clang-format on
constexpr _St _Strat = _Choice<_Rng>._Strategy;
if constexpr (_Strat == _St::_Base) {
return _STD forward<_Rng>(_Range).base();
} else if constexpr (_Strat == _St::_Subrange_unsized) {
return subrange{_Range.end().base(), _Range.begin().base()};
} else if constexpr (_Strat == _St::_Subrange_sized) {
return subrange{_Range.end().base(), _Range.begin().base(), _Range.size()};
} else if constexpr (_Strat == _St::_Reverse) {
return reverse_view{_STD forward<_Rng>(_Range)};
} else {
static_assert(_Always_false<_Rng>, "Should be unreachable");
}
}
};
inline constexpr _Reverse_fn reverse;
} // namespace views
// CLASS TEMPLATE ranges::elements_view
template <class _Tuple, size_t _Index>
concept _Has_tuple_element = requires(_Tuple __t) {
typename tuple_size<_Tuple>::type;
requires _Index < tuple_size_v<_Tuple>;
typename tuple_element_t<_Index, _Tuple>;
// clang-format off
{ _STD get<_Index>(__t) } -> convertible_to<const tuple_element_t<_Index, _Tuple>&>;
// clang-format on
};
template <class _Tuple, size_t _Index>
concept _Returnable_element = is_reference_v<_Tuple> || move_constructible<tuple_element_t<_Index, _Tuple>>;
// clang-format off
template <input_range _Vw, size_t _Index>
requires view<_Vw> && _Has_tuple_element<range_value_t<_Vw>, _Index>
&& _Has_tuple_element<remove_reference_t<range_reference_t<_Vw>>, _Index>
&& _Returnable_element<range_reference_t<_Vw>, _Index>
class elements_view : public view_interface<elements_view<_Vw, _Index>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
template <bool _Const>
class _Sentinel;
template <class _Traits> // TRANSITION, LWG-3289
struct _Category_base {};
// clang-format off
template <_Has_member_iterator_category _Traits>
struct _Category_base<_Traits> {
// clang-format on
using iterator_category = typename _Traits::iterator_category;
};
template <bool _Const>
class _Iterator : public _Category_base<iterator_traits<iterator_t<_Vw>>> {
private:
template <bool>
friend class _Iterator;
template <bool>
friend class _Sentinel;
using _Base = _Maybe_const<_Const, _Vw>;
iterator_t<_Base> _Current{};
public:
using iterator_concept = conditional_t<random_access_range<_Base>, random_access_iterator_tag,
conditional_t<bidirectional_range<_Base>, bidirectional_iterator_tag,
conditional_t<forward_range<_Base>, forward_iterator_tag, input_iterator_tag>>>;
using value_type = remove_cvref_t<tuple_element_t<_Index, range_value_t<_Base>>>;
using difference_type = range_difference_t<_Base>;
// clang-format off
_Iterator() requires default_initializable<iterator_t<_Base>> = default;
// clang-format on
constexpr explicit _Iterator(iterator_t<_Base> _Current_) noexcept(
is_nothrow_move_constructible_v<iterator_t<_Base>>) // strengthened
: _Current{_STD move(_Current_)} {}
// clang-format off
constexpr _Iterator(_Iterator<!_Const> _It) noexcept(
is_nothrow_constructible_v<iterator_t<_Base>, iterator_t<_Vw>>) // strengthened
requires _Const && convertible_to<iterator_t<_Vw>, iterator_t<_Base>>
: _Current{_STD move(_It._Current)} {}
// clang-format on
_NODISCARD constexpr iterator_t<_Base> base() const& noexcept(
is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires copyable<iterator_t<_Base>> {
return _Current;
}
_NODISCARD constexpr iterator_t<_Base> base() && noexcept(
is_nothrow_move_constructible_v<iterator_t<_Base>>) /* strengthened */ {
return _STD move(_Current);
}
_NODISCARD constexpr decltype(auto) operator*() const
noexcept(noexcept(_STD get<_Index>(*_Current))) /* strengthened */
requires is_reference_v<range_reference_t<_Base>> {
return _STD get<_Index>(*_Current);
}
_NODISCARD constexpr decltype(auto) operator*() const
noexcept(is_nothrow_move_constructible_v<tuple_element_t<_Index, range_reference_t<_Base>>> //
&& noexcept(_STD get<_Index>(*_Current))) /* strengthened */ {
using _ElemTy = remove_cv_t<tuple_element_t<_Index, range_reference_t<_Base>>>;
return static_cast<_ElemTy>(_STD get<_Index>(*_Current));
}
constexpr _Iterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ {
++_Current;
return *this;
}
constexpr void operator++(int) noexcept(noexcept(++_Current)) /* strengthened */ {
++_Current;
}
constexpr _Iterator operator++(int) noexcept(
noexcept(++_Current) && is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires forward_range<_Base> {
auto _Tmp = *this;
++_Current;
return _Tmp;
}
constexpr _Iterator& operator--() noexcept(noexcept(--_Current)) /* strengthened */
requires bidirectional_range<_Base> {
--_Current;
return *this;
}
constexpr _Iterator operator--(int) noexcept(
noexcept(--_Current) && is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires bidirectional_range<_Base> {
auto _Tmp = *this;
--_Current;
return _Tmp;
}
constexpr void _Verify_offset(const difference_type _Off) const requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
(void) _Off;
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv
if constexpr (_Offset_verifiable_v<iterator_t<_Base>>) {
_Current._Verify_offset(_Off);
}
#endif // _ITERATOR_DEBUG_LEVEL == 0
}
constexpr _Iterator& operator+=(const difference_type _Off) noexcept(
noexcept(_Current += _Off)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current += _Off;
return *this;
}
constexpr _Iterator& operator-=(const difference_type _Off) noexcept(
noexcept(_Current -= _Off)) /* strengthened */ requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(-_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current -= _Off;
return *this;
}
_NODISCARD constexpr decltype(auto) operator[](const difference_type _Idx) const
noexcept(noexcept(_STD get<_Index>(*(_Current + _Idx)))) /* strengthened */
requires random_access_range<_Base> && is_reference_v<range_reference_t<_Base>> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Idx);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _STD get<_Index>(*(_Current + _Idx));
}
_NODISCARD constexpr decltype(auto) operator[](const difference_type _Idx) const
noexcept(is_nothrow_move_constructible_v<tuple_element_t<_Index, range_reference_t<_Base>>> //
&& noexcept(_STD get<_Index>(*(_Current + _Idx)))) /* strengthened */
requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Idx);
#endif // _ITERATOR_DEBUG_LEVEL != 0
using _ElemTy = remove_cv_t<tuple_element_t<_Index, range_reference_t<_Base>>>;
return static_cast<_ElemTy>(_STD get<_Index>(*(_Current + _Idx)));
}
_NODISCARD friend constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current == _Right._Current)) /* strengthened */
requires equality_comparable<iterator_t<_Base>> {
return _Left._Current == _Right._Current;
}
_NODISCARD friend constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
return _Left._Current < _Right._Current;
}
_NODISCARD friend constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
return _Right < _Left;
}
_NODISCARD friend constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
return !(_Right < _Left);
}
_NODISCARD friend constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current < _Right._Current)) /* strengthened */ requires random_access_range<_Base> {
return !(_Left < _Right);
}
// clang-format off
_NODISCARD friend constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right) noexcept(
noexcept(_Left._Current <=> _Right._Current)) /* strengthened */
requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> {
// clang-format on
return _Left._Current <=> _Right._Current;
}
_NODISCARD friend constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept(
noexcept(_STD declval<iterator_t<_Base>&>() += _Off)
&& is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Verify_offset(_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
auto _Copy = _It;
_Copy._Current += _Off;
return _Copy;
}
_NODISCARD friend constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) noexcept(
noexcept(_STD declval<iterator_t<_Base>&>() += _Off)
&& is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Verify_offset(_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
auto _Copy = _It;
_Copy._Current += _Off;
return _Copy;
}
_NODISCARD friend constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) noexcept(
noexcept(_STD declval<iterator_t<_Base>&>() -= _Off)
&& is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires random_access_range<_Base> {
#if _ITERATOR_DEBUG_LEVEL != 0
_It._Verify_offset(-_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
auto _Copy = _It;
_Copy._Current -= _Off;
return _Copy;
}
_NODISCARD friend constexpr difference_type operator-(const _Iterator& _Left,
const _Iterator& _Right) noexcept(noexcept(_Left._Current - _Right._Current)) /* strengthened */
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> {
return _Left._Current - _Right._Current;
}
};
template <bool _Const>
class _Sentinel {
private:
template <bool>
friend class _Sentinel;
using _Base = _Maybe_const<_Const, _Vw>;
template <bool _OtherConst>
using _Maybe_const_iter = iterator_t<_Maybe_const<_OtherConst, _Vw>>;
sentinel_t<_Base> _Last{};
template <bool _OtherConst>
_NODISCARD static constexpr const _Maybe_const_iter<_OtherConst>& _Get_current(
const _Iterator<_OtherConst>& _It) noexcept {
return _It._Current;
}
public:
_Sentinel() = default;
constexpr explicit _Sentinel(sentinel_t<_Base> _Last_) noexcept(
is_nothrow_move_constructible_v<sentinel_t<_Base>>) // strengthened
: _Last(_STD move(_Last_)) {}
// clang-format off
constexpr _Sentinel(_Sentinel<!_Const> _Se)
noexcept(is_nothrow_constructible_v<sentinel_t<_Base>, sentinel_t<_Vw>>) // strengthened
requires _Const && convertible_to<sentinel_t<_Vw>, sentinel_t<_Base>>
: _Last(_STD move(_Se._Last)) {}
// clang-format on
_NODISCARD constexpr sentinel_t<_Base> base() const
noexcept(is_nothrow_copy_constructible_v<sentinel_t<_Base>>) /* strengthened */ {
return _Last;
}
// clang-format off
template <bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr bool operator==(const _Iterator<_OtherConst>& _Left,
const _Sentinel& _Right) noexcept(noexcept(_Get_current(_Left) == _Right._Last)) /* strengthened */ {
// clang-format on
return _Get_current(_Left) == _Right._Last;
}
// clang-format off
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-(
const _Iterator<_OtherConst>& _Left, const _Sentinel& _Right) noexcept(
noexcept(_Get_current(_Left) - _Right._Last)) /* strengthened */ {
// clang-format on
return _Get_current(_Left) - _Right._Last;
}
// clang-format off
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-(
const _Sentinel& _Left, const _Iterator<_OtherConst>& _Right) noexcept(
noexcept(_Left._Last - _Get_current(_Right))) /* strengthened */ {
// clang-format on
return _Left._Last - _Get_current(_Right);
}
};
public:
// clang-format off
elements_view() requires default_initializable<_Vw> = default;
// clang-format on
constexpr explicit elements_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Range(_STD move(_Range_)) {}
_NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) /* strengthened */
requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}
// clang-format off
_NODISCARD constexpr _Iterator<false> begin() noexcept(
noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */
requires (!_Simple_view<_Vw>) {
// clang-format on
return _Iterator<false>{_RANGES begin(_Range)};
}
_NODISCARD constexpr _Iterator<true> begin() const
noexcept(noexcept(_RANGES begin(_Range))
&& is_nothrow_move_constructible_v<iterator_t<const _Vw>>) /* strengthened */
requires range<const _Vw> {
return _Iterator<true>{_RANGES begin(_Range)};
}
// clang-format off
_NODISCARD constexpr auto end() noexcept(noexcept(
_RANGES end(_Range)) && is_nothrow_move_constructible_v<sentinel_t<_Vw>>) /* strengthened */
requires (!_Simple_view<_Vw>) {
// clang-format on
if constexpr (common_range<_Vw>) {
return _Iterator<false>{_RANGES end(_Range)};
} else {
return _Sentinel<false>{_RANGES end(_Range)};
}
}
// clang-format off
_NODISCARD constexpr auto end() const noexcept(noexcept(
_RANGES end(_Range)) && is_nothrow_move_constructible_v<sentinel_t<const _Vw>>) /* strengthened */
requires range<const _Vw> {
// clang-format on
if constexpr (common_range<const _Vw>) {
return _Iterator<true>{_RANGES end(_Range)};
} else {
return _Sentinel<true>{_RANGES end(_Range)};
}
}
_NODISCARD constexpr auto size() noexcept(noexcept(_RANGES size(_Range))) /* strengthened */
requires sized_range<_Vw> {
return _RANGES size(_Range);
}
_NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(_Range))) /* strengthened */
requires sized_range<const _Vw> {
return _RANGES size(_Range);
}
};
template <class _Rng, size_t _Index>
inline constexpr bool enable_borrowed_range<elements_view<_Rng, _Index>> = enable_borrowed_range<_Rng>;
template <class _Rng>
using keys_view = elements_view<views::all_t<_Rng>, 0>;
template <class _Rng>
using values_view = elements_view<views::all_t<_Rng>, 1>;
namespace views {
// VARIABLE views::elements
template <size_t _Index>
class _Elements_fn : public _Pipe::_Base<_Elements_fn<_Index>> {
public:
template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(
noexcept(elements_view<views::all_t<_Rng>, _Index>{_STD forward<_Rng>(_Range)})) requires requires {
elements_view<views::all_t<_Rng>, _Index>{static_cast<_Rng&&>(_Range)};
}
{ return elements_view<views::all_t<_Rng>, _Index>{_STD forward<_Rng>(_Range)}; }
};
template <size_t _Index>
inline constexpr _Elements_fn<_Index> elements;
inline constexpr auto keys = elements<0>;
inline constexpr auto values = elements<1>;
} // namespace views
} // namespace ranges
namespace views = ranges::views;
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // __cpp_lib_ranges
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _RANGES_