// ranges standard header // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef _RANGES_ #define _RANGES_ #include #if _STL_COMPILER_PREPROCESSOR #ifndef __cpp_lib_ranges _EMIT_STL_WARNING(STL4038, "The contents of are available only with C++20 or later."); #else // ^^^ !defined(__cpp_lib_ranges) / defined(__cpp_lib_ranges) vvv #include <__msvc_int128.hpp> #include #include #include #include #include #include #if _HAS_CXX23 #include #endif // _HAS_CXX23 #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 template inline constexpr bool _Is_initializer_list = _Is_specialization_v, initializer_list>; #if _HAS_CXX23 _EXPORT_STD template using const_iterator_t = const_iterator>; _EXPORT_STD template using const_sentinel_t = const_sentinel>; _EXPORT_STD template using range_const_reference_t = iter_const_reference_t>; #endif // _HAS_CXX23 // clang-format off _EXPORT_STD template concept viewable_range = range<_Rng> && ((view> && constructible_from, _Rng>) || (!view> && (is_lvalue_reference_v<_Rng> || (movable> && !_Is_initializer_list<_Rng>)))); template concept _Simple_view = view<_Rng> && range && same_as, iterator_t> && same_as, sentinel_t>; // clang-format on template concept _Valid_movable_box_object = #if _HAS_CXX23 move_constructible<_Ty> #else // ^^^ C++23 / C++20 vvv copy_constructible<_Ty> #endif // C++20 && _Destructible_object<_Ty>; template concept _Has_arrow = input_iterator<_It> && (is_pointer_v<_It> || _Has_member_arrow<_It&>); template using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>; template using _Maybe_wrapped = conditional_t<_IsWrapped, _Ty, _Unwrapped_t<_Ty>>; namespace _Pipe { template struct _Base {}; template _Ty* _Derived_from_range_adaptor_closure(_Base<_Ty>&); // not defined // clang-format off template concept _Range_adaptor_closure_object = !range> && requires(remove_cvref_t<_Ty>& __t) { { _Pipe::_Derived_from_range_adaptor_closure(__t) } -> same_as*>; }; // clang-format on template struct _Pipeline : _Base<_Pipeline<_ClosureLeft, _ClosureRight>> { _STL_INTERNAL_STATIC_ASSERT(_Range_adaptor_closure_object<_ClosureLeft>); _STL_INTERNAL_STATIC_ASSERT(_Range_adaptor_closure_object<_ClosureRight>); /* [[no_unique_address]] */ _ClosureLeft _Left; /* [[no_unique_address]] */ _ClosureRight _Right; template constexpr explicit _Pipeline(_Ty1&& _Val1, _Ty2&& _Val2) noexcept( is_nothrow_constructible_v<_Ty1, _ClosureLeft>&& is_nothrow_constructible_v<_Ty2, _ClosureRight>) : _Left(_STD forward<_Ty1>(_Val1)), _Right(_STD forward<_Ty2>(_Val2)) {} template _NODISCARD constexpr auto operator()(_Ty&& _Val) & noexcept( noexcept(_Right(_Left(_STD forward<_Ty>(_Val))))) requires requires { _Right(_Left(_STD forward<_Ty>(_Val))); } { return _Right(_Left(_STD forward<_Ty>(_Val))); } template _NODISCARD constexpr auto operator()(_Ty&& _Val) const& noexcept( noexcept(_Right(_Left(_STD forward<_Ty>(_Val))))) requires requires { _Right(_Left(_STD forward<_Ty>(_Val))); } { return _Right(_Left(_STD forward<_Ty>(_Val))); } template _NODISCARD constexpr auto operator()(_Ty&& _Val) && noexcept( noexcept(_STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))))) requires requires { _STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))); } { return _STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))); } template _NODISCARD constexpr auto operator()(_Ty&& _Val) const&& noexcept( noexcept(_STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))))) requires requires { _STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))); } { return _STD move(_Right)(_STD move(_Left)(_STD forward<_Ty>(_Val))); } }; template _Pipeline(_Ty1, _Ty2) -> _Pipeline<_Ty1, _Ty2>; _EXPORT_STD template requires _Range_adaptor_closure_object<_Left> // && _Range_adaptor_closure_object<_Right> // && constructible_from, _Left> // && constructible_from, _Right> // _NODISCARD constexpr auto operator|(_Left&& __l, _Right&& __r) noexcept( noexcept(_Pipeline{static_cast<_Left&&>(__l), static_cast<_Right&&>(__r)})) { return _Pipeline{static_cast<_Left&&>(__l), static_cast<_Right&&>(__r)}; } _EXPORT_STD template requires (_Range_adaptor_closure_object<_Right> && range<_Left>) _NODISCARD constexpr auto operator|(_Left&& __l, _Right&& __r) noexcept( noexcept(_STD forward<_Right>(__r)(_STD forward<_Left>(__l)))) requires requires { static_cast<_Right&&>(__r)(static_cast<_Left&&>(__l)); } { return _STD forward<_Right>(__r)(_STD forward<_Left>(__l)); } } // namespace _Pipe template 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 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(noexcept(_Pos = _It{})) { _Pos = _It{}; _Cached = false; return *this; } // a moved iterator doesn't point into a moved range, so cache values must not propagate via move; // similarly, a cache value might not be valid for a moved-from view so clear move sources constexpr _Cached_position(_Cached_position&& _Other) noexcept(noexcept(_Pos = _It{})) { _Other._Pos = _It{}; _Other._Cached = false; } constexpr _Cached_position& operator=(_Cached_position&& _Other) noexcept(noexcept(_Pos = _It{})) { _Pos = _It{}; _Cached = false; _Other._Pos = _It{}; _Other._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; } constexpr void _Set_cache(_Rng&, _It _Iter) noexcept(is_nothrow_move_assignable_v<_It>) { _Pos = _STD move(_Iter); _Cached = true; } }; template 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; // Offsets are potentially invalidated by move, so source caches are invalidated after move constexpr _Cached_position(_Cached_position&& _Other) noexcept : _Off(_STD exchange(_Other._Off, range_difference_t<_Rng>{-1})) {} constexpr _Cached_position& operator=(_Cached_position&& _Other) noexcept { _Off = _STD exchange(_Other._Off, range_difference_t<_Rng>{-1}); return *this; } _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; } constexpr void _Set_cache(_Rng& _Range, const _It& _Iter) noexcept( noexcept(_Off = _Iter - _RANGES begin(_Range))) { _Off = _Iter - _RANGES begin(_Range); } }; template using _Cached_position_t = conditional_t<_Enable, _Cached_position<_Rng, _Derived>, view_interface<_Derived>>; // A simplified optional that augments copy_constructible types with full copyability, // and move_constructible types with full movability. // In C++20, this corresponds to copyable-box. template <_Valid_movable_box_object _Ty> class _Movable_box { public: constexpr _Movable_box() noexcept(is_nothrow_default_constructible_v<_Ty>) requires default_initializable<_Ty> : _Val(), _Engaged{true} {} template constexpr _Movable_box(in_place_t, _Types&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _Types...>) // strengthened : _Val(_STD forward<_Types>(_Args)...), _Engaged{true} {} constexpr ~_Movable_box() { if (_Engaged) { _Val.~_Ty(); } } // clang-format off ~_Movable_box() requires is_trivially_destructible_v<_Ty> = default; _Movable_box(const _Movable_box&) requires copy_constructible<_Ty> && is_trivially_copy_constructible_v<_Ty> = default; // clang-format on constexpr _Movable_box(const _Movable_box& _That) requires copy_constructible<_Ty> : _Engaged{_That._Engaged} { if (_That._Engaged) { _STD _Construct_in_place(_Val, static_cast(_That._Val)); } } // clang-format off _Movable_box(_Movable_box&&) requires is_trivially_move_constructible_v<_Ty> = default; // clang-format on constexpr _Movable_box(_Movable_box&& _That) : _Engaged{_That._Engaged} { if (_That._Engaged) { _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); } } // clang-format off _Movable_box& operator=(const _Movable_box&) noexcept requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty> = default; // clang-format on constexpr _Movable_box& operator=(const _Movable_box& _That) noexcept( is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_copy_assignable_v<_Ty>) // strengthened requires copyable<_Ty> { if (_Engaged) { if (_That._Engaged) { static_cast<_Ty&>(_Val) = static_cast(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { _STD _Construct_in_place(_Val, static_cast(_That._Val)); _Engaged = true; } else { // nothing to do } } return *this; } constexpr _Movable_box& operator=(const _Movable_box& _That) noexcept(is_nothrow_copy_constructible_v<_Ty>) requires copy_constructible<_Ty> { if (_STD addressof(_That) == this) { return *this; } if (_Engaged) { _Val.~_Ty(); _Engaged = false; } if (_That._Engaged) { _STD _Construct_in_place(_Val, static_cast(_That._Val)); _Engaged = true; } return *this; } // clang-format off _Movable_box& operator=(_Movable_box&&) noexcept requires movable<_Ty> && is_trivially_move_assignable_v<_Ty> = default; // clang-format on constexpr _Movable_box& operator=(_Movable_box&& _That) noexcept( is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) // strengthened requires movable<_Ty> { if (_Engaged) { if (_That._Engaged) { static_cast<_Ty&>(_Val) = static_cast<_Ty&&>(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); _Engaged = true; } else { // nothing to do } } return *this; } constexpr _Movable_box& operator=(_Movable_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) { _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_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 { remove_cv_t<_Ty> _Val; }; bool _Engaged; }; // [range.move.wrap] template concept _Use_simple_movable_box_wrapper = (copy_constructible<_Ty> // 1. If copy_constructible is true, movable-box should store only a T if either T models // copyable, or is_nothrow_move_constructible_v && is_nothrow_copy_constructible_v is true. ? copyable<_Ty> || (is_nothrow_move_constructible_v<_Ty> && is_nothrow_copy_constructible_v<_Ty>) // 2. Otherwise, movable-box should store only a T if either T models movable or // is_nothrow_move_constructible_v is true. : movable<_Ty> || is_nothrow_move_constructible_v<_Ty>); template concept _Copy_constructible_for_box = is_copy_constructible_v<_Ty>; template <_Valid_movable_box_object _Ty> requires _Use_simple_movable_box_wrapper<_Ty> class _Movable_box<_Ty> { // provide the same API more efficiently when we can avoid the disengaged state public: // clang-format off _Movable_box() requires default_initializable<_Ty> = default; // clang-format on template constexpr _Movable_box(in_place_t, _Types&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _Types...>) // strengthened : _Val(_STD forward<_Types>(_Args)...) {} // clang-format off _Movable_box(const _Movable_box&) requires _Copy_constructible_for_box<_Ty> && is_trivially_copy_constructible_v<_Ty> = default; _Movable_box(_Movable_box&&) requires is_trivially_move_constructible_v<_Ty> = default; // clang-format on constexpr _Movable_box(const _Movable_box& _That) noexcept(is_nothrow_copy_constructible_v<_Ty>) requires _Copy_constructible_for_box<_Ty> : _Val(static_cast(_That._Val)) {} constexpr _Movable_box(_Movable_box&& _That) noexcept(is_nothrow_move_constructible_v<_Ty>) : _Val(static_cast<_Ty&&>(_That._Val)) {} // clang-format off _Movable_box& operator=(const _Movable_box&) requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty> = default; _Movable_box& operator=(_Movable_box&&) requires movable<_Ty> && is_trivially_move_assignable_v<_Ty> = default; // clang-format on constexpr _Movable_box& operator=(const _Movable_box& _That) noexcept( is_nothrow_copy_assignable_v<_Ty> || !copyable<_Ty>) // strengthened requires copy_constructible<_Ty> { if constexpr (copyable<_Ty>) { static_cast<_Ty&>(_Val) = static_cast(_That._Val); } else { if (_STD addressof(_That) != this) { _Val.~_Ty(); _STD _Construct_in_place(_Val, static_cast(_That._Val)); } } return *this; } constexpr _Movable_box& operator=(_Movable_box&& _That) noexcept( is_nothrow_move_assignable_v<_Ty> || !movable<_Ty>) /* strengthened */ { if constexpr (movable<_Ty>) { static_cast<_Ty&>(_Val) = static_cast<_Ty&&>(_That._Val); } else { if (_STD addressof(_That) != this) { _Val.~_Ty(); _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_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]] */ remove_cv_t<_Ty> _Val{}; }; template class _Defaultabox { // a simplified optional that augments movable types with default-constructibility public: constexpr _Defaultabox() noexcept {} constexpr ~_Defaultabox() { if (_Engaged) { _Val.~_Ty(); } } // clang-format off ~_Defaultabox() requires is_trivially_destructible_v<_Ty> = default; _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) { _STD _Construct_in_place(_Val, static_cast(_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) { _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); } } template <_Different_from<_Ty> _Uty> requires convertible_to constexpr _Defaultabox(const _Defaultabox<_Uty>& _That) : _Engaged{_That} { if (_That) { _STD _Construct_in_place(_Val, *_That); } } template <_Different_from<_Ty> _Uty> requires convertible_to<_Uty, _Ty> constexpr _Defaultabox(_Defaultabox<_Uty>&& _That) : _Engaged{_That} { if (_That) { _STD _Construct_in_place(_Val, _STD move(*_That)); } } // 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) { static_cast<_Ty&>(_Val) = static_cast(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { _STD _Construct_in_place(_Val, static_cast(_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) { static_cast<_Ty&>(_Val) = static_cast<_Ty&&>(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_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) { static_cast<_Ty&>(_Val) = _STD move(_That); } else { _STD _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) { static_cast<_Ty&>(_Val) = _That; } else { _STD _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(static_cast(_Val) == static_cast(_That._Val))) { _STL_INTERNAL_STATIC_ASSERT(equality_comparable<_Ty>); return _Engaged == _That._Engaged && (!_Engaged || static_cast(_Val) == static_cast(_That._Val)); } private: union { remove_cv_t<_Ty> _Val; }; bool _Engaged = false; }; template requires default_initializable<_Ty> class _Defaultabox<_Ty> { // provide the same API more efficiently for default-constructible types public: _Defaultabox() = default; template <_Different_from<_Ty> _Uty> requires convertible_to constexpr _Defaultabox(const _Defaultabox<_Uty>& _That) { if (_That) { _Value = static_cast<_Ty>(*_That); } } template <_Different_from<_Ty> _Uty> requires convertible_to<_Uty, _Ty> constexpr _Defaultabox(_Defaultabox<_Uty>&& _That) { if (_That) { _Value = static_cast<_Ty>(_STD move(*_That)); } } 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{}; }; template <_Destructible_object _Ty, bool _Needs_operator_bool = true> class _Non_propagating_cache { // a simplified optional that resets on copy / move public: constexpr _Non_propagating_cache() noexcept {} constexpr ~_Non_propagating_cache() { if (_Engaged) { _Val.~_Ty(); } } // clang-format off ~_Non_propagating_cache() requires is_trivially_destructible_v<_Ty> = default; // clang-format on constexpr _Non_propagating_cache(const _Non_propagating_cache&) noexcept {} constexpr _Non_propagating_cache(_Non_propagating_cache&& _Other) noexcept { if (_Other._Engaged) { _Other._Val.~_Ty(); _Other._Engaged = false; } } constexpr _Non_propagating_cache& operator=(const _Non_propagating_cache& _Other) noexcept { if (_STD addressof(_Other) == this) { return *this; } if (_Engaged) { _Val.~_Ty(); _Engaged = false; } return *this; } constexpr _Non_propagating_cache& operator=(_Non_propagating_cache&& _Other) noexcept { if (_Engaged) { _Val.~_Ty(); _Engaged = false; } if (_Other._Engaged) { _Other._Val.~_Ty(); _Other._Engaged = false; } return *this; } _NODISCARD constexpr explicit operator bool() const noexcept requires _Needs_operator_bool { 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; } template constexpr _Ty& _Emplace(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) { if (_Engaged) { _Val.~_Ty(); _Engaged = false; } _STD _Construct_in_place(_Val, _STD forward<_Types>(_Args)...); _Engaged = true; return _Val; } private: union { remove_cv_t<_Ty> _Val; }; bool _Engaged = false; }; template <_Destructible_object _Ty> requires is_trivially_destructible_v<_Ty> class _Non_propagating_cache<_Ty, false> { // a specialization for trivially destructible types where checking if // the cache contains a value is not needed public: constexpr _Non_propagating_cache() noexcept {} ~_Non_propagating_cache() = default; constexpr _Non_propagating_cache(const _Non_propagating_cache&) noexcept {} constexpr _Non_propagating_cache(_Non_propagating_cache&&) noexcept {} constexpr _Non_propagating_cache& operator=(const _Non_propagating_cache&) noexcept { return *this; } constexpr _Non_propagating_cache& operator=(_Non_propagating_cache&&) noexcept { return *this; } _NODISCARD constexpr _Ty& operator*() noexcept { return _Val; } _NODISCARD constexpr const _Ty& operator*() const noexcept { return _Val; } template constexpr _Ty& _Emplace(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) { _STD _Construct_in_place(_Val, _STD forward<_Types>(_Args)...); return _Val; } private: union { remove_cv_t<_Ty> _Val; }; }; #if _HAS_CXX23 _EXPORT_STD template requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> class range_adaptor_closure : public _Pipe::_Base<_Derived> {}; #endif // _HAS_CXX23 template class _Range_closure : public _Pipe::_Base<_Range_closure<_Fn, _Types...>> { public: // We assume that _Fn is the type of a customization point object. That means // 1. The behavior of operator() is independent of cvref qualifiers, so we can use `invocable<_Fn, ` without // loss of generality, and // 2. _Fn must be default-constructible and stateless, so we can create instances "on-the-fly" and avoid // storing a copy. _STL_INTERNAL_STATIC_ASSERT((same_as, _Types> && ...)); _STL_INTERNAL_STATIC_ASSERT(is_empty_v<_Fn>&& is_default_constructible_v<_Fn>); template requires (same_as, _Types> && ...) constexpr explicit _Range_closure(_UTypes&&... _Args) noexcept( conjunction_v...>) : _Captures(_STD forward<_UTypes>(_Args)...) {} void operator()(auto&&) & = delete; void operator()(auto&&) const& = delete; void operator()(auto&&) && = delete; void operator()(auto&&) const&& = delete; using _Indices = index_sequence_for<_Types...>; template requires invocable<_Fn, _Ty, _Types&...> constexpr decltype(auto) operator()(_Ty&& _Arg) & noexcept( noexcept(_Call(*this, _STD forward<_Ty>(_Arg), _Indices{}))) { return _Call(*this, _STD forward<_Ty>(_Arg), _Indices{}); } template requires invocable<_Fn, _Ty, const _Types&...> constexpr decltype(auto) operator()(_Ty&& _Arg) const& noexcept( noexcept(_Call(*this, _STD forward<_Ty>(_Arg), _Indices{}))) { return _Call(*this, _STD forward<_Ty>(_Arg), _Indices{}); } template requires invocable<_Fn, _Ty, _Types...> constexpr decltype(auto) operator()(_Ty&& _Arg) && noexcept( noexcept(_Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}))) { return _Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}); } template requires invocable<_Fn, _Ty, const _Types...> constexpr decltype(auto) operator()(_Ty&& _Arg) const&& noexcept( noexcept(_Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}))) { return _Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}); } private: template static constexpr decltype(auto) _Call(_SelfTy&& _Self, _Ty&& _Arg, index_sequence<_Idx...>) noexcept( noexcept(_Fn{}(_STD forward<_Ty>(_Arg), _STD get<_Idx>(_STD forward<_SelfTy>(_Self)._Captures)...))) { _STL_INTERNAL_STATIC_ASSERT(same_as, _Indices>); return _Fn{}(_STD forward<_Ty>(_Arg), _STD get<_Idx>(_STD forward<_SelfTy>(_Self)._Captures)...); } tuple<_Types...> _Captures; }; _EXPORT_STD template requires is_object_v<_Ty> class empty_view : public view_interface> { 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; } }; template inline constexpr bool enable_borrowed_range> = true; namespace views { _EXPORT_STD template inline constexpr empty_view<_Ty> empty; } // namespace views _EXPORT_STD template <_Valid_movable_box_object _Ty> class single_view : public view_interface> { 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 requires copy_constructible<_Ty> : _Val{in_place, _Val_} {} constexpr explicit single_view(_Ty&& _Val_) noexcept(is_nothrow_move_constructible_v<_Ty>) // strengthened : _Val{in_place, _STD move(_Val_)} {} template requires constructible_from<_Ty, _Types...> constexpr explicit single_view(in_place_t, _Types&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _Types...>) // strengthened : _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]] */ _Movable_box<_Ty> _Val{}; }; template single_view(_Ty) -> single_view<_Ty>; namespace views { struct _Single_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept( noexcept(single_view>(_STD forward<_Ty>(_Val)))) requires requires { typename single_view>; single_view>(static_cast<_Ty&&>(_Val)); } { return single_view>(_STD forward<_Ty>(_Val)); } // clang-format on }; _EXPORT_STD inline constexpr _Single_fn single; } // namespace views template using _Iota_diff_t = conditional_t, conditional_t>, iter_difference_t<_Ty>>; // clang-format off template concept _Decrementable = incrementable<_Ty> && requires(_Ty __t) { { --__t } -> same_as<_Ty&>; { __t-- } -> same_as<_Ty>; }; template 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>>; }; // clang-format on template struct _Ioterator_category_base {}; template requires integral<_Iota_diff_t<_Wi>> struct _Ioterator_category_base<_Wi> { using iterator_category = input_iterator_tag; }; template requires copyable<_Wi> struct _Ioterator : _Ioterator_category_base<_Wi> { /* [[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, forward_iterator_tag, input_iterator_tag>>>; using value_type = _Wi; using difference_type = _Iota_diff_t<_Wi>; // clang-format off _Ioterator() requires default_initializable<_Wi> = default; // clang-format on constexpr explicit _Ioterator(_Wi _Val) noexcept(is_nothrow_move_constructible_v<_Wi>) /* strengthened */ : _Current(_STD move(_Val)) {} _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 static constexpr bool _Nothrow_plus_equal = noexcept(_STD declval<_Left&>() += _STD declval()); template <_Integer_like _Left, class _Right> static constexpr bool _Nothrow_plus_equal<_Left, _Right> = true; template static constexpr bool _Nothrow_minus_equal = noexcept(_STD declval<_Left&>() -= _STD declval()); 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); } } _NODISCARD_FRIEND constexpr bool operator==(const _Ioterator& _Left, const _Ioterator& _Right) noexcept( noexcept(_Left._Current == _Right._Current)) requires equality_comparable<_Wi> { return _Left._Current == _Right._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; } _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); } _NODISCARD_FRIEND constexpr auto operator<=>(const _Ioterator& _Left, const _Ioterator& _Right) noexcept( noexcept(_Left._Current <=> _Right._Current)) requires totally_ordered<_Wi> && three_way_comparable<_Wi> { return _Left._Current <=> _Right._Current; } _NODISCARD_FRIEND constexpr _Ioterator operator+(_Ioterator _It, const difference_type _Off) noexcept( is_nothrow_move_constructible_v<_Ioterator>&& noexcept(_It += _Off)) /* strengthened */ requires _Advanceable<_Wi> { _It += _Off; return _It; } _NODISCARD_FRIEND constexpr _Ioterator operator+(const difference_type _Off, _Ioterator _It) noexcept( is_nothrow_move_constructible_v<_Wi>&& 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( is_nothrow_move_constructible_v<_Ioterator>&& noexcept(_It -= _Off)) /* strengthened */ requires _Advanceable<_Wi> { _It -= _Off; return _It; } _NODISCARD_FRIEND constexpr difference_type operator-(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(noexcept(_Left._Current - _Right._Current)) /* strengthened */ requires _Advanceable<_Wi> { if constexpr (_Integer_like<_Wi>) { if constexpr (_Signed_integer_like<_Wi>) { return static_cast( static_cast(_Left._Current) - static_cast(_Right._Current)); } else if (_Right._Current > _Left._Current) { return static_cast( -static_cast(_Right._Current - _Left._Current)); } else { return static_cast(_Left._Current - _Right._Current); } } else { return static_cast(_Left._Current - _Right._Current); } } }; template requires _Weakly_equality_comparable_with<_Wi, _Bo> && copyable<_Wi> struct _Iotinel { 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); } }; _EXPORT_STD template requires _Weakly_equality_comparable_with<_Wi, _Bo> && copyable<_Wi> class iota_view : public view_interface> { private: /* [[no_unique_address]] */ _Wi _Value{}; /* [[no_unique_address]] */ _Bo _Bound{}; using _It = _Ioterator<_Wi>; using _Se = conditional_t, _It, conditional_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 explicit 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 N4928 [range.iota.view]/8, the first argument must precede the " "second when their types are totally ordered."); } } constexpr explicit 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<_Wi, _Bo>) { return _It{_Bound}; } else if constexpr (same_as<_Bo, unreachable_sentinel_t>) { return unreachable_sentinel; } else { return _Se{_Bound}; } } #pragma warning(push) #pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned // clang-format off _NODISCARD constexpr auto size() const noexcept(noexcept(_Bound - _Value)) /* strengthened */ requires (same_as<_Wi, _Bo> && _Advanceable<_Wi>) || (_Integer_like<_Wi> && _Integer_like<_Bo>) || sized_sentinel_for<_Bo, _Wi> { // clang-format on if constexpr (_Integer_like<_Wi> && _Integer_like<_Bo>) { return (_Value < 0) ? ((_Bound < 0) ? (_To_unsigned_like(-_Value) - _To_unsigned_like(-_Bound)) : (_To_unsigned_like(_Bound) + _To_unsigned_like(-_Value))) : (_To_unsigned_like(_Bound) - _To_unsigned_like(_Value)); } else { return _To_unsigned_like(_Bound - _Value); } } #pragma warning(pop) }; // clang-format off template 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 inline constexpr bool enable_borrowed_range> = true; namespace views { struct _Iota_fn { template _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 _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)); } }; _EXPORT_STD inline constexpr _Iota_fn iota; class _Take_fn; class _Drop_fn; } // namespace views #if _HAS_CXX23 template concept _Integer_like_with_usable_difference_type = _Signed_integer_like<_Ty> || (_Integer_like<_Ty> && weakly_incrementable<_Ty>); template struct _Repeat_view_difference_type { using type = _Iota_diff_t<_Ty>; }; template <_Signed_integer_like _Ty> struct _Repeat_view_difference_type<_Ty> { using type = _Ty; }; _EXPORT_STD template requires (is_object_v<_Ty> && same_as<_Ty, remove_cv_t<_Ty>> && (_Integer_like_with_usable_difference_type<_Bo> || same_as<_Bo, unreachable_sentinel_t>) ) class repeat_view : public view_interface> { private: friend views::_Take_fn; friend views::_Drop_fn; class _Iterator { private: friend repeat_view; using _Index_type = conditional_t, ptrdiff_t, _Bo>; const _Ty* _Value{}; /* [[no_unique_address]] */ _Index_type _Current{}; constexpr explicit _Iterator(const _Ty* _Val, _Index_type _Bo_ = _Index_type{}) noexcept // strengthened : _Value(_Val), _Current(_Bo_) { if constexpr (_Signed_integer_like<_Bo>) { _STL_INTERNAL_CHECK(_Current >= 0); } } public: using iterator_concept = random_access_iterator_tag; using iterator_category = random_access_iterator_tag; using value_type = _Ty; using difference_type = typename _Repeat_view_difference_type<_Index_type>::type; _Iterator() = default; _NODISCARD constexpr const _Ty& operator*() const noexcept { return *_Value; } constexpr _Iterator& operator++() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Current < (numeric_limits<_Index_type>::max)(), "cannot increment repeat_view iterator past end (integer overflow)"); #endif ++_Current; return *this; } constexpr _Iterator operator++(int) noexcept /* strengthened */ { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (is_same_v<_Bo, unreachable_sentinel_t>) { _STL_VERIFY(_Current > (numeric_limits<_Index_type>::min)(), "cannot decrement repeat_view iterator before begin (integer overflow)"); } else { _STL_VERIFY(_Current > 0, "cannot decrement below 0"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 --_Current; return *this; } constexpr _Iterator operator--(int) noexcept /* strengthened */ { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(difference_type _Off) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 if (_Off > 0) { _STL_VERIFY(_Current <= (numeric_limits<_Index_type>::max)() - static_cast<_Index_type>(_Off), "cannot advance repeat_view iterator past end (integer overflow)"); } else { _STL_VERIFY(_Current >= (numeric_limits<_Index_type>::min)() - static_cast<_Index_type>(_Off), "cannot advance repeat_view iterator before begin (integer overflow)"); } if constexpr (!is_same_v<_Bo, unreachable_sentinel_t>) { _STL_VERIFY(_Current + _Off >= 0, "cannot subtract below 0"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 _Current += _Off; return *this; } constexpr _Iterator& operator-=(difference_type _Off) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 if (_Off < 0) { _STL_VERIFY(_Current <= (numeric_limits<_Index_type>::max)() + static_cast<_Index_type>(_Off), "cannot advance repeat_view iterator past end (integer overflow)"); } else { _STL_VERIFY(_Current >= (numeric_limits<_Index_type>::min)() + static_cast<_Index_type>(_Off), "cannot advance repeat_view iterator before begin (integer overflow)"); } if constexpr (!is_same_v<_Bo, unreachable_sentinel_t>) { _STL_VERIFY(_Current - _Off >= 0, "cannot subtract below 0"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 _Current -= _Off; return *this; } _NODISCARD constexpr const _Ty& operator[](difference_type _Idx) const noexcept { return *(*this + _Idx); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept /* strengthened */ { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right) noexcept /* strengthened */ { return _Left._Current <=> _Right._Current; } _NODISCARD_FRIEND constexpr _Iterator operator+(_Iterator _Iter, difference_type _Off) noexcept /* strengthened */ { _Iter += _Off; return _Iter; } _NODISCARD_FRIEND constexpr _Iterator operator+(difference_type _Off, _Iterator _Iter) noexcept /* strengthened */ { _Iter += _Off; return _Iter; } _NODISCARD_FRIEND constexpr _Iterator operator-(_Iterator _Iter, difference_type _Off) noexcept /* strengthened */ { _Iter -= _Off; return _Iter; } _NODISCARD_FRIEND constexpr difference_type operator-( const _Iterator& _Left, const _Iterator& _Right) noexcept /* strengthened */ { return static_cast( static_cast(_Left._Current) - static_cast(_Right._Current)); } }; /* [[no_unique_address]] */ _Movable_box<_Ty> _Value{}; /* [[no_unique_address]] */ _Bo _Bound{}; template _NODISCARD_CTOR constexpr repeat_view(_Tuple& _Val, index_sequence<_Indices...>, _Bo _Bound_) noexcept( is_nothrow_constructible_v<_Ty, tuple_element_t<_Indices, _Tuple>...>) : _Value(in_place, _Tuple_get<_Indices>(_STD move(_Val))...), _Bound(_STD move(_Bound_)) {} public: // clang-format off repeat_view() requires default_initializable<_Ty> = default; // clang-format on _NODISCARD_CTOR constexpr explicit repeat_view(const _Ty& _Value_, _Bo _Bound_ = _Bo{}) noexcept( is_nothrow_copy_constructible_v<_Ty>) // strengthened requires copy_constructible<_Ty> : _Value(in_place, _Value_), _Bound(_STD move(_Bound_)) { #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } #endif } _NODISCARD_CTOR constexpr explicit repeat_view(_Ty&& _Value_, _Bo _Bound_ = _Bo{}) noexcept( is_nothrow_move_constructible_v<_Ty>) // strengthened : _Value(in_place, _STD move(_Value_)), _Bound(_STD move(_Bound_)) { #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } #endif } template requires constructible_from<_Ty, _TArgs...> && constructible_from<_Bo, _BArgs...> _NODISCARD_CTOR constexpr explicit repeat_view(piecewise_construct_t, tuple<_TArgs...> _Val_args, tuple<_BArgs...> _Bound_args = tuple<>{}) noexcept(is_nothrow_constructible_v<_Ty, _TArgs...>&& noexcept(_STD make_from_tuple<_Bo>(_Bound_args))) // strengthened : repeat_view(_Val_args, index_sequence_for<_TArgs...>{}, _STD make_from_tuple<_Bo>(_Bound_args)) { #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } #endif } _NODISCARD constexpr _Iterator begin() const noexcept /* strengthened */ { return _Iterator{_STD addressof(*_Value)}; } _NODISCARD constexpr auto end() const noexcept /* strengthened */ { if constexpr (same_as<_Bo, unreachable_sentinel_t>) { return unreachable_sentinel; } else { return _Iterator{_STD addressof(*_Value), _Bound}; } } _NODISCARD constexpr auto size() const noexcept // strengthened requires (!same_as<_Bo, unreachable_sentinel_t>) { return _STD _To_unsigned_like(_Bound); } }; template repeat_view(_Ty, _Bo) -> repeat_view<_Ty, _Bo>; namespace views { struct _Repeat_fn { template _NODISCARD constexpr auto operator()(_Ty&& _Value) const noexcept(noexcept(repeat_view(_STD forward<_Ty>(_Value)))) requires requires { repeat_view(_STD forward<_Ty>(_Value)); } { return repeat_view(_STD forward<_Ty>(_Value)); } template _NODISCARD constexpr auto operator()(_Ty1&& _Val1, _Ty2&& _Val2) const noexcept(noexcept(repeat_view(_STD forward<_Ty1>(_Val1), _STD forward<_Ty2>(_Val2)))) requires requires { repeat_view(_STD forward<_Ty1>(_Val1), _STD forward<_Ty2>(_Val2)); } { return repeat_view(_STD forward<_Ty1>(_Val1), _STD forward<_Ty2>(_Val2)); } }; _EXPORT_STD inline constexpr _Repeat_fn repeat; } // namespace views #endif // _HAS_CXX23 template concept _Stream_extractable = requires(basic_istream<_Elem, _Traits>& __is, _Ty& __t) { __is >> __t; }; _EXPORT_STD template > requires default_initializable<_Ty> && _Stream_extractable<_Ty, _Elem, _Traits> class basic_istream_view : public view_interface> { 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 basic_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 basic_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{}; 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; } }; _EXPORT_STD template using istream_view = basic_istream_view<_Ty, char>; _EXPORT_STD template using wistream_view = basic_istream_view<_Ty, wchar_t>; namespace views { template concept _Istreamable_impl = derived_from<_Stream, basic_istream<_CharT, _Traits>> && constructible_from, _Stream&>; template concept _Istreamable = requires { typename _Stream::char_type; typename _Stream::traits_type; requires _Istreamable_impl<_Elem, _Stream, typename _Stream::char_type, typename _Stream::traits_type>; }; template struct _Istream_fn { template requires _Istreamable<_Ty, _StreamTy> _NODISCARD constexpr auto operator()(_StreamTy& _Stream) const noexcept(is_nothrow_default_constructible_v<_Ty>) /* strengthened */ { return basic_istream_view<_Ty, typename _StreamTy::char_type, typename _StreamTy::traits_type>(_Stream); } }; _EXPORT_STD template inline constexpr _Istream_fn<_Ty> istream; } // namespace views _EXPORT_STD template requires is_object_v<_Rng> class ref_view : public view_interface> { private: _Rng* _Range; static void _Rvalue_poison(_Rng&); static void _Rvalue_poison(_Rng&&) = delete; public: // clang-format off template <_Different_from _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 ref_view(_Rng&) -> ref_view<_Rng>; template inline constexpr bool enable_borrowed_range> = true; _EXPORT_STD template requires (movable<_Rng> && !_Is_initializer_list<_Rng>) class owning_view : public view_interface> { private: _Rng _Range{}; public: // clang-format off owning_view() requires default_initializable<_Rng> = default; // clang-format on constexpr owning_view(_Rng&& _Range_) noexcept(is_nothrow_move_constructible_v<_Rng>) // strengthened : _Range(_STD move(_Range_)) {} owning_view(owning_view&&) = default; owning_view& operator=(owning_view&&) = default; _NODISCARD constexpr _Rng& base() & noexcept { return _Range; } _NODISCARD constexpr const _Rng& base() const& noexcept { return _Range; } _NODISCARD constexpr _Rng&& base() && noexcept { return _STD move(_Range); } _NODISCARD constexpr const _Rng&& base() const&& noexcept { return _STD move(_Range); } _NODISCARD constexpr iterator_t<_Rng> begin() noexcept(noexcept(_RANGES begin(_Range))) /* strengthened */ { return _RANGES begin(_Range); } _NODISCARD constexpr sentinel_t<_Rng> end() noexcept(noexcept(_RANGES end(_Range))) /* strengthened */ { return _RANGES end(_Range); } _NODISCARD constexpr auto begin() const noexcept(noexcept(_RANGES begin(_Range))) /* strengthened */ requires range { return _RANGES begin(_Range); } _NODISCARD constexpr auto end() const noexcept(noexcept(_RANGES end(_Range))) /* strengthened */ requires range { return _RANGES end(_Range); } _NODISCARD constexpr bool empty() noexcept(noexcept(_RANGES empty(_Range))) /* strengthened */ requires _Can_empty<_Rng> { return _RANGES empty(_Range); } _NODISCARD constexpr bool empty() const noexcept(noexcept(_RANGES empty(_Range))) /* strengthened */ requires _Can_empty { return _RANGES empty(_Range); } _NODISCARD constexpr auto size() noexcept(noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range<_Rng> { return _RANGES size(_Range); } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(_Range))) /* strengthened */ requires sized_range { return _RANGES size(_Range); } _NODISCARD constexpr auto data() noexcept(noexcept(_RANGES data(_Range))) /* strengthened */ requires contiguous_range<_Rng> { return _RANGES data(_Range); } _NODISCARD constexpr auto data() const noexcept(noexcept(_RANGES data(_Range))) /* strengthened */ requires contiguous_range { return _RANGES data(_Range); } }; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { template concept _Can_ref_view = requires(_Rng&& __r) { ref_view{static_cast<_Rng&&>(__r)}; }; template concept _Ownable = requires(_Rng&& __r) { owning_view{static_cast<_Rng&&>(__r)}; }; class _All_fn : public _Pipe::_Base<_All_fn> { private: enum class _St { _None, _View, _Ref, _Own }; template _NODISCARD static consteval _Choice_t<_St> _Choose() noexcept { if constexpr (view>) { if constexpr (convertible_to<_Rng, remove_cvref_t<_Rng>>) { return {_St::_View, is_nothrow_convertible_v<_Rng, remove_cvref_t<_Rng>>}; } } else if constexpr (_Can_ref_view<_Rng>) { return {_St::_Ref, noexcept(ref_view{_STD declval<_Rng>()})}; } else if constexpr (_Ownable<_Rng>) { return {_St::_Own, noexcept(owning_view{_STD declval<_Rng>()})}; } return {_St::_None}; } template static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); public: template requires (_Choice<_Rng>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { 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::_Own) { return owning_view{_STD forward<_Rng>(_Range)}; } else { static_assert(_Always_false<_Rng>, "Should be unreachable"); } } }; _EXPORT_STD inline constexpr _All_fn all; _EXPORT_STD template using all_t = decltype(all(_STD declval<_Rng>())); } // namespace views #if _HAS_CXX23 _EXPORT_STD template requires view<_Vw> class as_rvalue_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; template static constexpr bool _Is_end_nothrow_v = noexcept(move_sentinel{_RANGES end(_STD declval<_Rng&>())}); template static constexpr bool _Is_end_nothrow_v<_Rng> = noexcept(move_iterator{_RANGES end(_STD declval<_Rng&>())}); public: // clang-format off as_rvalue_view() requires default_initializable<_Vw> = default; // clang-format on constexpr explicit as_rvalue_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() noexcept(noexcept(move_iterator{_RANGES begin(_Range)})) // strengthened requires (!_Simple_view<_Vw>) { return move_iterator{_RANGES begin(_Range)}; } _NODISCARD constexpr auto begin() const noexcept(noexcept(move_iterator{_RANGES begin(_Range)})) // strengthened requires range { return move_iterator{_RANGES begin(_Range)}; } _NODISCARD constexpr auto end() noexcept(_Is_end_nothrow_v<_Vw>) // strengthened requires (!_Simple_view<_Vw>) { if constexpr (common_range<_Vw>) { return move_iterator{_RANGES end(_Range)}; } else { return move_sentinel{_RANGES end(_Range)}; } } _NODISCARD constexpr auto end() const noexcept(_Is_end_nothrow_v) // strengthened requires range { if constexpr (common_range) { return move_iterator{_RANGES end(_Range)}; } else { return move_sentinel{_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 { return _RANGES size(_Range); } }; template as_rvalue_view(_Rng&&) -> as_rvalue_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { template concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view{static_cast<_Rng&&>(__r)}; }; class _As_rvalue_fn : public _Pipe::_Base<_As_rvalue_fn> { private: enum class _St { _None, _All, _As_rvalue }; template _NODISCARD static consteval _Choice_t<_St> _Choose() noexcept { if constexpr (same_as, range_reference_t<_Rng>>) { return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))}; } else if constexpr (_Can_as_rvalue<_Rng>) { return {_St::_As_rvalue, noexcept(as_rvalue_view{_STD declval<_Rng>()})}; } else { return {_St::_None}; } } template static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); public: template requires (_Choice<_Rng>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { constexpr _St _Strat = _Choice<_Rng>._Strategy; if constexpr (_Strat == _St::_All) { return views::all(_STD forward<_Rng>(_Range)); } else if constexpr (_Strat == _St::_As_rvalue) { return as_rvalue_view{_STD forward<_Rng>(_Range)}; } else { static_assert(_Always_false<_Rng>, "Should be unreachable"); } } }; _EXPORT_STD inline constexpr _As_rvalue_fn as_rvalue; } // namespace views #endif // _HAS_CXX23 _EXPORT_STD template > _Pr> requires view<_Vw> && is_object_v<_Pr> class filter_view : public _Cached_position_t, _Vw, filter_view<_Vw, _Pr>> { private: /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Movable_box<_Pr> _Pred{}; template struct _Category_base {}; template struct _Category_base<_View> { using iterator_category = conditional_t>, bidirectional_iterator_tag>, bidirectional_iterator_tag, conditional_t>, forward_iterator_tag>, forward_iterator_tag, _Iter_cat_t>>>; }; class _Iterator : public _Category_base<_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_iterator_tag, conditional_t, 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> = default; // clang-format on constexpr _Iterator(filter_view& _Parent_, iterator_t<_Vw> _Current_) noexcept( is_nothrow_move_constructible_v>) // 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 const iterator_t<_Vw>& base() const& noexcept { return _Current; } _NODISCARD constexpr iterator_t<_Vw> base() && noexcept( is_nothrow_move_constructible_v>) /* 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>) /* strengthened */ requires _Has_arrow> && copyable> { // 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> { #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> { #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 noexcept(noexcept(_Fake_copy_init(_Current == _Last))) { 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>) // strengthened : _Last(_RANGES end(_Parent._Range)) {} _NODISCARD constexpr sentinel_t<_Vw> base() const noexcept(is_nothrow_copy_constructible_v>) /* strengthened */ { return _Last; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _It, const _Sentinel& _Se) noexcept( noexcept(_It._Equal(_Se._Last))) /* strengthened */ { return _It._Equal(_Se._Last); } }; public: // clang-format off filter_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default; // clang-format on constexpr explicit 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, "N4928 [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 filter_view(_Rng&&, _Pr) -> filter_view, _Pr>; namespace views { struct _Filter_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr&& _Pred) const noexcept(noexcept( filter_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)))) requires requires { filter_view(static_cast<_Rng&&>(_Range), _STD forward<_Pr>(_Pred)); } { // clang-format on return filter_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)); } template requires constructible_from, _Pr> _NODISCARD constexpr auto operator()(_Pr&& _Pred) const noexcept(is_nothrow_constructible_v, _Pr>) { return _Range_closure<_Filter_fn, decay_t<_Pr>>{_STD forward<_Pr>(_Pred)}; } }; _EXPORT_STD inline constexpr _Filter_fn filter; } // namespace views #ifdef __clang__ template // TRANSITION, LLVM-47414 concept _Can_const_transform = range && regular_invocable>; #endif // ^^^ workaround ^^^ _EXPORT_STD template requires view<_Vw> && regular_invocable<_Fn&, range_reference_t<_Vw>> && _Can_reference>> class transform_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Movable_box<_Fn> _Fun{}; template struct _Category_base {}; template requires forward_range<_Maybe_const<_Const, _Vw>> struct _Category_base<_Const> { using _Base = _Maybe_const<_Const, _Vw>; using iterator_category = conditional_t&, range_reference_t<_Base>>>, conditional_t>, contiguous_iterator_tag>, random_access_iterator_tag, _Iter_cat_t>>, input_iterator_tag>; }; template class _Iterator : public _Category_base<_Const> { private: friend transform_view; 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 noexcept { _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_iterator_tag, conditional_t, bidirectional_iterator_tag, conditional_t, forward_iterator_tag, input_iterator_tag>>>; using value_type = remove_cvref_t&, range_reference_t<_Base>>>; using difference_type = range_difference_t<_Base>; // clang-format off _Iterator() requires default_initializable> = default; // clang-format on constexpr _Iterator(_Parent_t& _Parent_, iterator_t<_Base> _Current_) noexcept( is_nothrow_move_constructible_v>) // 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 } constexpr _Iterator(_Iterator _It) noexcept( is_nothrow_constructible_v, iterator_t<_Vw>>) // strengthened requires _Const && convertible_to, iterator_t<_Base>> : _Current(_STD move(_It._Current)), _Parent(_It._Parent) {} _NODISCARD constexpr const iterator_t<_Base>& base() const& noexcept { return _Current; } _NODISCARD constexpr iterator_t<_Base> base() && noexcept( is_nothrow_move_constructible_v>) /* strengthened */ { return _STD move(_Current); } _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(_STD invoke(*_Parent->_Fun, *_Current))) { #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>) ) /* 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>) /* strengthened */ requires bidirectional_range<_Base> { auto _Tmp = *this; --*this; return _Tmp; } #if _ITERATOR_DEBUG_LEVEL != 0 constexpr void _Verify_offset(const difference_type _Off) const noexcept requires random_access_range<_Base> { _STL_VERIFY(_Off == 0 || _Parent, "cannot seek value-initialized transform_view iterator"); if constexpr (_Offset_verifiable_v>) { _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 _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _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 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> { #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> { // 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, const difference_type _Off) noexcept( 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+(const difference_type _Off, _Iterator _It) noexcept( 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, const difference_type _Off) noexcept( noexcept(_It._Current -= _Off)) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _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>> { #if _ITERATOR_DEBUG_LEVEL != 0 _Left._Same_range(_Right); #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Left._Current - _Right._Current; } }; template class _Sentinel { private: friend transform_view; using _Parent_t = _Maybe_const<_Const, transform_view>; using _Base = _Maybe_const<_Const, _Vw>; template using _Maybe_const_iter = iterator_t<_Maybe_const<_OtherConst, _Vw>>; sentinel_t<_Base> _Last{}; template _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>) // strengthened : _Last(_STD move(_Last_)) {} // clang-format off constexpr _Sentinel(_Sentinel _Se) noexcept(is_nothrow_constructible_v, sentinel_t<_Vw>>) // strengthened requires _Const && convertible_to, sentinel_t<_Base>> : _Last(_STD move(_Se._Last)) {} // clang-format on _NODISCARD constexpr sentinel_t<_Base> base() const noexcept(is_nothrow_copy_constructible_v>) /* strengthened */ { return _Last; } template requires sentinel_for, _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; } // clang-format off template requires sized_sentinel_for, _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; } // clang-format on template requires sized_sentinel_for, _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: // clang-format off transform_view() requires default_initializable<_Vw> && default_initializable<_Fn> = default; // clang-format on constexpr explicit 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 begin() noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ { return _Iterator{*this, _RANGES begin(_Range)}; } _NODISCARD constexpr _Iterator begin() const noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_const_transform<_Vw, _Fn> #else // ^^^ workaround / no workaround vvv requires range && regular_invocable> #endif // TRANSITION, LLVM-47414 { return _Iterator{*this, _RANGES begin(_Range)}; } // clang-format off _NODISCARD constexpr auto end() noexcept(noexcept( _RANGES end(_Range)) && is_nothrow_move_constructible_v) /* strengthened */ { // clang-format on if constexpr (common_range<_Vw>) { return _Iterator{*this, _RANGES end(_Range)}; } else { return _Sentinel{_RANGES end(_Range)}; } } // clang-format off _NODISCARD constexpr auto end() const noexcept(noexcept( _RANGES end(_Range)) && is_nothrow_move_constructible_v) /* strengthened */ #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_const_transform<_Vw, _Fn> #else // ^^^ workaround / no workaround vvv requires range && regular_invocable> #endif // TRANSITION, LLVM-47414 { // clang-format on if constexpr (common_range<_Vw>) { return _Iterator{*this, _RANGES end(_Range)}; } else { return _Sentinel{_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 { return _RANGES size(_Range); } }; template transform_view(_Rng&&, _Fn) -> transform_view, _Fn>; namespace views { struct _Transform_fn { // clang-format off template _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 requires constructible_from, _Fn> _NODISCARD constexpr auto operator()(_Fn&& _Fun) const noexcept(is_nothrow_constructible_v, _Fn>) { return _Range_closure<_Transform_fn, decay_t<_Fn>>{_STD forward<_Fn>(_Fun)}; } }; _EXPORT_STD inline constexpr _Transform_fn transform; } // namespace views _EXPORT_STD template class take_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; range_difference_t<_Vw> _Count = 0; template class _Sentinel { private: friend take_view; using _Base_t = _Maybe_const<_Const, _Vw>; using _Base_sentinel = _Maybe_wrapped<_Wrapped, sentinel_t<_Base_t>>; template using _Base_iterator = _Maybe_wrapped<_Wrapped, iterator_t<_Maybe_const<_OtherConst, _Vw>>>; template 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 _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; } template requires sentinel_for<_Base_sentinel, _Base_iterator<_OtherConst>> _NODISCARD_FRIEND constexpr bool operator==( const _Counted_iter<_OtherConst>& _Left, const _Sentinel& _Right) { return _Left.count() == 0 || _Left.base() == _Right._Last; } using _Prevent_inheriting_unwrap = _Sentinel; // clang-format off _NODISCARD constexpr auto _Unwrapped() const& noexcept(noexcept(_Sentinel<_Const, false>{_Last._Unwrapped()})) requires _Wrapped && _Unwrappable_sentinel_for, const iterator_t<_Base_t>&> { // clang-format on return _Sentinel<_Const, false>{_Last._Unwrapped()}; } // clang-format off _NODISCARD constexpr auto _Unwrapped() && noexcept(noexcept(_Sentinel<_Const, false>{_STD move(_Last)._Unwrapped()})) requires _Wrapped && _Unwrappable_sentinel_for, iterator_t<_Base_t>> { // clang-format on return _Sentinel<_Const, false>{_STD move(_Last)._Unwrapped()}; } static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v>; 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 explicit 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>(size()); return counted_iterator(_RANGES begin(_Range), _Size); } } else if constexpr (sized_sentinel_for, iterator_t<_Vw>>) { auto _Iter = _RANGES begin(_Range); const auto _Size = (_STD min)(_Count, _RANGES end(_Range) - _Iter); return counted_iterator(_STD move(_Iter), _Size); } else { return counted_iterator(_RANGES begin(_Range), _Count); } } _NODISCARD constexpr auto begin() const requires range { if constexpr (sized_range) { if constexpr (random_access_range) { return _RANGES begin(_Range); } else { const auto _Size = static_cast>(size()); return counted_iterator(_RANGES begin(_Range), _Size); } } else if constexpr (sized_sentinel_for, iterator_t>) { auto _Iter = _RANGES begin(_Range); const auto _Size = (_STD min)(_Count, _RANGES end(_Range) - _Iter); return counted_iterator(_STD move(_Iter), _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>(size()); } else { return default_sentinel; } } else if constexpr (sized_sentinel_for, iterator_t<_Vw>>) { return default_sentinel; } else { return _Sentinel{_RANGES end(_Range)}; } } _NODISCARD constexpr auto end() const requires range { if constexpr (sized_range) { if constexpr (random_access_range) { return _RANGES begin(_Range) + static_cast>(size()); } else { return default_sentinel; } } else if constexpr (sized_sentinel_for, iterator_t>) { return default_sentinel; } else { return _Sentinel{_RANGES end(_Range)}; } } _NODISCARD constexpr auto size() requires sized_range<_Vw> { const auto _Length = _RANGES size(_Range); return (_STD min)(_Length, static_cast(_Count)); } _NODISCARD constexpr auto size() const requires sized_range { const auto _Length = _RANGES size(_Range); return (_STD min)(_Length, static_cast(_Count)); } }; template take_view(_Rng&&, range_difference_t<_Rng>) -> take_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { template concept _Random_sized_range = random_access_range<_Rng> && sized_range<_Rng>; class _Take_fn { private: enum class _St { _Empty, _Reconstruct_span, _Reconstruct_string_view, _Reconstruct_iota_view, _Reconstruct_repeat_view, _Reconstruct_subrange, _Take_view }; template _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&>()))}; #if _HAS_CXX23 } else if constexpr (_Is_specialization_v<_Ty, repeat_view>) { using _Range_val_t = range_value_t<_Ty>; return {_St::_Reconstruct_repeat_view, is_nothrow_constructible_v<_Range_val_t, _Forward_like_t<_Rng, _Range_val_t>>}; #endif // _HAS_CXX23 } else if constexpr (_Random_sized_range<_Ty> && _Is_subrange_v<_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 static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); public: template _NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const noexcept(_Choice<_Rng>._No_throw) { 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); #if _HAS_CXX23 } else if constexpr (!sized_range<_Rng> && _Strat == _St::_Reconstruct_repeat_view) { return repeat_view(_STD forward_like<_Rng>(*_Range._Value), _Count); #endif } 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); 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); #if _HAS_CXX23 } else if constexpr (_Strat == _St::_Reconstruct_repeat_view) { return repeat_view(_STD forward_like<_Rng>(*_Range._Value), _Count); #endif } else if constexpr (_Strat == _St::_Reconstruct_subrange) { return subrange(_First, _First + _Count); } else { static_assert(_Always_false<_Rng>, "Should be unreachable"); } } } template requires constructible_from, _Ty> _NODISCARD constexpr auto operator()(_Ty&& _Length) const noexcept(is_nothrow_constructible_v, _Ty>) { return _Range_closure<_Take_fn, decay_t<_Ty>>{_STD forward<_Ty>(_Length)}; } }; _EXPORT_STD inline constexpr _Take_fn take; } // namespace views #ifdef __clang__ template // TRANSITION, LLVM-47414 concept _Can_take_while_const = range && indirect_unary_predicate>; #endif // ^^^ workaround ^^^ _EXPORT_STD template requires input_range<_Vw> && is_object_v<_Pr> && indirect_unary_predicate> class take_while_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Movable_box<_Pr> _Pred{}; template class _Sentinel { private: friend take_while_view; 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 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 _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); } template requires sentinel_for<_Base_sentinel, _Maybe_const_iter<_OtherConst>> _NODISCARD_FRIEND constexpr bool operator==( const _Maybe_const_iter<_OtherConst>& _Left, const _Sentinel& _Right) { return _Right._Last == _Left || !_STD invoke(*_Right._Pred, *_Left); } using _Prevent_inheriting_unwrap = _Sentinel; // clang-format off _NODISCARD constexpr auto _Unwrapped() const& noexcept(noexcept(_Sentinel<_Const, false>{_Last._Unwrapped(), _Pred})) requires _Wrapped && _Unwrappable_sentinel_for, const iterator_t<_Base_t>&> { // clang-format on return _Sentinel<_Const, false>{_Last._Unwrapped(), _Pred}; } // clang-format off _NODISCARD constexpr auto _Unwrapped() && noexcept(noexcept(_Sentinel<_Const, false>{_STD move(_Last)._Unwrapped(), _Pred})) requires _Wrapped && _Unwrappable_sentinel_for, iterator_t<_Base_t>> { // clang-format on return _Sentinel<_Const, false>{_STD move(_Last)._Unwrapped(), _Pred}; } static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v>; 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 explicit 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; } _NODISCARD constexpr auto begin() noexcept(noexcept(_RANGES begin(_Range))) /* strengthened */ requires (!_Simple_view<_Vw>) { return _RANGES begin(_Range); } _NODISCARD constexpr auto begin() const noexcept(noexcept(_RANGES begin(_Range))) /* strengthened */ #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_take_while_const<_Vw, _Pr> #else // ^^^ workaround / no workaround vvv requires range && indirect_unary_predicate> #endif // TRANSITION, LLVM-47414 { return _RANGES begin(_Range); } _NODISCARD constexpr auto end() noexcept( noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel>) /* strengthened */ requires (!_Simple_view<_Vw>) { #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{_RANGES end(_Range), _STD addressof(*_Pred)}; } _NODISCARD constexpr auto end() const noexcept( noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel>) /* strengthened */ #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_take_while_const<_Vw, _Pr> #else // ^^^ workaround / no workaround vvv requires range && indirect_unary_predicate> #endif // TRANSITION, LLVM-47414 { #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{_RANGES end(_Range), _STD addressof(*_Pred)}; } }; template take_while_view(_Rng&&, _Pr) -> take_while_view, _Pr>; namespace views { struct _Take_while_fn { template _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 requires constructible_from, _Pr> _NODISCARD constexpr auto operator()(_Pr&& _Pred) const noexcept(is_nothrow_constructible_v, _Pr>) { return _Range_closure<_Take_while_fn, decay_t<_Pr>>{_STD forward<_Pr>(_Pred)}; } }; _EXPORT_STD inline constexpr _Take_while_fn take_while; } // namespace views _EXPORT_STD template class drop_view : public _Cached_position_t && !(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 explicit 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, "Number of elements to drop must be non-negative (N4928 [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 && sized_range)) { // 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> 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 && sized_range { // 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 { 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>(_Count); if (_Size < _Count_as_size) { return range_size_t<_Vw>{0}; } else { return static_cast>(_Size - _Count_as_size); } } _NODISCARD constexpr auto size() const requires sized_range { const auto _Size = _RANGES size(_Range); const auto _Count_as_size = static_cast>(_Count); if (_Size < _Count_as_size) { return range_size_t<_Vw>{0}; } else { return static_cast>(_Size - _Count_as_size); } } }; template drop_view(_Rng&&, range_difference_t<_Rng>) -> drop_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { class _Drop_fn { private: enum class _St { _Empty, _Reconstruct_span, _Reconstruct_subrange, _Reconstruct_repeat, _Reconstruct_other, _Drop_view }; template _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}; #if _HAS_CXX23 } else if constexpr (_Is_specialization_v<_Ty, repeat_view>) { using _Range_val_t = range_value_t<_Ty>; return {_St::_Reconstruct_repeat, is_nothrow_constructible_v<_Range_val_t, _Forward_like_t<_Rng, _Range_val_t>>}; #endif // _HAS_CXX23 } else if constexpr (_Random_sized_range<_Ty> && _Is_subrange_v<_Ty>) { if constexpr (sized_sentinel_for, 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 static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); public: template _NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const noexcept(_Choice<_Rng>._No_throw) { 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); #if _HAS_CXX23 } else if constexpr (_Strat == _St::_Reconstruct_repeat) { if constexpr (sized_range<_Rng>) { const auto _Size = _RANGES distance(_Range); _Count = _Size - (_STD min)(_Size, _Count); return repeat_view(_STD forward_like<_Rng>(*_Range._Value), _Count); } else { return _Range; } #endif // _HAS_CXX23 } else { // it's a "reconstructible range"; return the same kind of range with a restricted extent _Count = (_STD min)(_RANGES distance(_Range), _Count); 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, 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 requires constructible_from, _Ty> _NODISCARD constexpr auto operator()(_Ty&& _Length) const noexcept(is_nothrow_constructible_v, _Ty>) { return _Range_closure<_Drop_fn, decay_t<_Ty>>{_STD forward<_Ty>(_Length)}; } }; _EXPORT_STD inline constexpr _Drop_fn drop; } // namespace views _EXPORT_STD template requires input_range<_Vw> && is_object_v<_Pr> && indirect_unary_predicate> class drop_while_view : public _Cached_position_t, _Vw, drop_while_view<_Vw, _Pr>> { private: /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Movable_box<_Pr> _Pred{}; public: // clang-format off drop_while_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default; // clang-format on constexpr explicit 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, "N4928 [range.drop.while.view]/3 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 drop_while_view(_Rng&&, _Pr) -> drop_while_view, _Pr>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { struct _Drop_while_fn { template _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 requires constructible_from, _Pr> _NODISCARD constexpr auto operator()(_Pr&& _Pred) const noexcept(is_nothrow_constructible_v, _Pr>) { return _Range_closure<_Drop_while_fn, decay_t<_Pr>>{_STD forward<_Pr>(_Pred)}; } }; _EXPORT_STD inline constexpr _Drop_while_fn drop_while; } // namespace views #ifdef __clang__ template // TRANSITION, LLVM-47414 concept _Can_const_join = forward_range && is_reference_v> && input_range>; #endif // ^^^ workaround ^^^ template _NODISCARD constexpr _Ty& _As_lvalue(_Ty&& _Val) noexcept { return static_cast<_Ty&>(_Val); } _EXPORT_STD template requires view<_Vw> && input_range> class join_view; template class _Join_view_base : public view_interface> { private: struct _Cache_wrapper { template constexpr _Cache_wrapper(_Not_quite_object::_Construct_tag, const _Iter& _It) noexcept( noexcept(static_cast(*_It))) : _Val(*_It) {} remove_cv_t> _Val; }; protected: /* [[no_unique_address]] */ _Non_propagating_cache<_Cache_wrapper, false> _Inner{}; }; template requires is_reference_v> class _Join_view_base<_Vw> : public view_interface> {}; template class _Join_view_outer_iter_base : public _Join_view_base<_Vw> { protected: _Non_propagating_cache> _Outer; }; template class _Join_view_outer_iter_base<_Vw> : public _Join_view_base<_Vw> {}; _EXPORT_STD template requires view<_Vw> && input_range> class join_view : public _Join_view_outer_iter_base<_Vw> { private: template using _InnerRng = range_reference_t<_Maybe_const<_Const, _Vw>>; /* [[no_unique_address]] */ _Vw _Range{}; template struct _Category_base {}; template struct _Category_base<_Outer, _Inner, true> { using iterator_category = conditional_t && derived_from<_Iter_cat_t>, bidirectional_iterator_tag> && derived_from<_Iter_cat_t>, bidirectional_iterator_tag>, bidirectional_iterator_tag, conditional_t>, forward_iterator_tag> && derived_from<_Iter_cat_t>, forward_iterator_tag>, forward_iterator_tag, input_iterator_tag>>; }; template class _Iterator_base : public _Category_base<_Maybe_const<_Const, _Vw>, _InnerRng<_Const>, is_reference_v<_InnerRng<_Const>>> {}; template requires forward_range<_Maybe_const<_Const, _Vw>> class _Iterator_base<_Const> : public _Category_base<_Maybe_const<_Const, _Vw>, _InnerRng<_Const>, is_reference_v<_InnerRng<_Const>>> { protected: using _OuterIter = iterator_t<_Maybe_const<_Const, _Vw>>; _Iterator_base() = default; constexpr explicit _Iterator_base(_OuterIter&& _Outer_) : _Outer(_STD move(_Outer_)) {} /* [[no_unique_address]] */ _OuterIter _Outer{}; }; template class _Iterator : public _Iterator_base<_Const> { private: friend join_view; using _Mybase = _Iterator_base<_Const>; 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]] */ _Defaultabox<_InnerIter> _Inner{}; // Non-standard extension: when _Inner_iter // is default-constructible, we don't wrap in // an optional-like. _Parent_t* _Parent{}; constexpr _Iterator(_Parent_t& _Parent_, _OuterIter _Outer_) requires forward_range<_Base> : _Mybase{_STD move(_Outer_)}, _Parent{_STD addressof(_Parent_)} { #if _ITERATOR_DEBUG_LEVEL != 0 _Adl_verify_range(this->_Outer, _RANGES end(_Parent_._Range)); _Adl_verify_range(_RANGES begin(_Parent_._Range), this->_Outer); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Satisfy(); } constexpr explicit _Iterator(_Parent_t& _Parent) requires (!forward_range<_Base>) : _Parent{_STD addressof(_Parent)} { _Satisfy(); } _NODISCARD constexpr _OuterIter& _Get_outer() noexcept { if constexpr (forward_range<_Base>) { return this->_Outer; } else { return *_Parent->_Outer; } } _NODISCARD constexpr const _OuterIter& _Get_outer() const noexcept { if constexpr (forward_range<_Base>) { return this->_Outer; } else { return *_Parent->_Outer; } } constexpr auto&& _Update_inner() { if constexpr (_Deref_is_glvalue) { return *_Get_outer(); } else { return _Parent->_Inner._Emplace(_Not_quite_object::_Construct_tag{}, _Get_outer())._Val; } } constexpr void _Satisfy() { auto& _Outer = _Get_outer(); const auto _Last = _RANGES end(_Parent->_Range); for (; _Outer != _Last; ++_Outer) { auto&& _Tmp = _Update_inner(); _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(_Get_outer() != _RANGES end(_Parent->_Range), "cannot dereference join_view end iterator"); sentinel_t<_InnerRng<_Const>> _Last; if constexpr (_Deref_is_glvalue) { _Last = _RANGES end(_As_lvalue(*_Get_outer())); } else { _Last = _RANGES end((*_Parent->_Inner)._Val); } _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 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<_InnerRng<_Const>>>; // clang-format off _Iterator() requires default_initializable<_OuterIter> = default; // clang-format on constexpr _Iterator(_Iterator _It) requires _Const && convertible_to, _OuterIter> && convertible_to>, _InnerIter> : _Mybase(_STD move(_It._Outer)), _Inner(_STD move(_It._Inner)), _Parent(_It._Parent) {} _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++() { auto& _Outer = _Get_outer(); if constexpr (_Deref_is_glvalue) { if (++*_Inner == _RANGES end(_As_lvalue(*_Outer))) { ++_Outer; _Satisfy(); } } else { if (++*_Inner == _RANGES end((*_Parent->_Inner)._Val)) { ++_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 auto& _Outer = _Get_outer(); if (_Outer == _RANGES end(_Parent->_Range)) { --_Outer; _Inner = _RANGES end(_As_lvalue(*_Outer)); } while (*_Inner == _RANGES begin(_As_lvalue(*_Outer))) { --_Outer; *_Inner = _RANGES end(_As_lvalue(*_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(_Fake_copy_init(_Left._Outer == _Right._Outer && _Left._Inner == _Right._Inner))) /* strengthened */ requires _Deref_is_glvalue && forward_range<_Base> && 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 class _Sentinel { private: friend join_view; using _Parent_t = _Maybe_const<_Const, join_view>; using _Base = _Maybe_const<_Const, _Vw>; template using _Maybe_const_iter = iterator_t<_Maybe_const<_OtherConst, _Vw>>; /* [[no_unique_address]] */ sentinel_t<_Base> _Last{}; // clang-format off template requires sentinel_for, _Maybe_const_iter<_OtherConst>> _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const noexcept( noexcept(_Fake_copy_init(_It._Get_outer() == _Last))) { // clang-format on return _It._Get_outer() == _Last; } public: _Sentinel() = default; constexpr explicit _Sentinel(_Parent_t& _Parent) noexcept( noexcept(_RANGES end(_Parent._Range)) && is_nothrow_move_constructible_v>) // strengthened : _Last(_RANGES end(_Parent._Range)) {} // clang-format off constexpr _Sentinel(_Sentinel _Se) noexcept(is_nothrow_constructible_v, sentinel_t<_Vw>>) // strengthened requires _Const && convertible_to, sentinel_t<_Base>> : _Last(_STD move(_Se._Last)) {} // clang-format on template requires sentinel_for, _Maybe_const_iter<_OtherConst>> _NODISCARD_FRIEND constexpr bool operator==(const _Iterator<_OtherConst>& _Left, const _Sentinel& _Right) noexcept(noexcept(_Right._Equal(_Left))) /* strengthened */ { 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() { if constexpr (forward_range<_Vw>) { constexpr bool _Use_const = _Simple_view<_Vw> && is_reference_v<_InnerRng>; return _Iterator<_Use_const>{*this, _RANGES begin(_Range)}; } else { this->_Outer._Emplace(_RANGES begin(_Range)); return _Iterator{*this}; } } _NODISCARD constexpr _Iterator begin() const #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_const_join<_Vw> #else // ^^^ workaround / no workaround vvv requires forward_range && is_reference_v<_InnerRng> && input_range<_InnerRng> #endif // TRANSITION, LLVM-47414 { return _Iterator{*this, _RANGES begin(_Range)}; } _NODISCARD constexpr auto end() { if constexpr (forward_range<_Vw> && is_reference_v<_InnerRng> // && forward_range<_InnerRng> && common_range<_Vw> && common_range<_InnerRng>) { return _Iterator<_Simple_view<_Vw>>{*this, _RANGES end(_Range)}; } else { return _Sentinel<_Simple_view<_Vw>>{*this}; } } _NODISCARD constexpr auto end() const #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_const_join<_Vw> #else // ^^^ workaround / no workaround vvv requires forward_range && is_reference_v<_InnerRng> && input_range<_InnerRng> #endif // TRANSITION, LLVM-47414 { if constexpr (forward_range<_InnerRng> && common_range && common_range<_InnerRng>) { return _Iterator{*this, _RANGES end(_Range)}; } else { return _Sentinel{*this}; } } }; template explicit join_view(_Rng&&) -> join_view>; namespace views { class _Join_fn : public _Pipe::_Base<_Join_fn> { public: // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(noexcept( join_view>{_STD forward<_Rng>(_Range)})) requires requires { join_view>{static_cast<_Rng&&>(_Range)}; } { // clang-format on return join_view>{_STD forward<_Rng>(_Range)}; } }; _EXPORT_STD inline constexpr _Join_fn join; } // namespace views #if _HAS_CXX23 template concept _Compatible_joinable_ranges = common_with, range_value_t<_Pat>> && common_reference_with, range_reference_t<_Pat>> && common_reference_with, range_rvalue_reference_t<_Pat>>; #ifdef __clang__ template // TRANSITION, LLVM-47414 concept _Can_const_join_with = forward_range && forward_range && is_reference_v> && input_range>; #endif // ^^^ workaround ^^^ _EXPORT_STD template requires view<_Vw> && input_range> && view<_Pat> && _Compatible_joinable_ranges, _Pat> class join_with_view; template class _Join_with_view_base : public view_interface> { private: struct _Cache_wrapper { template constexpr _Cache_wrapper(_Not_quite_object::_Construct_tag, const _Iter& _It) noexcept( noexcept(static_cast(*_It))) : _Val(*_It) {} remove_cv_t> _Val; }; protected: /* [[no_unique_address]] */ _Non_propagating_cache<_Cache_wrapper, false> _Inner{}; }; template requires is_reference_v> class _Join_with_view_base<_Vw, _Pat> : public view_interface> {}; template class _Join_with_view_outer_iter_base : public _Join_with_view_base<_Vw, _Pat> { protected: _Non_propagating_cache> _Outer_it; }; template class _Join_with_view_outer_iter_base<_Vw, _Pat> : public _Join_with_view_base<_Vw, _Pat> {}; _EXPORT_STD template requires view<_Vw> && input_range> && view<_Pat> && _Compatible_joinable_ranges, _Pat> class join_with_view : public _Join_with_view_outer_iter_base<_Vw, _Pat> { private: template using _InnerRng = range_reference_t<_Maybe_const<_Const, _Vw>>; /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Pat _Pattern{}; template struct _Category_base {}; template requires forward_range<_Maybe_const<_Const, _Vw>> && forward_range<_InnerRng<_Const>> && is_reference_v<_InnerRng<_Const>> struct _Category_base<_Const> { using _Outer = _Maybe_const<_Const, _Vw>; using _Inner = _InnerRng<_Const>; using _PatternBase = _Maybe_const<_Const, _Pat>; using iterator_category = conditional_t< !is_reference_v, range_reference_t<_PatternBase>>>, input_iterator_tag, conditional_t && common_range<_PatternBase> && derived_from<_Iter_cat_t>, bidirectional_iterator_tag> && derived_from<_Iter_cat_t>, bidirectional_iterator_tag> && derived_from<_Iter_cat_t>, bidirectional_iterator_tag>, bidirectional_iterator_tag, conditional_t>, forward_iterator_tag> && derived_from<_Iter_cat_t>, forward_iterator_tag> && derived_from<_Iter_cat_t>, forward_iterator_tag>, forward_iterator_tag, input_iterator_tag>>>; }; template class _Iterator_base : public _Category_base<_Const> {}; template requires forward_range<_Maybe_const<_Const, _Vw>> class _Iterator_base<_Const> : public _Category_base<_Const> { protected: using _OuterIter = iterator_t<_Maybe_const<_Const, _Vw>>; _Iterator_base() = default; constexpr explicit _Iterator_base(_OuterIter&& _Outer_it_) : _Outer_it(_STD move(_Outer_it_)) {} /* [[no_unique_address]] */ _OuterIter _Outer_it{}; }; template class _Iterator : public _Iterator_base<_Const> { private: friend join_with_view; using _Mybase = _Iterator_base<_Const>; using _Parent_t = _Maybe_const<_Const, join_with_view>; using _Base = _Maybe_const<_Const, _Vw>; using _PatternBase = _Maybe_const<_Const, _Pat>; using _OuterIter = iterator_t<_Base>; using _InnerIter = iterator_t<_InnerRng<_Const>>; using _PatternIter = iterator_t<_PatternBase>; // 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>>; _Parent_t* _Parent{}; _Variantish<_PatternIter, _InnerIter> _Inner_it{}; constexpr _Iterator(_Parent_t& _Parent_, _OuterIter _Outer_) requires forward_range<_Base> : _Mybase(_STD move(_Outer_)), _Parent(_STD addressof(_Parent_)) { if (this->_Outer_it != _RANGES end(_Parent->_Range)) { _Inner_it._Emplace_second(_RANGES begin(_Update_inner())); _Satisfy(); } } constexpr explicit _Iterator(_Parent_t& _Parent_) requires (!forward_range<_Base>) : _Parent{_STD addressof(_Parent_)} { if (*_Parent->_Outer_it != _RANGES end(_Parent->_Range)) { _Inner_it._Emplace_second(_RANGES begin(_Update_inner())); _Satisfy(); } } _NODISCARD constexpr _OuterIter& _Get_outer() noexcept { if constexpr (forward_range<_Base>) { return this->_Outer_it; } else { return *_Parent->_Outer_it; } } _NODISCARD constexpr const _OuterIter& _Get_outer() const noexcept { if constexpr (forward_range<_Base>) { return this->_Outer_it; } else { return *_Parent->_Outer_it; } } _NODISCARD constexpr auto& _Update_inner() { if constexpr (_Deref_is_glvalue) { return _As_lvalue(*_Get_outer()); } else { return _Parent->_Inner._Emplace(_Not_quite_object::_Construct_tag{}, _Get_outer())._Val; } } _NODISCARD constexpr auto& _Get_inner() noexcept { if constexpr (_Deref_is_glvalue) { return _As_lvalue(*_Get_outer()); } else { return (*_Parent->_Inner)._Val; } } template constexpr _Ret _Visit_inner_it(auto&& _Func) const { if (_Inner_it._Contains == _Variantish_state::_Holds_first) { return _Func(_Inner_it._Get_first()); } else if (_Inner_it._Contains == _Variantish_state::_Holds_second) { return _Func(_Inner_it._Get_second()); } else { _STD _Throw_bad_variant_access(); } } constexpr void _Satisfy() { for (;;) { if (_Inner_it._Contains == _Variantish_state::_Holds_first) { if (_Inner_it._Get_first() != _RANGES end(_Parent->_Pattern)) { break; } _Inner_it._Emplace_second(_RANGES begin(_Update_inner())); } else { _STL_INTERNAL_CHECK(_Inner_it._Contains == _Variantish_state::_Holds_second); if (_Inner_it._Get_second() != _RANGES end(_Get_inner())) { break; } auto& _Outer_it = _Get_outer(); ++_Outer_it; if (_Outer_it == _RANGES end(_Parent->_Range)) { if constexpr (_Deref_is_glvalue) { _Inner_it._Emplace_first(); } break; } _Inner_it._Emplace_first(_RANGES begin(_Parent->_Pattern)); } } } public: using iterator_concept = // conditional_t<_Deref_is_glvalue && bidirectional_range<_Base> // && _Bidi_common_range<_InnerRng<_Const>> && _Bidi_common_range<_PatternBase>, bidirectional_iterator_tag, conditional_t<_Deref_is_glvalue && forward_range<_Base> && forward_range<_InnerRng<_Const>>, forward_iterator_tag, input_iterator_tag>>; using value_type = common_type_t, iter_value_t<_PatternIter>>; using difference_type = _Common_diff_t<_OuterIter, _InnerIter, _PatternIter>; // clang-format off _Iterator() requires default_initializable<_OuterIter> = default; // clang-format on constexpr _Iterator(_Iterator _It) requires _Const // && convertible_to, _OuterIter> // && convertible_to>, _InnerIter> // && convertible_to, _PatternIter> // : _Mybase(_STD move(_It._Outer_it)), _Parent(_It._Parent) { switch (_It._Inner_it._Contains) { case _Variantish_state::_Holds_first: _Inner_it._Emplace_first(_STD move(_It._Inner_it._Get_first())); break; case _Variantish_state::_Holds_second: _Inner_it._Emplace_second(_STD move(_It._Inner_it._Get_second())); break; case _Variantish_state::_Nothing: _STD _Throw_bad_variant_access(); } } _NODISCARD constexpr decltype(auto) operator*() const { using _Ref = common_reference_t, iter_reference_t<_PatternIter>>; return _Visit_inner_it<_Ref>([](auto&& _It) -> _Ref { return *_It; }); } constexpr _Iterator& operator++() { switch (_Inner_it._Contains) { case _Variantish_state::_Holds_first: ++_Inner_it._Get_first(); break; case _Variantish_state::_Holds_second: ++_Inner_it._Get_second(); break; case _Variantish_state::_Nothing: _STD _Throw_bad_variant_access(); } _Satisfy(); return *this; } constexpr void operator++(int) { ++*this; } constexpr _Iterator operator++(int) requires _Deref_is_glvalue && forward_iterator<_OuterIter> && forward_iterator<_InnerIter> { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() requires _Deref_is_glvalue && bidirectional_range<_Base> // && _Bidi_common_range<_InnerRng<_Const>> && _Bidi_common_range<_PatternBase> { auto& _Outer_it = _Get_outer(); if (_Outer_it == _RANGES end(_Parent->_Range)) { --_Outer_it; _Inner_it._Emplace_second(_RANGES end(_Get_inner())); } for (;;) { if (_Inner_it._Contains == _Variantish_state::_Holds_first) { auto& _It = _Inner_it._Get_first(); if (_It == _RANGES begin(_Parent->_Pattern)) { --_Outer_it; _Inner_it._Emplace_second(_RANGES end(_Get_inner())); } else { break; } } else if (_Inner_it._Contains == _Variantish_state::_Holds_second) { auto& _It = _Inner_it._Get_second(); if (_It == _RANGES begin(_Get_inner())) { _Inner_it._Emplace_first(_RANGES end(_Parent->_Pattern)); } else { break; } } else { _STD _Throw_bad_variant_access(); } } switch (_Inner_it._Contains) { case _Variantish_state::_Holds_first: --_Inner_it._Get_first(); break; case _Variantish_state::_Holds_second: --_Inner_it._Get_second(); break; case _Variantish_state::_Nothing: _STD _Throw_bad_variant_access(); } return *this; } constexpr _Iterator operator--(int) requires _Deref_is_glvalue && bidirectional_range<_Base> // && _Bidi_common_range<_InnerRng<_Const>> && _Bidi_common_range<_PatternBase> { auto _Tmp = *this; --*this; return _Tmp; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) requires _Deref_is_glvalue && forward_range<_Base> && equality_comparable<_InnerIter> { if (_Left._Outer_it != _Right._Outer_it) { return false; } if (_Left._Inner_it._Contains != _Right._Inner_it._Contains) { return false; } switch (_Left._Inner_it._Contains) { case _Variantish_state::_Holds_first: return _Left._Inner_it._Get_first() == _Right._Inner_it._Get_first(); case _Variantish_state::_Holds_second: return _Left._Inner_it._Get_second() == _Right._Inner_it._Get_second(); case _Variantish_state::_Nothing: return true; } _STL_UNREACHABLE; } _NODISCARD_FRIEND constexpr decltype(auto) iter_move(const _Iterator& _It) { using _Rvalue_ref = common_reference_t, iter_rvalue_reference_t<_PatternIter>>; return _It._Visit_inner_it<_Rvalue_ref>(_RANGES iter_move); } friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) requires indirectly_swappable<_InnerIter, _PatternIter> { switch (_Left._Inner_it._Contains) { case _Variantish_state::_Holds_first: switch (_Right._Inner_it._Contains) { case _Variantish_state::_Holds_first: return _RANGES iter_swap(_Left._Inner_it._Get_first(), _Right._Inner_it._Get_first()); case _Variantish_state::_Holds_second: return _RANGES iter_swap(_Left._Inner_it._Get_first(), _Right._Inner_it._Get_second()); case _Variantish_state::_Nothing: break; } break; case _Variantish_state::_Holds_second: switch (_Right._Inner_it._Contains) { case _Variantish_state::_Holds_first: return _RANGES iter_swap(_Left._Inner_it._Get_second(), _Right._Inner_it._Get_first()); case _Variantish_state::_Holds_second: return _RANGES iter_swap(_Left._Inner_it._Get_second(), _Right._Inner_it._Get_second()); case _Variantish_state::_Nothing: break; } break; case _Variantish_state::_Nothing: break; } _STD _Throw_bad_variant_access(); } }; template class _Sentinel { private: friend join_with_view; using _Parent_t = _Maybe_const<_Const, join_with_view>; using _Base = _Maybe_const<_Const, _Vw>; /* [[no_unique_address]] */ sentinel_t<_Base> _Last{}; constexpr explicit _Sentinel(_Parent_t& _Parent) noexcept( noexcept(_RANGES end(_Parent._Range)) && is_nothrow_move_constructible_v>) // strengthened : _Last(_RANGES end(_Parent._Range)) {} template _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const noexcept(noexcept(_Fake_copy_init(_It._Get_outer() == _Last))) { _STL_INTERNAL_STATIC_ASSERT( sentinel_for, iterator_t<_Maybe_const<_OtherConst, _Vw>>>); return _It._Get_outer() == _Last; } public: _Sentinel() = default; constexpr _Sentinel(_Sentinel _Se) noexcept( is_nothrow_constructible_v, sentinel_t<_Vw>>) // strengthened requires _Const && convertible_to, sentinel_t<_Base>> : _Last(_STD move(_Se._Last)) {} template requires sentinel_for, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD_FRIEND constexpr bool operator==(const _Iterator<_OtherConst>& _Left, const _Sentinel& _Right) noexcept(noexcept(_Right._Equal(_Left))) /* strengthened */ { return _Right._Equal(_Left); } }; public: // clang-format off join_with_view() requires default_initializable<_Vw> && default_initializable<_Pat> = default; // clang-format on constexpr explicit join_with_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_)} {} template requires constructible_from<_Vw, views::all_t<_Rng>> && constructible_from<_Pat, single_view>>> constexpr explicit join_with_view(_Rng&& _Range_, range_value_t<_InnerRng> _Elem) noexcept( noexcept(_Vw(views::all(_STD forward<_Rng>(_Range_)))) && noexcept( _Pat(views::single(_STD move(_Elem))))) // strengthened : _Range(views::all(_STD forward<_Rng>(_Range_))), _Pattern(views::single(_STD move(_Elem))) {} _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>) { constexpr bool _Use_const = _Simple_view<_Vw> && is_reference_v<_InnerRng> && _Simple_view<_Pat>; return _Iterator<_Use_const>{*this, _RANGES begin(_Range)}; } else { this->_Outer_it._Emplace(_RANGES begin(_Range)); return _Iterator{*this}; } } _NODISCARD constexpr auto begin() const #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_const_join_with<_Vw, _Pat> #else // ^^^ workaround / no workaround vvv requires forward_range && forward_range && is_reference_v<_InnerRng> && input_range<_InnerRng> #endif // TRANSITION, LLVM-47414 { return _Iterator{*this, _RANGES begin(_Range)}; } _NODISCARD constexpr auto end() { constexpr bool _Both_simple = _Simple_view<_Vw> && _Simple_view<_Pat>; if constexpr (forward_range<_Vw> // && is_reference_v<_InnerRng> && forward_range<_InnerRng> // && common_range<_Vw> && common_range<_InnerRng>) { return _Iterator<_Both_simple>{*this, _RANGES end(_Range)}; } else { return _Sentinel<_Both_simple>{*this}; } } _NODISCARD constexpr auto end() const #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Can_const_join_with<_Vw, _Pat> #else // ^^^ workaround / no workaround vvv requires forward_range && forward_range && is_reference_v<_InnerRng> && input_range<_InnerRng> #endif // TRANSITION, LLVM-47414 { if constexpr (forward_range<_InnerRng> && common_range<_Vw> && common_range<_InnerRng>) { return _Iterator{*this, _RANGES end(_Range)}; } else { return _Sentinel{*this}; } } }; template join_with_view(_Rng&&, _Pat&&) -> join_with_view, views::all_t<_Pat>>; template join_with_view(_Rng&&, range_value_t>) -> join_with_view, single_view>>>; namespace views { struct _Join_with_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pat&& _Pattern) const noexcept( noexcept(join_with_view(_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)))) requires requires { join_with_view(_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)); } { // clang-format on return join_with_view(_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)); } template requires constructible_from, _Delim> _NODISCARD constexpr auto operator()(_Delim&& _Delimiter) const noexcept(is_nothrow_constructible_v, _Delim>) { return _Range_closure<_Join_with_fn, decay_t<_Delim>>{_STD forward<_Delim>(_Delimiter)}; } }; _EXPORT_STD inline constexpr _Join_with_fn join_with; } // namespace views #endif // _HAS_CXX23 template // _Require_constant is a valid template-id iff E is a constant expression of structural type struct _Require_constant; // clang-format off template concept _Tiny_range = sized_range<_Ty> && requires { typename _Require_constant::size()>; } && (remove_reference_t<_Ty>::size() <= 1); _EXPORT_STD template requires (view<_Vw> && view<_Pat> && indirectly_comparable, iterator_t<_Pat>, _RANGES equal_to> && (forward_range<_Vw> || _Tiny_range<_Pat>)) class lazy_split_view; // clang-format on template class _Lazy_split_view_base : public view_interface> { protected: /* [[no_unique_address]] */ _Defaultabox> _Current{}; }; template class _Lazy_split_view_base<_Vw, _Pat> : public view_interface> {}; // clang-format off _EXPORT_STD template requires (view<_Vw> && view<_Pat> && indirectly_comparable, iterator_t<_Pat>, _RANGES equal_to> && (forward_range<_Vw> || _Tiny_range<_Pat>)) class lazy_split_view : public _Lazy_split_view_base<_Vw, _Pat> { // clang-format on private: /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Pat _Pattern{}; template class _Inner_iter; template class _Outer_iter_base {}; template class _Outer_iter_base<_Iter> { 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 class _Outer_iter : public _Outer_iter_base>> { private: friend lazy_split_view; using _Mybase = _Outer_iter_base>>; using _ParentTy = _Maybe_const<_Const, lazy_split_view>; using _BaseTy = _Maybe_const<_Const, _Vw>; _ParentTy* _Parent = nullptr; bool _Trailing_empty = false; _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(_Fake_copy_init(_Get_current() == _RANGES end(_Parent->_Range)))) { return _Get_current() == _RANGES end(_Parent->_Range); } public: using iterator_concept = conditional_t, forward_iterator_tag, input_iterator_tag>; using difference_type = range_difference_t<_BaseTy>; class value_type : public view_interface { 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>) // strengthened requires forward_range<_BaseTy> : _Mybase{_STD move(_Current_)}, _Parent{_STD addressof(_Parent_)} {} constexpr _Outer_iter(_Outer_iter _It) requires _Const && convertible_to, iterator_t<_BaseTy>> : _Mybase{_STD move(_It._Current)}, _Parent{_It._Parent} {} _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) { _Trailing_empty = false; 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; if (_Cur == _End) { _Trailing_empty = true; } } } else { do { auto _Result = _RANGES mismatch(_Cur, _End, _Pat_first, _Pat_last); if (_Result.in2 == _Pat_last) { // pattern matches _Cur = _STD move(_Result.in1); if (_Cur == _End) { _Trailing_empty = true; } 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 && _Left._Trailing_empty == _Right._Trailing_empty; } _NODISCARD_FRIEND constexpr bool operator==(const _Outer_iter& _Left, default_sentinel_t) noexcept( noexcept(_Left._At_end())) /* strengthened */ { return _Left._At_end() && !_Left._Trailing_empty; } }; template class _Inner_iter_base {}; template class _Inner_iter_base<_BaseTy> { private: using _BaseCategory = typename iterator_traits>::iterator_category; public: using iterator_category = conditional_t, forward_iterator_tag, _BaseCategory>; }; template 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 const iterator_t<_BaseTy>& base() const& noexcept { return _It._Get_current(); } _NODISCARD constexpr iterator_t<_BaseTy> base() && noexcept( is_nothrow_move_constructible_v>) /* strengthened */ requires forward_range<_Vw> { return _STD move(_It._Get_current()); } _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> { // clang-format on _RANGES iter_swap(_Left._Get_current(), _Right._Get_current()); } }; public: // clang-format off lazy_split_view() requires default_initializable<_Vw> && default_initializable<_Pat> = default; // clang-format on constexpr explicit lazy_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 requires constructible_from<_Vw, views::all_t<_Rng>> && constructible_from<_Pat, single_view>> constexpr explicit lazy_split_view(_Rng&& _Range_, range_value_t<_Rng> _Elem) noexcept(noexcept(_Vw(views::all(_STD forward<_Rng>(_Range_)))) && noexcept(_Pat(views::single(_STD move(_Elem))))) // strengthened : _Range(views::all(_STD forward<_Rng>(_Range_))), _Pattern(views::single(_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>) { constexpr bool _Both_simple = _Simple_view<_Vw> && _Simple_view<_Pat>; return _Outer_iter<_Both_simple>{*this, _RANGES begin(_Range)}; } else { this->_Current = _RANGES begin(_Range); return _Outer_iter{*this}; } } _NODISCARD constexpr auto begin() const requires forward_range<_Vw> && forward_range { return _Outer_iter{*this, _RANGES begin(_Range)}; } _NODISCARD constexpr auto end() requires forward_range<_Vw> && common_range<_Vw> { constexpr bool _Both_simple = _Simple_view<_Vw> && _Simple_view<_Pat>; return _Outer_iter<_Both_simple>{*this, _RANGES end(_Range)}; } _NODISCARD constexpr auto end() const { if constexpr (forward_range<_Vw> && forward_range && common_range) { return _Outer_iter{*this, _RANGES end(_Range)}; } else { return default_sentinel; } } }; template lazy_split_view(_Rng&&, _Pat&&) -> lazy_split_view, views::all_t<_Pat>>; template lazy_split_view(_Rng&&, range_value_t<_Rng>) -> lazy_split_view, single_view>>; namespace views { struct _Lazy_split_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pat&& _Pattern) const noexcept(noexcept( lazy_split_view(_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)))) requires requires { lazy_split_view(static_cast<_Rng&&>(_Range), static_cast<_Pat&&>(_Pattern)); } { // clang-format on return lazy_split_view(_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)); } template requires constructible_from, _Delim> _NODISCARD constexpr auto operator()(_Delim&& _Delimiter) const noexcept(is_nothrow_constructible_v, _Delim>) { return _Range_closure<_Lazy_split_fn, decay_t<_Delim>>{_STD forward<_Delim>(_Delimiter)}; } }; _EXPORT_STD inline constexpr _Lazy_split_fn lazy_split; } // namespace views _EXPORT_STD template requires view<_Vw> && view<_Pat> && indirectly_comparable, iterator_t<_Pat>, _RANGES equal_to> class split_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Pat _Pattern{}; _Non_propagating_cache>> _Next{}; class _Iterator { private: friend split_view; split_view* _Parent = nullptr; iterator_t<_Vw> _Current = {}; subrange> _Next = {}; bool _Trailing_empty = false; public: using iterator_concept = forward_iterator_tag; using iterator_category = input_iterator_tag; using value_type = subrange>; using difference_type = range_difference_t<_Vw>; _Iterator() = default; constexpr _Iterator(split_view& _Parent_, iterator_t<_Vw> _Current_, subrange> _Next_) // noexcept(is_nothrow_move_constructible_v>) // strengthened : _Parent{_STD addressof(_Parent_)}, _Current{_STD move(_Current_)}, _Next{_STD move(_Next_)} {} _NODISCARD constexpr iterator_t<_Vw> base() const noexcept(is_nothrow_copy_constructible_v>) /* strengthened */ { return _Current; } _NODISCARD constexpr value_type operator*() const noexcept(is_nothrow_copy_constructible_v>) /* strengthened */ { return {_Current, _Next.begin()}; } constexpr _Iterator& operator++() { const auto _Last = _RANGES end(_Parent->_Range); _Current = _Next.begin(); if (_Current == _Last) { _Trailing_empty = false; return *this; } _Current = _Next.end(); if (_Current == _Last) { _Trailing_empty = true; _Next = {_Current, _Current}; return *this; } #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-1559808 auto [_Begin, _End] = _RANGES search(subrange{_Current, _Last}, _Parent->_Pattern); #else // ^^^ no workaround / workaround vvv auto _Match = _RANGES search(subrange{_Current, _Last}, _Parent->_Pattern); auto _Begin = _Match.begin(); auto _End = _Match.end(); #endif // TRANSITION, DevCom-1559808 if (_Begin != _Last && _RANGES empty(_Parent->_Pattern)) { ++_Begin; ++_End; } _Next = {_STD move(_Begin), _STD move(_End)}; return *this; } constexpr _Iterator operator++(int) { auto _Tmp = *this; ++*this; return _Tmp; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Current == _Right._Current)) /* strengthened */ { return _Left._Current == _Right._Current && _Left._Trailing_empty == _Right._Trailing_empty; } }; class _Sentinel { private: /* [[no_unique_address]] */ sentinel_t<_Vw> _Last{}; _NODISCARD constexpr bool _Equal(const _Iterator& _It) const noexcept(noexcept(_Fake_copy_init(_It._Current == _Last))) { return !_It._Trailing_empty && _It._Current == _Last; } public: _Sentinel() = default; constexpr explicit _Sentinel(split_view& _Parent) noexcept( noexcept(_RANGES end(_Parent._Range)) && is_nothrow_move_constructible_v>) // strengthened : _Last(_RANGES end(_Parent._Range)) {} _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _It, const _Sentinel& _Se) noexcept( noexcept(_Se._Equal(_It))) /* strengthened */ { return _Se._Equal(_It); } }; constexpr subrange> _Find_next(iterator_t<_Vw> _It) { const auto _Last = _RANGES end(_Range); #if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-1559808 auto [_Begin, _End] = _RANGES search(subrange{_It, _Last}, _Pattern); #else // ^^^ no workaround / workaround vvv auto _Match = _RANGES search(subrange{_It, _Last}, _Pattern); auto _Begin = _Match.begin(); auto _End = _Match.end(); #endif // TRANSITION, DevCom-1559808 if (_Begin != _Last && _RANGES empty(_Pattern)) { ++_Begin; ++_End; } return {_STD move(_Begin), _STD move(_End)}; } public: // clang-format off split_view() requires default_initializable<_Vw> && default_initializable<_Pat> = default; // clang-format on constexpr explicit 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 requires constructible_from<_Vw, views::all_t<_Rng>> && constructible_from<_Pat, single_view>> constexpr explicit split_view(_Rng&& _Range_, range_value_t<_Rng> _Elem) noexcept(is_nothrow_constructible_v<_Vw, views::all_t<_Rng>> && is_nothrow_constructible_v<_Pat, single_view>> && is_nothrow_move_constructible_v>) // strengthened : _Range(views::all(_STD forward<_Rng>(_Range_))), _Pattern(views::single(_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() { auto _First = _RANGES begin(_Range); if (!_Next) { _Next._Emplace(_Find_next(_First)); } return _Iterator{*this, _First, *_Next}; } _NODISCARD constexpr auto end() { if constexpr (common_range<_Vw>) { return _Iterator{*this, _RANGES end(_Range), {}}; } else { return _Sentinel{*this}; } } }; template split_view(_Rng&&, _Pat&&) -> split_view, views::all_t<_Pat>>; template split_view(_Rng&&, range_value_t<_Rng>) -> split_view, single_view>>; namespace views { struct _Split_fn { // clang-format off template _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)); } template requires constructible_from, _Delim> _NODISCARD constexpr auto operator()(_Delim&& _Delimiter) const noexcept(is_nothrow_constructible_v, _Delim>) { return _Range_closure<_Split_fn, decay_t<_Delim>>{_STD forward<_Delim>(_Delimiter)}; } }; _EXPORT_STD inline constexpr _Split_fn split; class _Counted_fn { private: enum class _St { _None, _Span, _Subrange, _Subrange_counted }; template _NODISCARD static consteval _Choice_t<_St> _Choose() noexcept { using _Decayed = decay_t<_It>; _STL_INTERNAL_STATIC_ASSERT(input_or_output_iterator<_Decayed>); if constexpr (contiguous_iterator<_Decayed>) { return {_St::_Span, noexcept(span(_STD to_address(_STD declval<_It>()), iter_difference_t<_Decayed>{}))}; } else if constexpr (random_access_iterator<_Decayed>) { return {_St::_Subrange, noexcept(subrange(_STD declval<_It>(), _STD declval<_It>() + iter_difference_t<_Decayed>{}))}; } else if constexpr (constructible_from<_Decayed, _It>) { return {_St::_Subrange_counted, noexcept(subrange( counted_iterator(_STD declval<_It>(), iter_difference_t<_Decayed>{}), default_sentinel))}; } else { return {_St::_None}; } } template static constexpr _Choice_t<_St> _Choice = _Choose<_It>(); public: // clang-format off template requires (input_or_output_iterator> && _Choice<_It>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_It&& _First, const iter_difference_t> _Count) const noexcept(_Choice<_It>._No_throw) { // clang-format on _STL_ASSERT(_Count >= 0, "The size passed to views::counted must be non-negative"); constexpr _St _Strat = _Choice<_It>._Strategy; if constexpr (_Strat == _St::_Span) { return span(_STD to_address(_STD forward<_It>(_First)), static_cast(_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); } } }; _EXPORT_STD inline constexpr _Counted_fn counted; } // namespace views _EXPORT_STD template requires (!common_range<_Vw> && copyable>) class common_view : public view_interface> { 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>) /* strengthened */ { if constexpr (random_access_range<_Vw> && sized_range<_Vw>) { return _RANGES begin(_Base); } else { return common_iterator, sentinel_t<_Vw>>{_RANGES begin(_Base)}; } } _NODISCARD constexpr auto begin() const noexcept( noexcept(_RANGES begin(_Base)) && is_nothrow_move_constructible_v>) /* strengthened */ requires range { if constexpr (random_access_range && sized_range) { return _RANGES begin(_Base); } else { return common_iterator, sentinel_t>{_RANGES begin(_Base)}; } } _NODISCARD constexpr auto end() { if constexpr (random_access_range<_Vw> && sized_range<_Vw>) { return _RANGES begin(_Base) + _RANGES distance(_Base); } else { return common_iterator, sentinel_t<_Vw>>{_RANGES end(_Base)}; } } _NODISCARD constexpr auto end() const requires range { if constexpr (random_access_range && sized_range) { return _RANGES begin(_Base) + _RANGES distance(_Base); } else { return common_iterator, sentinel_t>{_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 { return _RANGES size(_Base); } }; template common_view(_Rng&&) -> common_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { class _Common_fn : public _Pipe::_Base<_Common_fn> { private: enum class _St { _None, _All, _Common }; template _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>) { return {_St::_Common, noexcept(common_view{_STD declval<_Rng>()})}; } else { return {_St::_None}; } } template static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); public: template requires (_Choice<_Rng>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { 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"); } } }; _EXPORT_STD inline constexpr _Common_fn common; } // namespace views _EXPORT_STD template requires bidirectional_range<_Vw> class reverse_view : public _Cached_position_t, _Vw, reverse_view<_Vw>> { private: /* [[no_unique_address]] */ _Vw _Range{}; template using _Rev_iter = reverse_iterator>; 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{_RANGES end(_Range)})) /* strengthened */ requires common_range { return _Rev_iter{_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{_RANGES begin(_Range)})) /* strengthened */ requires common_range { return _Rev_iter{_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 { return _RANGES size(_Range); } }; template reverse_view(_Rng&&) -> reverse_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { template concept _Can_extract_base = requires(_Rng&& __r) { static_cast<_Rng&&>(__r).base(); }; template 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 static constexpr auto _Reversed_subrange = -1; template static constexpr auto _Reversed_subrange, reverse_iterator<_It>, _Ki>> = static_cast(_Ki); template _NODISCARD static consteval _Choice_t<_St> _Choose() noexcept { using _Ty = remove_cvref_t<_Rng>; if constexpr (_Is_specialization_v<_Ty, reverse_view>) { if constexpr (_Can_extract_base<_Rng>) { return {_St::_Base, noexcept(_STD declval<_Rng>().base())}; } } else if constexpr (_Reversed_subrange<_Ty> == 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<_Ty> == 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 static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); public: template requires (_Choice<_Rng>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { 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"); } } }; _EXPORT_STD inline constexpr _Reverse_fn reverse; } // namespace views #if _HAS_CXX23 _EXPORT_STD template requires input_range<_Vw> class as_const_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; public: // clang-format off as_const_view() requires default_initializable<_Vw> = default; // clang-format on constexpr explicit as_const_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() noexcept(noexcept(_RANGES cbegin(_Range))) // strengthened requires (!_Simple_view<_Vw>) { return _RANGES cbegin(_Range); } _NODISCARD constexpr auto begin() const noexcept(noexcept(_RANGES cbegin(_Range))) // strengthened requires range { return _RANGES cbegin(_Range); } _NODISCARD constexpr auto end() noexcept(noexcept(_RANGES cend(_Range))) // strengthened requires (!_Simple_view<_Vw>) { return _RANGES cend(_Range); } _NODISCARD constexpr auto end() const noexcept(noexcept(_RANGES cend(_Range))) // strengthened requires range { return _RANGES cend(_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 { return _RANGES size(_Range); } }; template as_const_view(_Rng&&) -> as_const_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { template concept _Can_as_const = requires(_Rng&& __r) { as_const_view{static_cast<_Rng&&>(__r)}; }; class _As_const_fn : public _Pipe::_Base<_As_const_fn> { private: enum class _St { _None, _All, _Empty, _Reconstruct_span, _Reconstruct_ref, _Ref, _As_const }; template static constexpr bool _Can_reconstruct_ref_view_v = false; template requires constant_range static constexpr bool _Can_reconstruct_ref_view_v> = true; template _NODISCARD static consteval _Choice_t<_St> _Choose() noexcept { using _Ty = remove_cvref_t<_Rng>; if constexpr (constant_range>) { return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))}; } else 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 (_Can_reconstruct_ref_view_v<_Ty>) { return {_St::_Reconstruct_ref, noexcept(ref_view{_STD as_const(_STD declval<_Rng>().base())})}; } else if constexpr (is_lvalue_reference_v<_Rng> && constant_range && !view<_Ty>) { return {_St::_Ref, noexcept(ref_view{_STD as_const(_STD declval<_Rng>())})}; } else if constexpr (_Can_as_const<_Rng>) { return {_St::_As_const, noexcept(as_const_view{_STD declval<_Rng>()})}; } else { return {_St::_None}; } } template static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); public: template requires (_Choice<_Rng>._Strategy != _St::_None) _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { using _Ty = remove_cvref_t<_Rng>; constexpr _St _Strat = _Choice<_Rng>._Strategy; if constexpr (_Strat == _St::_All) { return views::all(_STD forward<_Rng>(_Range)); } else if constexpr (_Strat == _St::_Empty) { return empty_view>>{}; } else if constexpr (_Strat == _St::_Reconstruct_span) { return span{_STD forward<_Rng>(_Range)}; } else if constexpr (_Strat == _St::_Reconstruct_ref) { return ref_view{_STD as_const(_STD forward<_Rng>(_Range).base())}; } else if constexpr (_Strat == _St::_Ref) { return ref_view{_STD as_const(_STD forward<_Rng>(_Range))}; } else if constexpr (_Strat == _St::_As_const) { return as_const_view{_STD forward<_Rng>(_Range)}; } else { static_assert(_Always_false<_Rng>, "Should be unreachable"); } } }; _EXPORT_STD inline constexpr _As_const_fn as_const; } // namespace views #endif // _HAS_CXX23 template concept _Has_tuple_element = #if _HAS_CXX23 _Tuple_like<_Tuple> && _Index < tuple_size_v<_Tuple>; #else // ^^^ C++23 / C++20 vvv requires(_Tuple __t) { typename tuple_size<_Tuple>::type; requires _Index < tuple_size_v<_Tuple>; typename tuple_element_t<_Index, _Tuple>; { _STD get<_Index>(__t) } -> convertible_to&>; }; #endif // C++20 template concept _Returnable_element = is_reference_v<_Tuple> || move_constructible>; // clang-format off _EXPORT_STD template requires view<_Vw> && _Has_tuple_element, _Index> && _Has_tuple_element>, _Index> && _Returnable_element, _Index> class elements_view : public view_interface> { // clang-format on private: /* [[no_unique_address]] */ _Vw _Range{}; template struct _Category_base {}; template struct _Category_base<_Base> { using iterator_category = conditional_t(*_STD declval>()))>, input_iterator_tag, conditional_t>, random_access_iterator_tag>, random_access_iterator_tag, _Iter_cat_t>>>; }; template class _Iterator : public _Category_base<_Maybe_const<_Const, _Vw>> { private: friend elements_view; using _Base = _Maybe_const<_Const, _Vw>; iterator_t<_Base> _Current{}; public: using iterator_concept = conditional_t, random_access_iterator_tag, conditional_t, bidirectional_iterator_tag, conditional_t, forward_iterator_tag, input_iterator_tag>>>; using value_type = remove_cvref_t>>; using difference_type = range_difference_t<_Base>; // clang-format off _Iterator() requires default_initializable> = default; // clang-format on constexpr explicit _Iterator(iterator_t<_Base> _Current_) noexcept( is_nothrow_move_constructible_v>) // strengthened : _Current{_STD move(_Current_)} {} constexpr _Iterator(_Iterator _It) noexcept( is_nothrow_constructible_v, iterator_t<_Vw>>) // strengthened requires _Const && convertible_to, iterator_t<_Base>> : _Current(_STD move(_It._Current)) {} _NODISCARD constexpr const iterator_t<_Base>& base() const& noexcept { return _Current; } _NODISCARD constexpr iterator_t<_Base> base() && noexcept( is_nothrow_move_constructible_v>) /* strengthened */ { return _STD move(_Current); } _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(_STD get<_Index>(*_Current))) /* strengthened */ requires is_reference_v> { return _STD get<_Index>(*_Current); } _NODISCARD constexpr decltype(auto) operator*() const noexcept(is_nothrow_move_constructible_v>> // && noexcept(_STD get<_Index>(*_Current))) /* strengthened */ { using _ElemTy = remove_cv_t>>; 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>) /* 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>) /* strengthened */ requires bidirectional_range<_Base> { auto _Tmp = *this; --_Current; return _Tmp; } #if _ITERATOR_DEBUG_LEVEL != 0 constexpr void _Verify_offset(const difference_type _Off) const requires random_access_range<_Base> { if constexpr (_Offset_verifiable_v>) { _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 _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _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> { #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>> // && 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>>; 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> { 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> { // clang-format on return _Left._Current <=> _Right._Current; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept( noexcept(_STD declval&>() += _Off) && is_nothrow_copy_constructible_v>) /* 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&>() += _Off) && is_nothrow_copy_constructible_v>) /* 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&>() -= _Off) && is_nothrow_copy_constructible_v>) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _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>> { return _Left._Current - _Right._Current; } }; template class _Sentinel { private: friend elements_view; using _Base = _Maybe_const<_Const, _Vw>; template using _Maybe_const_iter = iterator_t<_Maybe_const<_OtherConst, _Vw>>; sentinel_t<_Base> _Last{}; template _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>) // strengthened : _Last(_STD move(_Last_)) {} // clang-format off constexpr _Sentinel(_Sentinel _Se) noexcept(is_nothrow_constructible_v, sentinel_t<_Vw>>) // strengthened requires _Const && convertible_to, sentinel_t<_Base>> : _Last(_STD move(_Se._Last)) {} // clang-format on _NODISCARD constexpr sentinel_t<_Base> base() const noexcept(is_nothrow_copy_constructible_v>) /* strengthened */ { return _Last; } template requires sentinel_for, _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; } // clang-format off template requires sized_sentinel_for, _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 requires sized_sentinel_for, _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 begin() noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires (!_Simple_view<_Vw>) { // clang-format on return _Iterator{_RANGES begin(_Range)}; } _NODISCARD constexpr _Iterator begin() const noexcept(noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires range { return _Iterator{_RANGES begin(_Range)}; } // clang-format off _NODISCARD constexpr auto end() noexcept(noexcept( _RANGES end(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires (!_Simple_view<_Vw>) { // clang-format on if constexpr (common_range<_Vw>) { return _Iterator{_RANGES end(_Range)}; } else { return _Sentinel{_RANGES end(_Range)}; } } // clang-format off _NODISCARD constexpr auto end() const noexcept(noexcept( _RANGES end(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires range { // clang-format on if constexpr (common_range) { return _Iterator{_RANGES end(_Range)}; } else { return _Sentinel{_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 { return _RANGES size(_Range); } }; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; _EXPORT_STD template using keys_view = elements_view<_Rng, 0>; _EXPORT_STD template using values_view = elements_view<_Rng, 1>; namespace views { template class _Elements_fn : public _Pipe::_Base<_Elements_fn<_Index>> { public: template _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(noexcept(elements_view, _Index>{_STD forward<_Rng>(_Range)})) requires requires { elements_view, _Index>{static_cast<_Rng&&>(_Range)}; } { return elements_view, _Index>{_STD forward<_Rng>(_Range)}; } }; _EXPORT_STD template inline constexpr _Elements_fn<_Index> elements; _EXPORT_STD inline constexpr auto keys = elements<0>; _EXPORT_STD inline constexpr auto values = elements<1>; } // namespace views #if _HAS_CXX23 template concept _Range_with_movable_references = input_range<_Rng> && move_constructible> && move_constructible>; _EXPORT_STD template requires _Range_with_movable_references<_Vw> class enumerate_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; template class _Iterator { private: friend enumerate_view; using _Base_t = _Maybe_const<_Const, _Vw>; using _Base_iterator = iterator_t<_Base_t>; using _Reference_type = tuple, range_reference_t<_Base_t>>; /* [[no_unique_address]] */ _Base_iterator _Current{}; range_difference_t<_Base_t> _Pos = 0; constexpr explicit _Iterator(_Base_iterator _Current_, range_difference_t<_Base_t> _Pos_) noexcept( is_nothrow_move_constructible_v<_Base_iterator>) // strengthened : _Current(_STD move(_Current_)), _Pos(_Pos_) {} public: using iterator_category = input_iterator_tag; using iterator_concept = conditional_t, random_access_iterator_tag, conditional_t, bidirectional_iterator_tag, conditional_t, forward_iterator_tag, input_iterator_tag>>>; using difference_type = range_difference_t<_Base_t>; using value_type = tuple>; // clang-format off _Iterator() requires default_initializable<_Base_iterator> = default; // clang-format on constexpr _Iterator(_Iterator _Other) noexcept( is_nothrow_constructible_v<_Base_iterator, iterator_t<_Vw>>) // strengthened requires _Const && convertible_to, _Base_iterator> : _Current(_STD move(_Other._Current)), _Pos(_Other._Pos) {} _NODISCARD constexpr const _Base_iterator& base() const& noexcept { return _Current; } _NODISCARD constexpr _Base_iterator base() && noexcept( is_nothrow_move_constructible_v<_Base_iterator>) /* strengthened */ { return _STD move(_Current); } _NODISCARD constexpr difference_type index() const noexcept { return _Pos; } _NODISCARD constexpr auto operator*() const noexcept( noexcept(*_Current) && is_nothrow_copy_constructible_v>) /* strengthened */ { return _Reference_type{_Pos, *_Current}; } constexpr _Iterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ { ++_Current; ++_Pos; return *this; } constexpr void operator++(int) noexcept(noexcept(++_Current)) /* strengthened */ { ++*this; } constexpr _Iterator operator++(int) noexcept( noexcept(++*this) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires forward_range<_Base_t> { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() noexcept(noexcept(--_Current)) // strengthened requires bidirectional_range<_Base_t> { --_Current; --_Pos; return *this; } constexpr _Iterator operator--(int) noexcept( noexcept(--*this) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires bidirectional_range<_Base_t> { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(const difference_type _Off) noexcept( noexcept(_Current += _Off)) // strengthened requires random_access_range<_Base_t> { _Current += _Off; _Pos += _Off; return *this; } constexpr _Iterator& operator-=(const difference_type _Off) noexcept( noexcept(_Current -= _Off)) // strengthened requires random_access_range<_Base_t> { _Current -= _Off; _Pos -= _Off; return *this; } _NODISCARD constexpr auto operator[](const difference_type _Off) const noexcept( noexcept(_Current[_Off]) && is_nothrow_copy_constructible_v>) // strengthened requires random_access_range<_Base_t> { return _Reference_type{static_cast(_Pos + _Off), _Current[_Off]}; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept { return _Left._Pos == _Right._Pos; } _NODISCARD_FRIEND constexpr strong_ordering operator<=>( const _Iterator& _Left, const _Iterator& _Right) noexcept { return _Left._Pos <=> _Right._Pos; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept( is_nothrow_copy_constructible_v<_Iterator>&& noexcept( _STD declval<_Iterator&>() += _Off)) // strengthened requires random_access_range<_Base_t> { auto _Tmp = _It; _Tmp += _Off; return _Tmp; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) noexcept( noexcept(_It + _Off)) // strengthened requires random_access_range<_Base_t> { return _It + _Off; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) noexcept( is_nothrow_copy_constructible_v<_Iterator>&& noexcept( _STD declval<_Iterator&>() -= _Off)) // strengthened requires random_access_range<_Base_t> { auto _Tmp = _It; _Tmp -= _Off; return _Tmp; } _NODISCARD_FRIEND constexpr difference_type operator-( const _Iterator& _Left, const _Iterator& _Right) noexcept /* strengthened */ { return _Left._Pos - _Right._Pos; } _NODISCARD_FRIEND constexpr auto iter_move(const _Iterator& _It) noexcept( noexcept(_RANGES iter_move(_It._Current)) && is_nothrow_move_constructible_v>) { return tuple>{ _It._Pos, _RANGES iter_move(_It._Current)}; } }; template class _Sentinel { private: friend enumerate_view; using _Base_t = _Maybe_const<_Const, _Vw>; using _Base_sentinel = sentinel_t<_Base_t>; /* [[no_unique_address]] */ _Base_sentinel _End{}; constexpr explicit _Sentinel(_Base_sentinel _End_) noexcept( is_nothrow_move_constructible_v<_Base_sentinel>) // strengthened : _End(_STD move(_End_)) {} template requires sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const noexcept(noexcept(_Fake_copy_init(_It._Current == _End))) { return _It._Current == _End; } template requires sized_sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> _Distance_from( const _Iterator<_OtherConst>& _It) const noexcept(noexcept(_End - _It._Current)) { return _End - _It._Current; } public: _Sentinel() = default; constexpr _Sentinel(_Sentinel _Other) noexcept( is_nothrow_constructible_v<_Base_sentinel, sentinel_t<_Vw>>) // strengthened requires _Const && convertible_to, _Base_sentinel> : _End(_STD move(_Other._End)) {} _NODISCARD constexpr _Base_sentinel base() const noexcept(is_nothrow_copy_constructible_v<_Base_sentinel>) /* strengthened */ { return _End; } template requires sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD_FRIEND constexpr bool operator==(const _Iterator<_OtherConst>& _It, const _Sentinel& _Se) // noexcept(noexcept(_Se._Equal(_It))) /* strengthened */ { return _Se._Equal(_It); } template requires sized_sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD_FRIEND constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-( const _Iterator<_OtherConst>& _It, const _Sentinel& _Se) // noexcept(noexcept(_Se._Distance_from(_It))) /* strengthened */ { return -_Se._Distance_from(_It); } template requires sized_sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD_FRIEND constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-( const _Sentinel& _Se, const _Iterator<_OtherConst>& _It) // noexcept(noexcept(_Se._Distance_from(_It))) /* strengthened */ { return _Se._Distance_from(_It); } }; template static constexpr bool _Is_end_nothrow_v = is_nothrow_move_constructible_v> // && noexcept(_RANGES end(_STD declval<_Rng&>())); template requires common_range<_Rng> && sized_range<_Rng> static constexpr bool _Is_end_nothrow_v<_Rng> = is_nothrow_move_constructible_v> // && noexcept(_RANGES end(_STD declval<_Rng&>())) // && noexcept(_RANGES distance(_STD declval<_Rng&>())); public: // clang-format off constexpr enumerate_view() requires default_initializable<_Vw> = default; // clang-format on constexpr explicit enumerate_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)) {} _NODISCARD constexpr auto begin() noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) // strengthened requires (!_Simple_view<_Vw>) { return _Iterator{_RANGES begin(_Range), 0}; } _NODISCARD constexpr auto begin() const noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) // strengthened requires _Range_with_movable_references { return _Iterator{_RANGES begin(_Range), 0}; } _NODISCARD constexpr auto end() noexcept(_Is_end_nothrow_v<_Vw>) // strengthened requires (!_Simple_view<_Vw>) { if constexpr (common_range<_Vw> && sized_range<_Vw>) { return _Iterator{_RANGES end(_Range), _RANGES distance(_Range)}; } else { return _Sentinel{_RANGES end(_Range)}; } } _NODISCARD constexpr auto end() const noexcept(_Is_end_nothrow_v) // strengthened requires _Range_with_movable_references { if constexpr (common_range && sized_range) { return _Iterator{_RANGES end(_Range), _RANGES distance(_Range)}; } else { return _Sentinel{_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 { return _RANGES size(_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); } }; template enumerate_view(_Rng&&) -> enumerate_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { class _Enumerate_fn : public _Pipe::_Base<_Enumerate_fn> { public: template _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(noexcept(enumerate_view>{_STD forward<_Rng>(_Range)})) requires requires { enumerate_view>{_STD forward<_Rng>(_Range)}; } { return enumerate_view>{_STD forward<_Rng>(_Range)}; } }; _EXPORT_STD inline constexpr _Enumerate_fn enumerate; } // namespace views template _NODISCARD constexpr _Size _Div_ceil(const _Size _Num, const _Size _Denom) noexcept { _Size _Result = _Num / _Denom; if (_Num % _Denom != 0) { ++_Result; } return _Result; } _EXPORT_STD template requires input_range<_Vw> class chunk_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range; range_difference_t<_Vw> _Count; range_difference_t<_Vw> _Remainder = 0; _Non_propagating_cache> _Current{}; class _Inner_iterator { private: friend chunk_view; chunk_view* _Parent{}; constexpr explicit _Inner_iterator(chunk_view* _Parent_) noexcept : _Parent(_Parent_) {} _NODISCARD constexpr range_difference_t<_Vw> _Get_remainder() const noexcept { return _Parent->_Remainder; } _NODISCARD constexpr range_difference_t<_Vw> _Get_size() const noexcept(noexcept(_RANGES end(_Parent->_Range) - *_Parent->_Current)) { return (_STD min)(_Parent->_Remainder, _RANGES end(_Parent->_Range) - *_Parent->_Current); } _NODISCARD constexpr const iterator_t<_Vw>& _Get_current() const noexcept { return *_Parent->_Current; } public: using iterator_concept = input_iterator_tag; using difference_type = range_difference_t<_Vw>; using value_type = range_value_t<_Vw>; _Inner_iterator(_Inner_iterator&&) = default; _Inner_iterator& operator=(_Inner_iterator&&) = default; _NODISCARD constexpr const iterator_t<_Vw>& base() const& noexcept /* strengthened */ { return *_Parent->_Current; } _NODISCARD constexpr range_reference_t<_Vw> operator*() const noexcept(noexcept(**_Parent->_Current)) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(*this != default_sentinel, "cannot dereference chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return **_Parent->_Current; } constexpr _Inner_iterator& operator++() noexcept(noexcept(++*_Parent->_Current) && noexcept( static_cast(*_Parent->_Current == _RANGES end(_Parent->_Range)))) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(*this != default_sentinel, "cannot increment chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 ++*_Parent->_Current; if (*_Parent->_Current == _RANGES end(_Parent->_Range)) { _Parent->_Remainder = 0; } else { --_Parent->_Remainder; } return *this; } constexpr void operator++(int) noexcept(noexcept(++*_Parent->_Current) && noexcept( static_cast(*_Parent->_Current == _RANGES end(_Parent->_Range)))) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(*this != default_sentinel, "cannot increment chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 ++*_Parent->_Current; if (*_Parent->_Current == _RANGES end(_Parent->_Range)) { _Parent->_Remainder = 0; } else { --_Parent->_Remainder; } } _NODISCARD_FRIEND constexpr bool operator==(const _Inner_iterator& _Left, default_sentinel_t) noexcept /* strengthened */ { return _Left._Get_remainder() == 0; } _NODISCARD_FRIEND constexpr difference_type operator-(default_sentinel_t, const _Inner_iterator& _Right) noexcept(noexcept(_Right._Get_size())) /* strengthened */ requires sized_sentinel_for, iterator_t<_Vw>> { return _Right._Get_size(); } _NODISCARD_FRIEND constexpr difference_type operator-(const _Inner_iterator& _Left, default_sentinel_t) noexcept(noexcept(_Left._Get_size())) /* strengthened */ requires sized_sentinel_for, iterator_t<_Vw>> { return -_Left._Get_size(); } _NODISCARD_FRIEND constexpr range_rvalue_reference_t<_Vw> iter_move(const _Inner_iterator& _It) noexcept( noexcept(_RANGES iter_move(_It._Get_current()))) { return _RANGES iter_move(_It._Get_current()); } friend constexpr void iter_swap(const _Inner_iterator& _Left, const _Inner_iterator& _Right) noexcept( noexcept(_RANGES iter_swap(_Left._Get_current(), _Right._Get_current()))) requires indirectly_swappable> { _RANGES iter_swap(_Left._Get_current(), _Right._Get_current()); } }; class _Outer_iterator { private: friend chunk_view; chunk_view* _Parent{}; constexpr explicit _Outer_iterator(chunk_view* _Parent_) noexcept : _Parent(_Parent_) {} _NODISCARD constexpr bool _Is_end() const noexcept(noexcept(*_Parent->_Current == _RANGES end(_Parent->_Range) && true)) { return *_Parent->_Current == _RANGES end(_Parent->_Range) && _Parent->_Remainder != 0; } _NODISCARD constexpr range_difference_t<_Vw> _Get_size() const noexcept(noexcept(_RANGES end(_Parent->_Range) - *_Parent->_Current)) { const auto _Size = _RANGES end(_Parent->_Range) - *_Parent->_Current; if (_Size < _Parent->_Remainder) { return _Size == 0 ? 0 : 1; } return _Div_ceil(_Size - _Parent->_Remainder, _Parent->_Count) + 1; } public: using iterator_concept = input_iterator_tag; using difference_type = range_difference_t<_Vw>; struct value_type : view_interface { private: friend _Outer_iterator; chunk_view* _Parent{}; constexpr explicit value_type(chunk_view* _Parent_) noexcept : _Parent(_Parent_) {} public: _NODISCARD constexpr _Inner_iterator begin() const noexcept { return _Inner_iterator{_Parent}; } _NODISCARD constexpr default_sentinel_t end() const noexcept { return default_sentinel; } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES end(_Parent->_Range) - *_Parent->_Current)) /* strengthened */ requires sized_sentinel_for, iterator_t<_Vw>> { return _To_unsigned_like( (_STD min)(_Parent->_Remainder, _RANGES end(_Parent->_Range) - *_Parent->_Current)); } }; _Outer_iterator(_Outer_iterator&&) = default; _Outer_iterator& operator=(_Outer_iterator&&) = default; _NODISCARD constexpr value_type operator*() const noexcept /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(*this != default_sentinel, "cannot dereference chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return value_type{_Parent}; } constexpr _Outer_iterator& operator++() /* not strengthened, see _RANGES advance */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(*this != default_sentinel, "cannot increment chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 _RANGES advance(*_Parent->_Current, _Parent->_Remainder, _RANGES end(_Parent->_Range)); _Parent->_Remainder = _Parent->_Count; return *this; } constexpr void operator++(int) /* not strengthened, see _RANGES advance */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(*this != default_sentinel, "cannot increment chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 _RANGES advance(*_Parent->_Current, _Parent->_Remainder, _RANGES end(_Parent->_Range)); _Parent->_Remainder = _Parent->_Count; } _NODISCARD_FRIEND constexpr bool operator==(const _Outer_iterator& _Left, default_sentinel_t) noexcept( noexcept(_Left._Is_end())) /* strengthened */ { return _Left._Is_end(); } _NODISCARD_FRIEND constexpr difference_type operator-(default_sentinel_t, const _Outer_iterator& _Right) noexcept(noexcept(_Right._Get_size())) /* strengthened */ requires sized_sentinel_for, iterator_t<_Vw>> { return _Right._Get_size(); } _NODISCARD_FRIEND constexpr difference_type operator-(const _Outer_iterator& _Left, default_sentinel_t) noexcept(noexcept(_Left._Get_size())) /* strengthened */ requires sized_sentinel_for, iterator_t<_Vw>> { return -_Left._Get_size(); } }; public: constexpr explicit chunk_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, "chunk size must be greater than 0"); #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); } _NODISCARD constexpr _Outer_iterator begin() noexcept( noexcept(_Current._Emplace(_RANGES begin(_Range)))) /* strengthened */ { _Current._Emplace(_RANGES begin(_Range)); _Remainder = _Count; return _Outer_iterator{this}; } _NODISCARD constexpr default_sentinel_t end() const noexcept { return default_sentinel; } _NODISCARD constexpr auto size() noexcept(noexcept(_RANGES distance(_Range))) /* strengthened */ requires sized_range<_Vw> { return _To_unsigned_like(_Div_ceil(_RANGES distance(_Range), _Count)); } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES distance(_Range))) /* strengthened */ requires sized_range { return _To_unsigned_like(_Div_ceil(_RANGES distance(_Range), _Count)); } }; template requires forward_range<_Vw> class chunk_view<_Vw> : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range; range_difference_t<_Vw> _Count; template class _Iterator { private: friend chunk_view; using _ParentTy = _Maybe_const<_Const, chunk_view>; using _Base = _Maybe_const<_Const, _Vw>; using _Base_iterator = iterator_t<_Base>; using _Base_sentinel = sentinel_t<_Base>; /* [[no_unique_address]] */ _Base_iterator _Current{}; /* [[no_unique_address]] */ _Base_sentinel _End{}; range_difference_t<_Base> _Count = 0; range_difference_t<_Base> _Missing = 0; constexpr _Iterator(_ParentTy* _Parent, _Base_iterator _Current_, // range_difference_t<_Base> _Missing_ = 0) // noexcept(noexcept(_RANGES end(_Parent->_Range)) && is_nothrow_move_constructible_v<_Base_iterator> // && is_nothrow_move_constructible_v<_Base_sentinel>) /* strengthened */ : _Current(_STD move(_Current_)), _End(_RANGES end(_Parent->_Range)), _Count(_Parent->_Count), _Missing(_Missing_) {} public: using iterator_category = input_iterator_tag; using iterator_concept = conditional_t, random_access_iterator_tag, conditional_t, bidirectional_iterator_tag, forward_iterator_tag>>; using value_type = decltype(views::take(subrange(_Current, _End), _Count)); using difference_type = range_difference_t<_Base>; _Iterator() = default; constexpr _Iterator(_Iterator _Other) noexcept( is_nothrow_constructible_v<_Base_iterator, typename _Iterator::_Base_iterator> // && is_nothrow_constructible_v<_Base_sentinel, typename _Iterator::_Base_sentinel> // ) /* strengthened */ requires _Const && convertible_to, _Base_iterator> && convertible_to, _Base_sentinel> : _Current(_STD move(_Other._Current)), _End(_STD move(_Other._End)), _Count(_Other._Count), _Missing(_Other._Missing) {} _NODISCARD constexpr _Base_iterator base() const noexcept(is_nothrow_copy_constructible_v<_Base_iterator>) /* strengthened */ { return _Current; } _NODISCARD constexpr value_type operator*() const noexcept(noexcept(views::take(subrange(_Current, _End), _Count))) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Current != _End, "cannot dereference chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return views::take(subrange(_Current, _End), _Count); } constexpr _Iterator& operator++() /* not strengthened, see _RANGES advance */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Current != _End, "cannot increment chunk_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Missing = _RANGES advance(_Current, _Count, _End); return *this; } constexpr _Iterator operator++(int) /* not strengthened, see _RANGES advance */ { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() /* not strengthened, see _RANGES advance */ requires bidirectional_range<_Base> { _RANGES advance(_Current, _Missing - _Count); _Missing = 0; return *this; } constexpr _Iterator operator--(int) /* not strengthened, see _RANGES advance */ requires bidirectional_range<_Base> { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(const difference_type _Off) /* not strengthened, see _RANGES advance */ requires random_access_range<_Base> { if (_Off > 0) { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count <= (numeric_limits::max)() / _Off, "cannot advance chunk_view iterator past end (integer overflow)"); if constexpr (sized_sentinel_for<_Base_sentinel, _Base_iterator>) { _STL_VERIFY(_End - _Current > _Count * (_Off - 1), // "cannot advance chunk_view iterator past end"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 if constexpr (sized_sentinel_for<_Base_sentinel, _Base_iterator>) { _Missing = _RANGES advance(_Current, _Count * _Off, _End); } else { _Current += static_cast(_Count * (_Off - 1)); _Missing = _RANGES advance(_Current, _Count, _End); } } else if (_Off < 0) { _Current += static_cast(_Count * _Off + _Missing); _Missing = 0; } return *this; } constexpr _Iterator& operator-=(const difference_type _Off) /* not strengthened, see _RANGES advance */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off != (numeric_limits::min)(), "cannot advance chunk_view iterator past end (integer overflow)"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return *this += -_Off; } _NODISCARD constexpr value_type operator[](const difference_type _Off) const noexcept(noexcept(*(*this + _Off))) /* strengthened */ requires random_access_range<_Base> { return *(*this + _Off); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, default_sentinel_t) noexcept( noexcept(_Fake_copy_init(_Left._Current == _Left._End))) /* strengthened */ { return _Left._Current == _Left._End; } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_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(_Fake_copy_init(_Right._Current < _Left._Current))) /* strengthened */ requires random_access_range<_Base> { return _Right._Current < _Left._Current; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(!(_Right._Current < _Left._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Right._Current < _Left._Current); } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(!(_Left._Current < _Right._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Left._Current < _Right._Current); } _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<_Base_iterator> { return _Left._Current <=> _Right._Current; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept( is_nothrow_copy_constructible_v<_Iterator>&& noexcept( _STD declval<_Iterator&>() += _Off)) /* strengthened */ requires random_access_range<_Base> { auto _Copy = _It; _Copy += _Off; return _Copy; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) noexcept( is_nothrow_copy_constructible_v<_Iterator>&& noexcept( _STD declval<_Iterator&>() += _Off)) /* strengthened */ requires random_access_range<_Base> { auto _Copy = _It; _Copy += _Off; return _Copy; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) noexcept( is_nothrow_copy_constructible_v<_Iterator>&& noexcept( _STD declval<_Iterator&>() -= _Off)) /* strengthened */ requires random_access_range<_Base> { auto _Copy = _It; _Copy -= _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<_Base_iterator, _Base_iterator> { return (_Left._Current - _Right._Current + _Left._Missing - _Right._Missing) / _Left._Count; } _NODISCARD_FRIEND constexpr difference_type operator-(default_sentinel_t, const _Iterator& _Right) noexcept( noexcept(_Right._End - _Right._Current)) /* strengthened */ requires sized_sentinel_for<_Base_sentinel, _Base_iterator> { return _Div_ceil(_Right._End - _Right._Current, _Right._Count); } _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _Left, default_sentinel_t) noexcept( noexcept(_Left._End - _Left._Current)) /* strengthened */ requires sized_sentinel_for<_Base_sentinel, _Base_iterator> { return -_Div_ceil(_Left._End - _Left._Current, _Left._Count); } }; public: constexpr explicit chunk_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, "chunk size must be greater than 0"); #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() noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires (!_Simple_view<_Vw>) { // clang-format on return _Iterator{this, _RANGES begin(_Range)}; } _NODISCARD constexpr auto begin() const noexcept(noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires forward_range { return _Iterator{this, _RANGES begin(_Range)}; } // clang-format off _NODISCARD constexpr auto end() noexcept(noexcept(_RANGES distance(_Range)) && noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires (!_Simple_view<_Vw>) { // clang-format on if constexpr (common_range<_Vw> && sized_range<_Vw>) { const auto _Missing = static_cast>(_Count - _RANGES distance(_Range) % _Count); if (_Missing == _Count) { return _Iterator{this, _RANGES end(_Range)}; } return _Iterator{this, _RANGES end(_Range), _Missing}; } else if constexpr (common_range<_Vw> && !bidirectional_range<_Vw>) { return _Iterator{this, _RANGES end(_Range)}; } else { return default_sentinel; } } // clang-format off _NODISCARD constexpr auto end() const noexcept(noexcept(_RANGES distance(_Range)) && noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires forward_range { // clang-format on if constexpr (common_range && sized_range) { const auto _Missing = static_cast>(_Count - _RANGES distance(_Range) % _Count); if (_Missing == _Count) { return _Iterator{this, _RANGES end(_Range)}; } return _Iterator{this, _RANGES end(_Range), _Missing}; } else if constexpr (common_range && !bidirectional_range) { return _Iterator{this, _RANGES end(_Range)}; } else { return default_sentinel; } } _NODISCARD constexpr auto size() noexcept(noexcept(_RANGES distance(_Range))) /* strengthened */ requires sized_range<_Vw> { return _To_unsigned_like(_Div_ceil(_RANGES distance(_Range), _Count)); } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES distance(_Range))) /* strengthened */ requires sized_range { return _To_unsigned_like(_Div_ceil(_RANGES distance(_Range), _Count)); } }; template chunk_view(_Rng&&, range_difference_t<_Rng>) -> chunk_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw> && forward_range<_Vw>; namespace views { struct _Chunk_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, const range_difference_t<_Rng> _Count) const noexcept( noexcept(chunk_view(_STD forward<_Rng>(_Range), _Count))) requires requires { chunk_view(_STD forward<_Rng>(_Range), _Count); } { // clang-format on return chunk_view(_STD forward<_Rng>(_Range), _Count); } template requires constructible_from, _Ty> _NODISCARD constexpr auto operator()(_Ty&& _Count) const noexcept(is_nothrow_constructible_v, _Ty>) { return _Range_closure<_Chunk_fn, decay_t<_Ty>>{_STD forward<_Ty>(_Count)}; } }; _EXPORT_STD inline constexpr _Chunk_fn chunk; } // namespace views template concept _Slide_caches_nothing = random_access_range<_Vw> && sized_range<_Vw>; template concept _Slide_caches_last = (!_Slide_caches_nothing<_Vw>) && bidirectional_range<_Vw> && common_range<_Vw>; template concept _Slide_caches_first = (!_Slide_caches_nothing<_Vw>) && (!_Slide_caches_last<_Vw>); _EXPORT_STD template requires view<_Vw> class slide_view : public _Cached_position_t, _Vw, slide_view<_Vw>> { private: /* [[no_unique_address]] */ _Vw _Range; range_difference_t<_Vw> _Count; template class _Iter_base {}; template <_Slide_caches_first _Base> class _Iter_base<_Base> { protected: using _Base_iterator = iterator_t<_Base>; _Base_iterator _Last_element{}; public: _Iter_base() = default; constexpr explicit _Iter_base(_Base_iterator _Last_element_) noexcept( is_nothrow_move_constructible_v<_Base_iterator>) : _Last_element{_STD move(_Last_element_)} {} _NODISCARD constexpr const _Base_iterator& _Get_last_element() const noexcept { return _Last_element; } }; template class _Iterator : public _Iter_base<_Maybe_const<_Const, _Vw>> { private: friend slide_view; using _Base = _Maybe_const<_Const, _Vw>; using _Base_iterator = iterator_t<_Base>; /* [[no_unique_address]] */ _Base_iterator _Current{}; range_difference_t<_Base> _Count = 0; constexpr _Iterator(_Base_iterator _Current_, range_difference_t<_Base> _Count_) noexcept( is_nothrow_move_constructible_v<_Base_iterator>) /* strengthened */ requires (!_Slide_caches_first<_Base>) : _Current(_STD move(_Current_)), _Count(_Count_) {} constexpr _Iterator(_Base_iterator _Current_, _Base_iterator _Last_, range_difference_t<_Base> _Count_) // noexcept(is_nothrow_move_constructible_v<_Base_iterator>) /* strengthened */ requires _Slide_caches_first<_Base> : _Iter_base<_Base>(_STD move(_Last_)), _Current(_STD move(_Current_)), _Count(_Count_) {} public: using value_type = decltype(views::counted(_Current, _Count)); using difference_type = range_difference_t<_Base>; using iterator_category = input_iterator_tag; using iterator_concept = conditional_t, random_access_iterator_tag, conditional_t, bidirectional_iterator_tag, forward_iterator_tag>>; _Iterator() = default; constexpr _Iterator(_Iterator _Other) noexcept( is_nothrow_constructible_v<_Base_iterator, iterator_t<_Vw>>) // strengthened requires _Const && convertible_to, _Base_iterator> : _Current(_STD move(_Other._Current)), _Count(_Other._Count) {} _NODISCARD constexpr value_type operator*() const noexcept(noexcept(views::counted(_Current, _Count))) /* strengthened */ { return views::counted(_Current, _Count); } constexpr _Iterator& operator++() noexcept(noexcept(++_Current)) /* strengthened */ { ++_Current; if constexpr (_Slide_caches_first<_Base>) { ++this->_Last_element; } return *this; } constexpr _Iterator operator++(int) noexcept( is_nothrow_copy_constructible_v<_Base_iterator>&& noexcept(++_Current)) /* strengthened */ { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() noexcept(noexcept(--_Current)) /* strengthened */ requires bidirectional_range<_Base> { --_Current; if constexpr (_Slide_caches_first<_Base>) { --this->_Last_element; } return *this; } constexpr _Iterator operator--(int) noexcept( is_nothrow_copy_constructible_v<_Base_iterator>&& noexcept(--_Current)) /* strengthened */ requires bidirectional_range<_Base> { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(const difference_type _Off) noexcept( noexcept(_Current += _Off)) /* strengthened */ requires random_access_range<_Base> { _Current += _Off; if constexpr (_Slide_caches_first<_Base>) { this->_Last_element += _Off; } return *this; } constexpr _Iterator& operator-=(const difference_type _Off) noexcept( noexcept(_Current -= _Off)) /* strengthened */ requires random_access_range<_Base> { _Current -= _Off; if constexpr (_Slide_caches_first<_Base>) { this->_Last_element -= _Off; } return *this; } _NODISCARD constexpr value_type operator[](const difference_type _Off) const noexcept(noexcept(views::counted(_Current + _Off, _Count))) /* strengthened */ requires random_access_range<_Base> { return views::counted(_Current + _Off, _Count); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { if constexpr (_Slide_caches_first<_Base>) { return _Left._Last_element == _Right._Last_element; } else { return _Left._Current == _Right._Current; } } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_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(_Fake_copy_init(_Right._Current < _Left._Current))) /* strengthened */ requires random_access_range<_Base> { return _Right._Current < _Left._Current; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(!(_Right._Current < _Left._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Right._Current < _Left._Current); } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(!(_Left._Current < _Right._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Left._Current < _Right._Current); } _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<_Base_iterator> { return _Left._Current <=> _Right._Current; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept( noexcept(_STD declval<_Iterator&>() += _Off)) /* strengthened */ requires random_access_range<_Base> { auto _Copy = _It; _Copy += _Off; return _Copy; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) noexcept( noexcept(_STD declval<_Iterator&>() += _Off)) /* strengthened */ requires random_access_range<_Base> { auto _Copy = _It; _Copy += _Off; return _Copy; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) noexcept( noexcept(_STD declval<_Iterator&>() -= _Off)) /* strengthened */ requires random_access_range<_Base> { auto _Copy = _It; _Copy -= _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<_Base_iterator, _Base_iterator> { if constexpr (_Slide_caches_first<_Base>) { return _Left._Last_element - _Right._Last_element; } else { return _Left._Current - _Right._Current; } } }; class _Sentinel { private: friend slide_view; /* [[no_unique_address]] */ sentinel_t<_Vw> _Last{}; constexpr explicit _Sentinel(sentinel_t<_Vw> _Last_) noexcept( is_nothrow_move_constructible_v>) /* strengthened */ : _Last(_STD move(_Last_)) {} public: _Sentinel() = default; _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Sentinel& _Right) noexcept( noexcept(_Fake_copy_init(_Left._Get_last_element() == _Right._Last))) /* strengthened */ { return _Left._Get_last_element() == _Right._Last; } _NODISCARD_FRIEND constexpr range_difference_t<_Vw> operator-(const _Iterator& _Left, const _Sentinel& _Right) noexcept(noexcept(_Left._Get_last_element() - _Right._Last)) /* strengthened */ requires sized_sentinel_for, iterator_t<_Vw>> { return _Left._Get_last_element() - _Right._Last; } _NODISCARD_FRIEND constexpr range_difference_t<_Vw> operator-(const _Sentinel& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Last - _Right._Get_last_element())) /* strengthened */ requires sized_sentinel_for, iterator_t<_Vw>> { return _Left._Last - _Right._Get_last_element(); } }; public: constexpr explicit slide_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, "The window size must be positive (N4928 [range.slide.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> && _Slide_caches_nothing) ) { // clang-format on if constexpr (_Slide_caches_first<_Vw>) { auto _First = _RANGES begin(_Range); if (this->_Has_cache()) { return _Iterator{_STD move(_First), this->_Get_cache(_Range), _Count}; } auto _Current_last = _RANGES next(_First, _Count - 1, _RANGES end(_Range)); this->_Set_cache(_Range, _Current_last); return _Iterator{_STD move(_First), _STD move(_Current_last), _Count}; } else { return _Iterator{_RANGES begin(_Range), _Count}; } } _NODISCARD constexpr auto begin() const noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) /* strengthened */ requires _Slide_caches_nothing { return _Iterator{_RANGES begin(_Range), _Count}; } // clang-format off _NODISCARD constexpr auto end() requires (!(_Simple_view<_Vw> && _Slide_caches_nothing) ) { // clang-format on if constexpr (_Slide_caches_nothing<_Vw>) { const auto _Size = _RANGES distance(_Range) - (_Count - 1); if (_Size < 0) { return _Iterator{_RANGES begin(_Range), _Count}; } return _Iterator{_RANGES begin(_Range) + _Size, _Count}; } else if constexpr (_Slide_caches_last<_Vw>) { if (this->_Has_cache()) { return _Iterator{this->_Get_cache(_Range), _Count}; } auto _Current_last = _RANGES prev(_RANGES end(_Range), _Count - 1, _RANGES begin(_Range)); this->_Set_cache(_Range, _Current_last); return _Iterator{_STD move(_Current_last), _Count}; } else if constexpr (common_range<_Vw>) { const auto _Last = _RANGES end(_Range); return _Iterator{_Last, _Last, _Count}; } else { return _Sentinel{_RANGES end(_Range)}; } } _NODISCARD constexpr auto end() const noexcept(is_nothrow_move_constructible_v> // && noexcept(_RANGES distance(_Range)) && noexcept(_RANGES begin(_Range) + _Count)) /* strengthened */ requires _Slide_caches_nothing { const auto _Size = _RANGES distance(_Range) - (_Count - 1); if (_Size < 0) { return _Iterator{_RANGES begin(_Range), _Count}; } return _Iterator{_RANGES begin(_Range) + _Size, _Count}; } _NODISCARD constexpr auto size() noexcept(noexcept(_RANGES distance(_Range))) /* strengthened */ requires sized_range<_Vw> { auto _Size = _RANGES distance(_Range) - (_Count - 1); if (_Size < 0) { _Size = 0; } return _To_unsigned_like(_Size); } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES distance(_Range))) /* strengthened */ requires sized_range { auto _Size = _RANGES distance(_Range) - (_Count - 1); if (_Size < 0) { _Size = 0; } return _To_unsigned_like(_Size); } }; template slide_view(_Rng&&, range_difference_t<_Rng>) -> slide_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw>; namespace views { struct _Slide_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, const range_difference_t<_Rng> _Count) const noexcept( noexcept(slide_view(_STD forward<_Rng>(_Range), _Count))) requires requires { slide_view(_STD forward<_Rng>(_Range), _Count); } { // clang-format on return slide_view(_STD forward<_Rng>(_Range), _Count); } template requires constructible_from, _Ty> _NODISCARD constexpr auto operator()(_Ty&& _Count) const noexcept(is_nothrow_constructible_v, _Ty>) { return _Range_closure<_Slide_fn, decay_t<_Ty>>{_STD forward<_Ty>(_Count)}; } }; _EXPORT_STD inline constexpr _Slide_fn slide; } // namespace views template struct _Negated_pred { template _NODISCARD constexpr bool operator()(_Ty1&& _Left, _Ty2&& _Right) { return !_STD invoke(_Pred, _STD forward<_Ty1>(_Left), _STD forward<_Ty2>(_Right)); } _Pr& _Pred; }; template struct _Backward_negated_pred { template _NODISCARD constexpr bool operator()(_Ty1&& _Left, _Ty2&& _Right) { return !_STD invoke(_Pred, _STD forward<_Ty2>(_Right), _STD forward<_Ty1>(_Left)); } _Pr& _Pred; }; _EXPORT_STD template , iterator_t<_Vw>> _Pr> requires view<_Vw> && is_object_v<_Pr> class chunk_by_view : public _Cached_position<_Vw, chunk_by_view<_Vw, _Pr>> { private: /* [[no_unique_address]] */ _Vw _Range{}; /* [[no_unique_address]] */ _Movable_box<_Pr> _Pred{}; class _Iterator { private: friend chunk_by_view; chunk_by_view* _Parent{}; /* [[no_unique_address]] */ iterator_t<_Vw> _Current{}; /* [[no_unique_address]] */ iterator_t<_Vw> _Next{}; constexpr _Iterator(chunk_by_view& _Parent_, iterator_t<_Vw> _Current_, iterator_t<_Vw> _Next_) noexcept( is_nothrow_move_constructible_v>) // strengthened : _Parent(_STD addressof(_Parent_)), _Current(_STD move(_Current_)), _Next(_STD move(_Next_)) {} public: using value_type = subrange>; using difference_type = range_difference_t<_Vw>; using iterator_category = input_iterator_tag; using iterator_concept = conditional_t, bidirectional_iterator_tag, forward_iterator_tag>; _Iterator() = default; _NODISCARD constexpr value_type operator*() const noexcept(is_nothrow_copy_constructible_v>) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Current != _Next, "cannot dereference chunk_by_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return subrange{_Current, _Next}; } constexpr _Iterator& operator++() { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Current != _Next, "cannot increment chunk_by_view iterator past end"); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Current = _Next; _Next = _Parent->_Find_next(_Next); return *this; } constexpr _Iterator operator++(int) { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() requires bidirectional_range<_Vw> { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Parent != nullptr, "cannot decrement value-initialized chunk_by_view iterator"); _STL_VERIFY( _Current != _RANGES begin(_Parent->_Range), "cannot decrement chunk_by_view iterator before begin"); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Next = _Current; _Current = _Parent->_Find_prev(_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) noexcept( noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, default_sentinel_t) noexcept( noexcept(_Fake_copy_init(_Left._Current == _Left._Next))) /* strengthened */ { return _Left._Current == _Left._Next; } }; _NODISCARD constexpr iterator_t<_Vw> _Find_next(iterator_t<_Vw> _It) { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "cannot increment a chunk_by_view iterator whose parent view has no predicate"); #endif // _ITERATOR_DEBUG_LEVEL != 0 const auto _Before_next = _RANGES adjacent_find(_It, _RANGES end(_Range), _Negated_pred<_Pr>{*_Pred}); return _RANGES next(_Before_next, 1, _RANGES end(_Range)); } _NODISCARD constexpr iterator_t<_Vw> _Find_prev(iterator_t<_Vw> _It) { _STL_INTERNAL_STATIC_ASSERT(bidirectional_range<_Vw>); #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "cannot decrement a chunk_by_view iterator whose parent view has no predicate"); #endif // _ITERATOR_DEBUG_LEVEL != 0 reverse_view _Rv{subrange{_RANGES begin(_Range), _It}}; const auto _After_prev = _RANGES adjacent_find(_Rv, _Backward_negated_pred<_Pr>{*_Pred}); return _RANGES prev(_After_prev.base(), 1, _RANGES begin(_Range)); } public: // clang-format off chunk_by_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default; // clang-format on constexpr explicit chunk_by_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, "chunk_by_view has no predicate"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_Pred; } _NODISCARD constexpr _Iterator begin() { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "cannot call begin on a chunk_by_view with no predicate"); #endif // _CONTAINER_DEBUG_LEVEL > 0 const auto _First = _RANGES begin(_Range); if (this->_Has_cache()) { return _Iterator{*this, _First, this->_Get_cache(_Range)}; } const auto _Result = _Find_next(_First); this->_Set_cache(_Range, _Result); return _Iterator{*this, _First, _Result}; } _NODISCARD constexpr auto end() { if constexpr (common_range<_Vw>) { const auto _Last = _RANGES end(_Range); return _Iterator{*this, _Last, _Last}; } else { return default_sentinel; } } }; template chunk_by_view(_Rng&&, _Pr) -> chunk_by_view, _Pr>; namespace views { struct _Chunk_by_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr&& _Pred) const noexcept( noexcept(chunk_by_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)))) requires requires { chunk_by_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)); } { // clang-format on return chunk_by_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)); } template requires constructible_from, _Pr> _NODISCARD constexpr auto operator()(_Pr&& _Pred) const noexcept(is_nothrow_constructible_v, _Pr>) { return _Range_closure<_Chunk_by_fn, decay_t<_Pr>>{_STD forward<_Pr>(_Pred)}; } }; _EXPORT_STD inline constexpr _Chunk_by_fn chunk_by; } // namespace views _EXPORT_STD template requires view<_Vw> class stride_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range; range_difference_t<_Vw> _Stride; template class _Category_base {}; template class _Category_base<_BaseTy> { private: using _BaseCategory = typename iterator_traits>::iterator_category; public: using iterator_category = conditional_t, random_access_iterator_tag, _BaseCategory>; }; template class _Iterator : public _Category_base<_Maybe_const<_Const, _Vw>> { private: friend stride_view; using _ParentTy = _Maybe_const<_Const, stride_view>; using _Base = _Maybe_const<_Const, _Vw>; using _Base_iterator = iterator_t<_Base>; using _Base_sentinel = sentinel_t<_Base>; /* [[no_unique_address]] */ _Base_iterator _Current{}; /* [[no_unique_address]] */ _Base_sentinel _End{}; range_difference_t<_Base> _Stride = 0; range_difference_t<_Base> _Missing = 0; constexpr _Iterator(_ParentTy* _Parent, _Base_iterator _Current_, range_difference_t<_Base> _Missing_ = 0) // noexcept(noexcept(_RANGES end(_Parent->_Range)) && is_nothrow_move_constructible_v<_Base_iterator> // && is_nothrow_move_constructible_v<_Base_sentinel>) // strengthened : _Current(_STD move(_Current_)), _End(_RANGES end(_Parent->_Range)), _Stride(_Parent->_Stride), _Missing(_Missing_) {} public: using difference_type = range_difference_t<_Base>; using value_type = range_value_t<_Base>; using iterator_concept = conditional_t, random_access_iterator_tag, conditional_t, bidirectional_iterator_tag, conditional_t, forward_iterator_tag, input_iterator_tag>>>; // clang-format off _Iterator() requires default_initializable<_Base_iterator> = default; // clang-format on constexpr _Iterator(_Iterator _Other) noexcept( is_nothrow_constructible_v<_Base_iterator, iterator_t<_Vw>> // && is_nothrow_constructible_v<_Base_sentinel, sentinel_t<_Vw>> // ) /* strengthened */ requires _Const && convertible_to, _Base_iterator> && convertible_to, _Base_sentinel> : _Current(_STD move(_Other._Current)), _End(_STD move(_Other._End)), _Stride(_Other._Stride), _Missing(_Other._Missing) {} _NODISCARD constexpr _Base_iterator base() && noexcept( is_nothrow_move_constructible_v<_Base_iterator>) /* strengthened */ { return _STD move(_Current); } _NODISCARD constexpr const _Base_iterator& base() const& noexcept { return _Current; } _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(*_Current)) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Current != _End, "cannot dereference stride_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return *_Current; } constexpr _Iterator& operator++() { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Current != _End, "cannot increment stride_view end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Missing = _RANGES advance(_Current, _Stride, _End); return *this; } constexpr void operator++(int) { ++*this; } constexpr _Iterator operator++(int) requires forward_range<_Base> { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() requires bidirectional_range<_Base> { _RANGES advance(_Current, _Missing - _Stride); _Missing = 0; return *this; } constexpr _Iterator operator--(int) requires bidirectional_range<_Base> { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(const difference_type _Off) requires random_access_range<_Base> { if (_Off > 0) { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Stride <= (numeric_limits::max)() / _Off, "cannot advance stride_view iterator past end (integer overflow)"); if constexpr (sized_sentinel_for<_Base_sentinel, _Base_iterator>) { _STL_VERIFY(_End - _Current > _Stride * (_Off - 1), // "cannot advance stride_view iterator past end"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 if constexpr (sized_sentinel_for<_Base_sentinel, _Base_iterator>) { _Missing = _RANGES advance(_Current, _Stride * _Off, _End); } else { _Current += static_cast(_Stride * (_Off - 1)); _Missing = _RANGES advance(_Current, _Stride, _End); } } else if (_Off < 0) { _Current += static_cast(_Stride * _Off + _Missing); _Missing = 0; } return *this; } constexpr _Iterator& operator-=(const difference_type _Off) requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off != (numeric_limits::min)(), "cannot advance stride_view iterator past end (integer overflow)"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return *this += -_Off; } _NODISCARD constexpr decltype(auto) operator[](const difference_type _Off) const noexcept(noexcept(*(*this + _Off))) /* strengthened */ requires random_access_range<_Base> { return *(*this + _Off); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _It, default_sentinel_t) noexcept( noexcept(_Fake_copy_init(_It._Current == _It._End))) /* strengthened */ { return _It._Current == _It._End; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) // strengthened requires equality_comparable<_Base_iterator> { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_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(_Fake_copy_init(_Right._Current < _Left._Current))) // strengthened requires random_access_range<_Base> { return _Right._Current < _Left._Current; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(!(_Right._Current < _Left._Current)))) // strengthened requires random_access_range<_Base> { return !(_Right._Current < _Left._Current); } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(!(_Left._Current < _Right._Current)))) // strengthened requires random_access_range<_Base> { return !(_Left._Current < _Right._Current); } _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<_Base_iterator> { return _Left._Current <=> _Right._Current; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) requires random_access_range<_Base> { auto _Copy = _It; _Copy += _Off; return _Copy; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) requires random_access_range<_Base> { auto _Copy = _It; _Copy += _Off; return _Copy; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) requires random_access_range<_Base> { auto _Copy = _It; _Copy -= _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<_Base_iterator, _Base_iterator> { const auto _Diff = _Left._Current - _Right._Current; if constexpr (forward_range<_Base>) { return (_Diff + _Left._Missing - _Right._Missing) / _Left._Stride; } else { if (_Diff < 0) { return -_Div_ceil(-_Diff, _Left._Stride); } else { return _Div_ceil(_Diff, _Left._Stride); } } } _NODISCARD_FRIEND constexpr difference_type operator-(default_sentinel_t, const _Iterator& _It) noexcept( noexcept(_It._End - _It._Current)) // strengthened requires sized_sentinel_for<_Base_sentinel, _Base_iterator> { return _Div_ceil(_It._End - _It._Current, _It._Stride); } _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _It, default_sentinel_t) noexcept( noexcept(_It._End - _It._Current)) // strengthened requires sized_sentinel_for<_Base_sentinel, _Base_iterator> { return -_Div_ceil(_It._End - _It._Current, _It._Stride); } _NODISCARD_FRIEND constexpr range_rvalue_reference_t<_Base> iter_move(const _Iterator& _It) noexcept( noexcept(_RANGES iter_move(_It._Current))) { 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<_Base_iterator> { return _RANGES iter_swap(_Left._Current, _Right._Current); } }; public: constexpr explicit stride_view(_Vw _Range_, range_difference_t<_Vw> _Stride_) noexcept( is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)), _Stride(_Stride_) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Stride > 0, "stride must be greater than 0"); #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); } _NODISCARD constexpr range_difference_t<_Vw> stride() const noexcept { return _Stride; } _NODISCARD constexpr auto begin() noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) // strengthened requires (!_Simple_view<_Vw>) { return _Iterator{this, _RANGES begin(_Range)}; } _NODISCARD constexpr auto begin() const noexcept( noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v>) // strengthened requires range { return _Iterator{this, _RANGES begin(_Range)}; } _NODISCARD constexpr auto end() noexcept(noexcept(_RANGES distance(_Range)) && noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v>) // strengthened requires (!_Simple_view<_Vw>) { if constexpr (common_range<_Vw> && sized_range<_Vw> && forward_range<_Vw>) { const auto _Missing = static_cast>(_Stride - _RANGES distance(_Range) % _Stride); if (_Missing == _Stride) { return _Iterator{this, _RANGES end(_Range)}; } else { return _Iterator{this, _RANGES end(_Range), _Missing}; } } else if constexpr (common_range<_Vw> && !bidirectional_range<_Vw>) { return _Iterator{this, _RANGES end(_Range)}; } else { return default_sentinel; } } _NODISCARD constexpr auto end() const noexcept(noexcept(_RANGES distance(_Range)) && noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v>) // strengthened requires range { if constexpr (common_range && sized_range && forward_range) { const auto _Missing = static_cast>(_Stride - _RANGES distance(_Range) % _Stride); if (_Missing == _Stride) { return _Iterator{this, _RANGES end(_Range)}; } else { return _Iterator{this, _RANGES end(_Range), _Missing}; } } else if constexpr (common_range && !bidirectional_range) { return _Iterator{this, _RANGES end(_Range)}; } else { return default_sentinel; } } _NODISCARD constexpr auto size() noexcept(noexcept(_RANGES distance(_Range))) // strengthened requires sized_range<_Vw> { return _To_unsigned_like(_Div_ceil(_RANGES distance(_Range), _Stride)); } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES distance(_Range))) // strengthened requires sized_range { return _To_unsigned_like(_Div_ceil(_RANGES distance(_Range), _Stride)); } }; template stride_view(_Rng&&, range_difference_t<_Rng>) -> stride_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw>; namespace views { struct _Stride_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, const range_difference_t<_Rng> _Stride) const noexcept( noexcept(stride_view(_STD forward<_Rng>(_Range), _Stride))) requires requires { stride_view(_STD forward<_Rng>(_Range), _Stride); } { // clang-format on return stride_view(_STD forward<_Rng>(_Range), _Stride); } template requires constructible_from, _Ty> _NODISCARD constexpr auto operator()(_Ty&& _Stride) const noexcept(is_nothrow_constructible_v, _Ty>) { return _Range_closure<_Stride_fn, decay_t<_Ty>>{_STD forward<_Ty>(_Stride)}; } }; _EXPORT_STD inline constexpr _Stride_fn stride; } // namespace views template concept _Zip_is_common = (sizeof...(_RangeTypes) == 1 && (common_range<_RangeTypes> && ...)) // || (!(bidirectional_range<_RangeTypes> && ...) && (common_range<_RangeTypes> && ...)) // || ((random_access_range<_RangeTypes> && ...) && (sized_range<_RangeTypes> && ...)); template constexpr auto _Tuple_transform_closure(_CallbackType& _Callback) noexcept { return [&_Callback](_ViewTupleTypes&&... _View_tuples) noexcept( noexcept(tuple...>{ _STD invoke(_Callback, _STD forward<_ViewTupleTypes>(_View_tuples))...})) { return tuple...>{ _STD invoke(_Callback, _STD forward<_ViewTupleTypes>(_View_tuples))...}; }; } template constexpr auto _Tuple_transform(_CallbackType&& _Callback, _TupleType&& _Tuple) noexcept(noexcept( _STD apply(_Tuple_transform_closure(_Callback), _STD forward<_TupleType>(_Tuple)))) /* strengthened */ { return _STD apply(_Tuple_transform_closure(_Callback), _STD forward<_TupleType>(_Tuple)); } template constexpr auto _Tuple_for_each_closure(_CallbackType& _Callback) noexcept { return [&_Callback](_ViewTupleTypes&&... _View_tuples) noexcept( noexcept(((void) (_STD invoke(_Callback, _STD forward<_ViewTupleTypes>(_View_tuples))), ...))) { ((void) (_STD invoke(_Callback, _STD forward<_ViewTupleTypes>(_View_tuples))), ...); }; } template constexpr void _Tuple_for_each(_CallbackType&& _Callback, _TupleType&& _Tuple) noexcept( noexcept(_STD apply(_Tuple_for_each_closure(_Callback), _STD forward<_TupleType>(_Tuple)))) /* strengthened */ { _STD apply(_Tuple_for_each_closure(_Callback), _STD forward<_TupleType>(_Tuple)); } template concept _All_random_access = (random_access_range<_Maybe_const<_IsConst, _Views>> && ...); template concept _All_bidirectional = (bidirectional_range<_Maybe_const<_IsConst, _Views>> && ...); template concept _All_forward = (forward_range<_Maybe_const<_IsConst, _Views>> && ...); template requires (sizeof...(_LHSTupleTypes) == sizeof...(_RHSTupleTypes)) _NODISCARD constexpr _ResultType _Zip_get_smallest_distance( const tuple<_LHSTupleTypes...>& _Lhs_tuple, const tuple<_RHSTupleTypes...>& _Rhs_tuple) // clang-format off noexcept((noexcept(static_cast<_ResultType>( _STD declval() - _STD declval())) && ...)) { constexpr bool _Is_noexcept = (noexcept(static_cast<_ResultType>( _STD declval() - _STD declval())) && ...); // clang-format on const auto _Get_smallest_distance_closure = [&_Lhs_tuple, &_Rhs_tuple ]( index_sequence<_FirstIdx, _Idxs...>) noexcept(_Is_noexcept) { const _ResultType _First_size = static_cast<_ResultType>(_STD get<0>(_Lhs_tuple) - _STD get<0>(_Rhs_tuple)); if (_First_size == 0) { return static_cast<_ResultType>(0); } const initializer_list<_ResultType> _Sizes = { _First_size, (_STD get<_Idxs>(_Lhs_tuple) - _STD get<_Idxs>(_Rhs_tuple))...}; return _First_size < 0 ? static_cast<_ResultType>((_RANGES max)(_Sizes)) : static_cast<_ResultType>((_RANGES min)(_Sizes)); }; return _Get_smallest_distance_closure(index_sequence_for<_LHSTupleTypes...>{}); } template requires (sizeof...(_LHSTupleTypes) == sizeof...(_RHSTupleTypes)) _NODISCARD constexpr bool _Zip_iterator_sentinel_equal( const tuple<_LHSTupleTypes...>& _Lhs_tuple, const tuple<_RHSTupleTypes...>& _Rhs_tuple) // clang-format off noexcept((noexcept(_STD declval() == _STD declval()) && ...)) { // clang-format on const auto _Evaluate_equality_closure = [&_Lhs_tuple, &_Rhs_tuple ](index_sequence<_Indices...>) noexcept( (noexcept(_STD declval() == _STD declval()) && ...)) { return ((_STD get<_Indices>(_Lhs_tuple) == _STD get<_Indices>(_Rhs_tuple)) || ...); }; return _Evaluate_equality_closure(index_sequence_for<_LHSTupleTypes...>{}); } #ifdef __clang__ template // TRANSITION, LLVM-47414 concept _Zip_iter_converts = _IsConst && (convertible_to, iterator_t> && ...); template // TRANSITION, LLVM-47414 concept _Zip_sent_converts = _IsConst && (convertible_to, sentinel_t> && ...); #endif // ^^^ workaround ^^^ template concept _Zip_transform_constraints = move_constructible<_Func> && is_object_v<_Func> && (sizeof...(_Views) > 0) && (input_range<_Views> && ...) && (view<_Views> && ...) && regular_invocable<_Func&, range_reference_t<_Views>...> && _Can_reference...>>; _EXPORT_STD template requires (view<_ViewTypes> && ...) && (sizeof...(_ViewTypes) > 0) class zip_view : public view_interface> { private: /* [[no_unique_address]] */ tuple<_ViewTypes...> _Views; template struct _Category_base {}; template requires _All_forward<_IsConst, _ViewTypes...> struct _Category_base<_IsConst> { using iterator_category = input_iterator_tag; }; template class _Iterator : public _Category_base<_IsConst> { private: friend zip_view; template requires _Zip_transform_constraints<_Func, _OtherViews...> friend class zip_transform_view; using _My_tuple = tuple>...>; /* [[no_unique_address]] */ _My_tuple _Current; constexpr explicit _Iterator(_My_tuple _Current_) noexcept( is_nothrow_move_constructible_v<_My_tuple>) // strengthened : _Current(_STD move(_Current_)) {} public: using iterator_concept = conditional_t<_All_random_access<_IsConst, _ViewTypes...>, random_access_iterator_tag, conditional_t<_All_bidirectional<_IsConst, _ViewTypes...>, bidirectional_iterator_tag, conditional_t<_All_forward<_IsConst, _ViewTypes...>, forward_iterator_tag, input_iterator_tag>>>; using value_type = tuple>...>; using difference_type = common_type_t>...>; _Iterator() = default; constexpr _Iterator(_Iterator _Rhs) noexcept( (is_nothrow_convertible_v, iterator_t> && ...)) // strengthened #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Zip_iter_converts<_IsConst, _ViewTypes...> #else // ^^^ workaround / no workaround vvv requires (_IsConst && (convertible_to, iterator_t> && ...)) #endif // __clang__ : _Current(_STD move(_Rhs._Current)) { } _NODISCARD constexpr auto operator*() const noexcept((noexcept(*(_STD declval>&>())) && ...)) /* strengthened */ { return _Tuple_transform( [](auto& _Itr) noexcept(noexcept(*_Itr)) -> decltype(auto) { return *_Itr; }, _Current); } constexpr _Iterator& operator++() noexcept(noexcept( _Tuple_for_each([](auto& _Itr) noexcept(noexcept(++_Itr)) { ++_Itr; }, _Current))) /* strengthened */ { _Tuple_for_each([](auto& _Itr) noexcept(noexcept(++_Itr)) { ++_Itr; }, _Current); return *this; } constexpr void operator++(int) noexcept(noexcept(++(_STD declval<_Iterator>()))) /* strengthened */ { ++*this; } constexpr _Iterator operator++(int) noexcept( noexcept(++(_STD declval<_Iterator>())) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires _All_forward<_IsConst, _ViewTypes...> { auto _Temp = *this; ++*this; return _Temp; } constexpr _Iterator& operator--() noexcept(noexcept( _Tuple_for_each([](auto& _Itr) noexcept(noexcept(--_Itr)) { --_Itr; }, _Current))) // strengthened requires _All_bidirectional<_IsConst, _ViewTypes...> { _Tuple_for_each([](auto& _Itr) noexcept(noexcept(--_Itr)) { --_Itr; }, _Current); return *this; } constexpr _Iterator operator--(int) noexcept( noexcept(--(_STD declval<_Iterator>())) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires _All_bidirectional<_IsConst, _ViewTypes...> { auto _Temp = *this; --*this; return _Temp; } constexpr _Iterator& operator+=(const difference_type _Off) noexcept( (noexcept(_STD declval>&>() += static_cast>>>(_Off)) && ...)) // strengthened requires _All_random_access<_IsConst, _ViewTypes...> { _Tuple_for_each( [&_Off](_IteratorType& _Itr) noexcept( noexcept(_Itr += static_cast>(_Off))) { _Itr += static_cast>(_Off); }, _Current); return *this; } constexpr _Iterator& operator-=(const difference_type _Off) noexcept( (noexcept(_STD declval>&>() -= static_cast>>>(_Off)) && ...)) // strengthened requires _All_random_access<_IsConst, _ViewTypes...> { _Tuple_for_each( [&_Off](_IteratorType& _Itr) noexcept( noexcept(_Itr -= static_cast>(_Off))) { _Itr -= static_cast>(_Off); }, _Current); return *this; } _NODISCARD constexpr auto operator[](const difference_type _Where) const noexcept( (noexcept((_STD declval>&>()) [static_cast>>>(_Where)]) && ...)) // strengthened requires _All_random_access<_IsConst, _ViewTypes...> { return _Tuple_transform( [&_Where](_IteratorType& _Itr) noexcept( noexcept(_Itr[static_cast>(_Where)])) -> decltype(auto) { return _Itr[static_cast>(_Where)]; }, _Current); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Lhs, const _Iterator& _Rhs) noexcept( noexcept(_Zip_iterator_sentinel_equal(_Lhs._Current, _Rhs._Current))) // strengthened requires (equality_comparable>> && ...) { if constexpr (!_Zip_is_common<_Maybe_const<_IsConst, _ViewTypes>...> || _All_random_access<_IsConst, _ViewTypes...> || sizeof...(_ViewTypes) == 1) { return _STD get<0>(_Lhs._Current) == _STD get<0>(_Rhs._Current); } else { return _Zip_iterator_sentinel_equal(_Lhs._Current, _Rhs._Current); } } _NODISCARD_FRIEND constexpr auto operator<=>(const _Iterator& _Lhs, const _Iterator& _Rhs) requires _All_random_access<_IsConst, _ViewTypes...> { return _Lhs._Current <=> _Rhs._Current; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _Lhs, const difference_type _Rhs) noexcept( noexcept(_STD declval<_Iterator&>() += _Rhs) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires _All_random_access<_IsConst, _ViewTypes...> { auto _Modified_iterator = _Lhs; _Modified_iterator += _Rhs; return _Modified_iterator; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Lhs, const _Iterator& _Rhs) noexcept( noexcept(_Rhs + _Lhs)) /* strengthened */ requires _All_random_access<_IsConst, _ViewTypes...> { return _Rhs + _Lhs; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _Lhs, const difference_type _Rhs) noexcept( noexcept(_STD declval<_Iterator&>() -= _Rhs) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires _All_random_access<_IsConst, _ViewTypes...> { auto _Modified_iterator = _Lhs; _Modified_iterator -= _Rhs; return _Modified_iterator; } _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _Lhs, const _Iterator& _Rhs) noexcept( noexcept(_Zip_get_smallest_distance(_STD declval<_My_tuple>(), _STD declval<_My_tuple>()))) // strengthened requires (sized_sentinel_for>, iterator_t<_Maybe_const<_IsConst, _ViewTypes>>> && ...) { return _Zip_get_smallest_distance(_Lhs._Current, _Rhs._Current); } _NODISCARD_FRIEND constexpr auto iter_move(const _Iterator& _Itr) noexcept( (noexcept(_RANGES iter_move(_STD declval>&>())) && ...) && (is_nothrow_move_constructible_v>> && ...)) { return _Tuple_transform(_RANGES iter_move, _Itr._Current); } // clang-format off friend constexpr void iter_swap(const _Iterator& _Lhs, const _Iterator& _Rhs) noexcept((noexcept(_RANGES iter_swap( _STD declval>&>(), _STD declval>&>())) && ...)) requires (indirectly_swappable>> && ...) { // clang-format on const auto _Swap_every_pair_closure = [&_Lhs, &_Rhs ](index_sequence<_Indices...>) noexcept(noexcept( ((_RANGES iter_swap(_STD get<_Indices>(_Lhs._Current), _STD get<_Indices>(_Rhs._Current))), ...))) { ((_RANGES iter_swap(_STD get<_Indices>(_Lhs._Current), _STD get<_Indices>(_Rhs._Current))), ...); }; _Swap_every_pair_closure(index_sequence_for<_ViewTypes...>{}); } }; template class _Sentinel { private: friend zip_view; using _My_tuple = tuple>...>; /* [[no_unique_address]] */ _My_tuple _End; constexpr explicit _Sentinel(_My_tuple _End_) noexcept( is_nothrow_copy_constructible_v<_My_tuple>) // strengthened : _End(_End_) {} template _NODISCARD static constexpr const auto& _Get_iterator_tuple( const _Iterator<_IteratorConst>& _Itr) noexcept { // NOTE: This function is necessary because friend functions are never // member functions, and friendship is not transitive. return _Itr._Current; } public: _Sentinel() = default; constexpr _Sentinel(_Sentinel _Rhs) noexcept( (is_nothrow_convertible_v, sentinel_t> && ...)) // strengthened #ifdef __clang__ // TRANSITION, LLVM-47414 requires _Zip_sent_converts<_IsConst, _ViewTypes...> #else // ^^^ workaround / no workaround vvv requires (_IsConst && (convertible_to, sentinel_t> && ...)) #endif // __clang__ : _End(_STD move(_Rhs._End)) { } template requires (sentinel_for>, iterator_t<_Maybe_const<_IteratorConst, _ViewTypes>>> && ...) _NODISCARD_FRIEND constexpr bool operator==(const _Iterator<_IteratorConst>& _Lhs, const _Sentinel& _Rhs) noexcept( noexcept(_Zip_iterator_sentinel_equal(_Get_iterator_tuple(_Lhs), _Rhs._End))) /* strengthened */ { return _Zip_iterator_sentinel_equal(_Get_iterator_tuple(_Lhs), _Rhs._End); } template requires (sized_sentinel_for>, iterator_t<_Maybe_const<_IteratorConst, _ViewTypes>>> && ...) _NODISCARD_FRIEND constexpr common_type_t>...> operator-(const _Iterator<_IteratorConst>& _Lhs, const _Sentinel& _Rhs) noexcept( noexcept(_Zip_get_smallest_distance< common_type_t>...>>( _Get_iterator_tuple(_Lhs), _Rhs._End))) /* strengthened */ { using _Difference_type = common_type_t>...>; return _Zip_get_smallest_distance<_Difference_type>(_Get_iterator_tuple(_Lhs), _Rhs._End); } template requires (sized_sentinel_for>, iterator_t<_Maybe_const<_IteratorConst, _ViewTypes>>> && ...) _NODISCARD_FRIEND constexpr common_type_t>...> operator-(const _Sentinel& _Lhs, const _Iterator<_IteratorConst>& _Rhs) noexcept( noexcept(-(_Rhs - _Lhs))) /* strengthened */ { return -(_Rhs - _Lhs); } }; template _NODISCARD static consteval bool _Is_end_noexcept() noexcept { if constexpr (!_Zip_is_common<_Maybe_const<_IsConst, _ViewTypes>...>) { return noexcept(_Sentinel<_IsConst>{ _Tuple_transform(_RANGES end, _STD declval<_Maybe_const<_IsConst, tuple<_ViewTypes...>>&>())}); } else if constexpr ((random_access_range<_Maybe_const<_IsConst, _ViewTypes>> && ...)) { // Operations on iter_difference_t values must be noexcept, so we only // need to check the noexcept of begin(). return noexcept(_STD declval<_Maybe_const<_IsConst, zip_view>&>().begin()); } else { return noexcept(_Iterator<_IsConst>{ _Tuple_transform(_RANGES end, _STD declval<_Maybe_const<_IsConst, tuple<_ViewTypes...>>&>())}); } } public: zip_view() noexcept((is_nothrow_default_constructible_v<_ViewTypes> && ...)) = default; constexpr explicit zip_view(_ViewTypes... _Args) noexcept( (is_nothrow_move_constructible_v<_ViewTypes> && ...)) // strengthened : _Views(_STD move(_Args)...) {} _NODISCARD constexpr auto begin() noexcept( noexcept(_Iterator{_Tuple_transform(_RANGES begin, _Views)})) // strengthened requires (!(_Simple_view<_ViewTypes> && ...)) { return _Iterator{_Tuple_transform(_RANGES begin, _Views)}; } _NODISCARD constexpr auto begin() const noexcept(noexcept(_Iterator{_Tuple_transform(_RANGES begin, _Views)})) // strengthened requires (range && ...) { return _Iterator{_Tuple_transform(_RANGES begin, _Views)}; } _NODISCARD constexpr auto end() noexcept(_Is_end_noexcept()) // strengthened requires (!(_Simple_view<_ViewTypes> && ...)) { if constexpr (!_Zip_is_common<_ViewTypes...>) { return _Sentinel{_Tuple_transform(_RANGES end, _Views)}; } else if constexpr ((random_access_range<_ViewTypes> && ...)) { return begin() + static_cast>>(size()); } else { return _Iterator{_Tuple_transform(_RANGES end, _Views)}; } } _NODISCARD constexpr auto end() const noexcept(_Is_end_noexcept()) // strengthened requires (range && ...) { if constexpr (!_Zip_is_common) { return _Sentinel{_Tuple_transform(_RANGES end, _Views)}; } else if constexpr ((random_access_range && ...)) { return begin() + static_cast>>(size()); } else { return _Iterator{_Tuple_transform(_RANGES end, _Views)}; } } _NODISCARD constexpr auto size() noexcept( noexcept(_STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)))) // strengthened requires (sized_range<_ViewTypes> && ...) { return _STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)); } _NODISCARD constexpr auto size() const noexcept(noexcept(_STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)))) // strengthened requires (sized_range && ...) { return _STD apply(_Size_closure(), _Tuple_transform(_RANGES size, _Views)); } private: _NODISCARD static constexpr auto _Size_closure() noexcept { return [](auto... _Sizes) noexcept { using _Common_unsigned_type = _Make_unsigned_like_t>; return (_RANGES min)({static_cast<_Common_unsigned_type>(_Sizes)...}); }; } }; template zip_view(_RangeTypes&&...) -> zip_view...>; template inline constexpr bool enable_borrowed_range> = (enable_borrowed_range<_ViewTypes> && ...); namespace views { struct _Zip_fn { private: template _NODISCARD static consteval bool _Is_invocation_noexcept() { if constexpr (sizeof...(_Types) == 0) { // NOTE: views::empty> is nothrow copy-constructible. return true; } else { return noexcept(zip_view...>(_STD declval<_Types>()...)); } } public: template _NODISCARD constexpr auto operator()(_Types&&... _Args) const noexcept(_Is_invocation_noexcept<_Types...>()) requires (sizeof...(_Types) == 0) || requires { zip_view...>(_STD forward<_Types>(_Args)...); } { if constexpr (sizeof...(_Types) == 0) { return empty_view>{}; } else { return zip_view...>(_STD forward<_Types>(_Args)...); } } }; _EXPORT_STD inline constexpr _Zip_fn zip{}; } // namespace views _EXPORT_STD template requires _Zip_transform_constraints<_Func, _ViewTypes...> class zip_transform_view : public view_interface> { private: using _Inner_view = zip_view<_ViewTypes...>; /* [[no_unique_address]] */ _Movable_box<_Func> _Function; /* [[no_unique_address]] */ _Inner_view _Zip; template using _Ziperator = iterator_t<_Maybe_const<_IsConst, _Inner_view>>; template using _Zentinel = sentinel_t<_Maybe_const<_IsConst, _Inner_view>>; template struct _Category_base {}; template requires forward_range<_Maybe_const<_IsConst, _Inner_view>> struct _Category_base<_IsConst> { private: template static constexpr bool _Iterators_derive_from_tag = (derived_from< typename iterator_traits>>::iterator_category, _Tag_type> && ...); using _Invoke_t = invoke_result_t<_Maybe_const<_IsConst, _Func>&, range_reference_t<_Maybe_const<_IsConst, _ViewTypes>>...>; public: using iterator_category = conditional_t, input_iterator_tag, conditional_t<_Iterators_derive_from_tag, random_access_iterator_tag, conditional_t<_Iterators_derive_from_tag, bidirectional_iterator_tag, conditional_t<_Iterators_derive_from_tag, forward_iterator_tag, input_iterator_tag>>>>; }; template class _Iterator : public _Category_base<_IsConst> { private: friend zip_transform_view; using _Parent_t = _Maybe_const<_IsConst, zip_transform_view>; using _Base_t = _Maybe_const<_IsConst, _Inner_view>; _Parent_t* _Parent = nullptr; /* [[no_unique_address]] */ _Ziperator<_IsConst> _Inner; constexpr _Iterator(_Parent_t& _Parent_, _Ziperator<_IsConst> _Inner_) noexcept( is_nothrow_move_constructible_v<_Ziperator<_IsConst>>) // strengthened : _Parent(_STD addressof(_Parent_)), _Inner(_STD move(_Inner_)) {} public: using iterator_concept = typename _Ziperator<_IsConst>::iterator_concept; using value_type = remove_cvref_t&, range_reference_t<_Maybe_const<_IsConst, _ViewTypes>>...>>; using difference_type = range_difference_t<_Base_t>; _Iterator() = default; constexpr _Iterator(_Iterator _Rhs) noexcept( is_nothrow_convertible_v<_Ziperator, _Ziperator<_IsConst>>) // strengthened requires (_IsConst && convertible_to<_Ziperator, _Ziperator<_IsConst>>) : _Parent(_Rhs._Parent), _Inner(_STD move(_Rhs._Inner)) {} _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(_STD apply(_Dereference_closure(), _Inner._Current))) { return _STD apply(_Dereference_closure(), _Inner._Current); } constexpr _Iterator& operator++() noexcept(noexcept(++_Inner)) /* strengthened */ { ++_Inner; return *this; } constexpr void operator++(int) noexcept(noexcept(++_STD declval<_Iterator&>())) /* strengthened */ { ++*this; } constexpr _Iterator operator++(int) noexcept( is_nothrow_copy_constructible_v<_Iterator>&& noexcept(++*this)) // strengthened requires forward_range<_Base_t> { auto _Temp = *this; ++*this; return _Temp; } constexpr _Iterator& operator--() noexcept(noexcept(--_Inner)) // strengthened requires bidirectional_range<_Base_t> { --_Inner; return *this; } constexpr _Iterator operator--(int) noexcept( is_nothrow_copy_constructible_v<_Iterator>&& noexcept(--*this)) // strengthened requires bidirectional_range<_Base_t> { auto _Temp = *this; --*this; return _Temp; } constexpr _Iterator& operator+=(const difference_type _Off) noexcept( noexcept(_Inner += _Off)) // strengthened requires random_access_range<_Base_t> { _Inner += _Off; return *this; } constexpr _Iterator& operator-=(const difference_type _Off) noexcept( noexcept(_Inner -= _Off)) // strengthened requires random_access_range<_Base_t> { _Inner -= _Off; return *this; } _NODISCARD constexpr decltype(auto) operator[](const difference_type _Where) const noexcept(noexcept(_STD apply(_Subscript_closure(_Where), _Inner._Current))) // strengthened requires random_access_range<_Base_t> { return _STD apply(_Subscript_closure(_Where), _Inner._Current); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Lhs, const _Iterator& _Rhs) noexcept( noexcept(_Lhs._Inner == _Rhs._Inner)) // strengthened requires equality_comparable<_Ziperator<_IsConst>> { return _Lhs._Inner == _Rhs._Inner; } _NODISCARD_FRIEND constexpr auto operator<=>(const _Iterator& _Lhs, const _Iterator& _Rhs) noexcept( noexcept(_Lhs._Inner <=> _Rhs._Inner)) // strengthened requires random_access_range<_Base_t> { return _Lhs._Inner <=> _Rhs._Inner; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _Lhs, const difference_type _Rhs) noexcept( noexcept(_Iterator{*_Lhs._Parent, _Lhs._Inner + _Rhs})) // strengthened requires random_access_range<_Base_t> { return _Iterator{*_Lhs._Parent, _Lhs._Inner + _Rhs}; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Lhs, const _Iterator& _Rhs) noexcept( noexcept(_Iterator{*_Rhs._Parent, _Rhs._Inner + _Lhs})) // strengthened requires random_access_range<_Base_t> { return _Iterator{*_Rhs._Parent, _Rhs._Inner + _Lhs}; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _Lhs, const difference_type _Rhs) noexcept( noexcept(_Iterator{*_Lhs._Parent, _Lhs._Inner - _Rhs})) // strengthened requires random_access_range<_Base_t> { return _Iterator{*_Lhs._Parent, _Lhs._Inner - _Rhs}; } // clang-format off _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _Lhs, const _Iterator& _Rhs) noexcept(noexcept(_Lhs._Inner - _Rhs._Inner)) // strengthened requires sized_sentinel_for<_Ziperator<_IsConst>, _Ziperator<_IsConst>> { // clang-format on return _Lhs._Inner - _Rhs._Inner; } private: _NODISCARD constexpr auto _Dereference_closure() const noexcept { return [this](const auto&... _Itrs) noexcept(noexcept(_STD invoke(*_Parent->_Function, *_Itrs...))) -> decltype(auto) { return _STD invoke(*_Parent->_Function, *_Itrs...); }; } _NODISCARD constexpr auto _Subscript_closure(const difference_type _Where) const noexcept { return [this, _Where](const _Iterator_types&... _Iters) noexcept( noexcept(_STD invoke(*_Parent->_Function, _Iters[static_cast>(_Where)]...))) -> decltype(auto) { return _STD invoke( *_Parent->_Function, _Iters[static_cast>(_Where)]...); }; } }; template class _Sentinel { private: friend zip_transform_view; // TRANSITION, DevCom-10253131 template using _Iter_sent_difference_type = range_difference_t<_Maybe_const<_IteratorConst, _Inner_view>>; /* [[no_unique_address]] */ _Zentinel<_IsConst> _Inner; constexpr explicit _Sentinel(_Zentinel<_IsConst> _Inner_) noexcept( is_nothrow_copy_constructible_v<_Zentinel<_IsConst>>) // strengthened : _Inner(_Inner_) {} template _NODISCARD static constexpr const auto& _Get_iterator_inner( const _Iterator<_IteratorConst>& _Itr) noexcept { return _Itr._Inner; } public: _Sentinel() = default; constexpr _Sentinel(_Sentinel _Rhs) noexcept( is_nothrow_convertible_v<_Zentinel, _Zentinel<_IsConst>>) // strengthened requires (_IsConst && convertible_to<_Zentinel, _Zentinel<_IsConst>>) : _Inner(_STD move(_Rhs._Inner)) {} template requires sentinel_for<_Zentinel<_IsConst>, _Ziperator<_IteratorConst>> _NODISCARD_FRIEND constexpr bool operator==(const _Iterator<_IteratorConst>& _Lhs, const _Sentinel& _Rhs) noexcept(noexcept(_Get_iterator_inner(_Lhs) == _Rhs._Inner)) /* strengthened */ { return _Get_iterator_inner(_Lhs) == _Rhs._Inner; } template requires sized_sentinel_for<_Zentinel<_IsConst>, _Ziperator<_IteratorConst>> _NODISCARD_FRIEND constexpr _Iter_sent_difference_type<_IteratorConst> // TRANSITION, DevCom-10253131 operator-(const _Iterator<_IteratorConst>& _Lhs, const _Sentinel& _Rhs) noexcept( noexcept(_Get_iterator_inner(_Lhs) - _Rhs._Inner)) /* strengthened */ { return _Get_iterator_inner(_Lhs) - _Rhs._Inner; } template requires sized_sentinel_for<_Zentinel<_IsConst>, _Ziperator<_IteratorConst>> _NODISCARD_FRIEND constexpr _Iter_sent_difference_type<_IteratorConst> // TRANSITION, DevCom-10253131 operator-(const _Sentinel& _Lhs, const _Iterator<_IteratorConst>& _Rhs) noexcept( noexcept(_Lhs._Inner - _Get_iterator_inner(_Rhs))) /* strengthened */ { return _Lhs._Inner - _Get_iterator_inner(_Rhs); } }; template _NODISCARD static consteval bool _Is_end_noexcept() noexcept { if constexpr (common_range<_Maybe_const<_IsConst, _Inner_view>>) { return noexcept(_Iterator<_IsConst>{_STD declval<_Maybe_const<_IsConst, zip_transform_view>&>(), _STD declval<_Maybe_const<_IsConst, _Inner_view>&>().end()}); } else { return noexcept(_Sentinel<_IsConst>{_STD declval<_Maybe_const<_IsConst, _Inner_view>&>().end()}); } } static constexpr bool _Enable_const_begin_end = (range && regular_invocable...>); public: zip_transform_view() = default; constexpr explicit zip_transform_view(_Func _Function_, _ViewTypes... _Views) noexcept( is_nothrow_move_constructible_v<_Func>&& is_nothrow_constructible_v<_Inner_view, remove_reference_t<_ViewTypes>&&...>) // strengthened : _Function(in_place, _STD move(_Function_)), _Zip(_STD move(_Views)...) {} _NODISCARD constexpr auto begin() noexcept(noexcept(_Iterator{*this, _Zip.begin()})) /* strengthened */ { return _Iterator{*this, _Zip.begin()}; } _NODISCARD constexpr auto begin() const noexcept(noexcept(_Iterator{*this, _Zip.begin()})) // strengthened requires _Enable_const_begin_end { return _Iterator{*this, _Zip.begin()}; } _NODISCARD constexpr auto end() noexcept(_Is_end_noexcept()) /* strengthened */ { if constexpr (common_range<_Inner_view>) { return _Iterator{*this, _Zip.end()}; } else { return _Sentinel{_Zip.end()}; } } _NODISCARD constexpr auto end() const noexcept(_Is_end_noexcept()) // strengthened requires _Enable_const_begin_end { if constexpr (common_range) { return _Iterator{*this, _Zip.end()}; } else { return _Sentinel{_Zip.end()}; } } _NODISCARD constexpr auto size() noexcept(noexcept(_Zip.size())) // strengthened requires sized_range<_Inner_view> { return _Zip.size(); } _NODISCARD constexpr auto size() const noexcept(noexcept(_Zip.size())) // strengthened requires sized_range { return _Zip.size(); } }; template zip_transform_view(_Func, _Ranges&&...) -> zip_transform_view<_Func, views::all_t<_Ranges>...>; namespace views { struct _Zip_transform_fn { private: template static constexpr bool _Is_invocation_noexcept = []() noexcept { if constexpr (sizeof...(_Types) == 0) { return true; } else { return noexcept(zip_transform_view(_STD declval<_Func>(), _STD declval<_Types>()...)); } }(); template static constexpr bool _Enable_cpo = []() noexcept { if constexpr (sizeof...(_Types) == 0) { // This is a more efficient implementation of the CPO requirements listed in // N4928 [range.zip.transform.overview]/2.1.1. using _Decayed_func = decay_t<_Func>; if constexpr (move_constructible<_Decayed_func> && regular_invocable<_Decayed_func&>) { return !is_void_v>; } else { return false; } } else { // clang-format off return requires(_Func&& _Function, _Types&&... _Args) { zip_transform_view(_STD forward<_Func>(_Function), _STD forward<_Types>(_Args)...); }; // clang-format on } }(); public: template requires _Enable_cpo<_Func, _Types...> _NODISCARD constexpr auto operator()(_Func&& _Function, _Types&&... _Args) const noexcept(_Is_invocation_noexcept<_Func, _Types...>) /* strengthened */ { if constexpr (sizeof...(_Types) == 0) { using _Decayed_func = decay_t<_Func>; return empty_view>>{}; } else { return zip_transform_view(_STD forward<_Func>(_Function), _STD forward<_Types>(_Args)...); } } }; _EXPORT_STD inline constexpr _Zip_transform_fn zip_transform{}; } // namespace views template using _Repeat_type = _Ty; template struct _Repeated_tuple_impl; template struct _Repeated_tuple_impl<_Ty, index_sequence<_Indices...>> { using type = tuple<_Repeat_type<_Ty, _Indices>...>; }; template using _Repeated_tuple = typename _Repeated_tuple_impl<_Ty, make_index_sequence<_Nx>>::type; template inline constexpr bool _Regular_invocable_with_repeated_type_impl = false; template inline constexpr bool _Regular_invocable_with_repeated_type_impl<_Fn, _Ty, index_sequence<_Indices...>> = regular_invocable<_Fn, _Repeat_type<_Ty, _Indices>...>; template concept _Regular_invocable_with_repeated_type = _Regular_invocable_with_repeated_type_impl<_Fn, _Ty, make_index_sequence<_Nx>>; template struct _Invoke_result_with_repeated_type_impl; template struct _Invoke_result_with_repeated_type_impl<_Fn, _Ty, index_sequence<_Indices...>> { #if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1761088 using type = invoke_result_t<_Fn, _Repeat_type<_Ty, _Indices>...>; #else // ^^^ no workaround / workaround vvv using type = decltype(_STD invoke(_STD declval<_Fn>(), _STD declval<_Repeat_type<_Ty, _Indices>>()...)); #endif // ^^^ workaround ^^^ }; template using _Invoke_result_with_repeated_type = typename _Invoke_result_with_repeated_type_impl<_Fn, _Ty, make_index_sequence<_Nx>>::type; _EXPORT_STD template requires view<_Vw> && (_Nx > 0) class adjacent_view : public view_interface> { private: /* [[no_unique_address]] */ _Vw _Range{}; struct _As_sentinel { explicit _As_sentinel() = default; }; template class _Iterator { private: friend adjacent_view; template requires view<_Vw2> && (_Nx2 > 0) && is_object_v<_Fn> && _Regular_invocable_with_repeated_type<_Fn&, range_reference_t<_Vw2>, _Nx2> && _Can_reference<_Invoke_result_with_repeated_type<_Fn&, range_reference_t<_Vw2>, _Nx2>> friend class adjacent_transform_view; using _Base = _Maybe_const<_Const, _Vw>; using _Base_iterator = iterator_t<_Base>; array<_Base_iterator, _Nx> _Current{}; constexpr _Iterator(_Base_iterator _First, sentinel_t<_Base> _Last) { _Current.front() = _First; for (size_t _Ix = 1; _Ix < _Nx; ++_Ix) { _RANGES advance(_First, 1, _Last); _Current[_Ix] = _First; } } constexpr _Iterator(_As_sentinel, _Base_iterator _First, _Base_iterator _Last) { if constexpr (!bidirectional_range<_Base>) { _Current.fill(_Last); } else { _Current.back() = _Last; for (size_t _Ix = 1; _Ix < _Nx; ++_Ix) { _RANGES advance(_Last, -1, _First); _Current[_Nx - 1 - _Ix] = _Last; } } } template constexpr _Iterator(_Iterator& _Other, index_sequence<_Indices...>) noexcept( is_nothrow_convertible_v, _Base_iterator>) requires _Const && convertible_to, _Base_iterator> : _Current{_STD move(_Other._Current[_Indices])...} {} public: using iterator_category = input_iterator_tag; using iterator_concept = conditional_t, random_access_iterator_tag, conditional_t, bidirectional_iterator_tag, forward_iterator_tag>>; using value_type = _Repeated_tuple, _Nx>; using difference_type = range_difference_t<_Base>; _Iterator() = default; constexpr _Iterator(_Iterator _Other) noexcept( is_nothrow_convertible_v, _Base_iterator>) // strengthened requires _Const && convertible_to, _Base_iterator> : _Iterator(_Other, make_index_sequence<_Nx>{}) {} _NODISCARD constexpr auto operator*() const { return _RANGES _Tuple_transform([](auto& _It) -> decltype(auto) { return *_It; }, _Current); } constexpr _Iterator& operator++() noexcept(noexcept(++_Current.front())) /* strengthened */ { for (_Base_iterator& _It : _Current) { ++_It; } return *this; } constexpr _Iterator operator++(int) noexcept( noexcept(++*this) && is_nothrow_copy_constructible_v<_Iterator>) /* strengthened */ { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() noexcept(noexcept(--_Current.back())) // strengthened requires bidirectional_range<_Base> { for (_Base_iterator& _It : _Current) { --_It; } return *this; } constexpr _Iterator operator--(int) noexcept( noexcept(--*this) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires bidirectional_range<_Base> { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(const difference_type _Off) noexcept( noexcept(_Current.back() += _Off)) // strengthened requires random_access_range<_Base> { for (_Base_iterator& _It : _Current) { _It += _Off; } return *this; } constexpr _Iterator& operator-=(const difference_type _Off) noexcept( noexcept(_Current.back() -= _Off)) // strengthened requires random_access_range<_Base> { for (_Base_iterator& _It : _Current) { _It -= _Off; } return *this; } _NODISCARD constexpr auto operator[](const difference_type _Off) const requires random_access_range<_Base> { return _RANGES _Tuple_transform([&](auto& _It) -> decltype(auto) { return _It[_Off]; }, _Current); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_Left._Current.back() == _Right._Current.back()))) /* strengthened */ { return _Left._Current.back() == _Right._Current.back(); } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Fake_copy_init(_Left._Current.back() < _Right._Current.back()))) // strengthened requires random_access_range<_Base> { return _Left._Current.back() < _Right._Current.back(); } _NODISCARD_FRIEND constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Right < _Left)) // strengthened requires random_access_range<_Base> { return _Right < _Left; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(!(_Right < _Left))) // strengthened requires random_access_range<_Base> { return !(_Right < _Left); } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(!(_Left < _Right))) // strengthened requires random_access_range<_Base> { return !(_Left < _Right); } _NODISCARD_FRIEND constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Current.back() <=> _Right._Current.back())) // strengthened requires random_access_range<_Base> && three_way_comparable<_Base_iterator> { return _Left._Current.back() <=> _Right._Current.back(); } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept( noexcept(_STD declval<_Iterator&>() += _Off) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires random_access_range<_Base> { auto _Tmp = _It; _Tmp += _Off; return _Tmp; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) noexcept( noexcept(_STD declval<_Iterator&>() += _Off) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires random_access_range<_Base> { auto _Tmp = _It; _Tmp += _Off; return _Tmp; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) noexcept( noexcept(_STD declval<_Iterator&>() -= _Off) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires random_access_range<_Base> { auto _Tmp = _It; _Tmp -= _Off; return _Tmp; } _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Current.back() - _Right._Current.back())) // strengthened requires sized_sentinel_for<_Base_iterator, _Base_iterator> { return _Left._Current.back() - _Right._Current.back(); } _NODISCARD_FRIEND constexpr auto iter_move(const _Iterator& _It) noexcept( noexcept(_RANGES iter_move(_STD declval())) && is_nothrow_move_constructible_v>) { return _RANGES _Tuple_transform(_RANGES iter_move, _It._Current); } friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_RANGES iter_swap(_STD declval<_Base_iterator>(), _STD declval<_Base_iterator>()))) requires indirectly_swappable<_Base_iterator> { for (size_t _Ix = 0; _Ix < _Nx; ++_Ix) { _RANGES iter_swap(_Left._Current[_Ix], _Right._Current[_Ix]); } } }; template class _Sentinel { private: friend adjacent_view; using _Base = _Maybe_const<_Const, _Vw>; using _Base_sentinel = sentinel_t<_Base>; /* [[no_unique_address]] */ _Base_sentinel _End{}; constexpr explicit _Sentinel(_Base_sentinel _Last_) noexcept( is_nothrow_move_constructible_v<_Base_sentinel>) // strengthened : _End(_STD move(_Last_)) {} template requires sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const noexcept(noexcept(_Fake_copy_init(_It._Current.back() == _End))) { return _It._Current.back() == _End; } template requires sized_sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> _Distance_from( const _Iterator<_OtherConst>& _It) const noexcept(noexcept(_End - _It._Current.back())) { return _End - _It._Current.back(); } public: _Sentinel() = default; constexpr _Sentinel(_Sentinel _Other) noexcept( is_nothrow_convertible_v, _Base_sentinel>) // strengthened requires _Const && convertible_to, _Base_sentinel> : _End(_STD move(_Other._End)) {} template requires sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD_FRIEND constexpr bool operator==(const _Iterator<_OtherConst>& _It, const _Sentinel& _Se) noexcept(noexcept(_Se._Equal(_It))) /* strengthened */ { return _Se._Equal(_It); } template requires sized_sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD_FRIEND constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-( const _Iterator<_OtherConst>& _It, const _Sentinel& _Se) noexcept( // noexcept(_Se._Distance_from(_It))) /* strengthened */ { return -_Se._Distance_from(_It); } template requires sized_sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD_FRIEND constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-( const _Sentinel& _Se, const _Iterator<_OtherConst>& _It) noexcept( // noexcept(_Se._Distance_from(_It))) /* strengthened */ { return _Se._Distance_from(_It); } }; public: // clang-format off adjacent_view() requires default_initializable<_Vw> = default; // clang-format on constexpr explicit adjacent_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() requires (!_Simple_view<_Vw>) { return _Iterator{_RANGES begin(_Range), _RANGES end(_Range)}; } _NODISCARD constexpr auto begin() const requires range { return _Iterator{_RANGES begin(_Range), _RANGES end(_Range)}; } _NODISCARD constexpr auto end() requires (!_Simple_view<_Vw>) { if constexpr (common_range<_Vw>) { return _Iterator{_As_sentinel{}, _RANGES begin(_Range), _RANGES end(_Range)}; } else { return _Sentinel{_RANGES end(_Range)}; } } _NODISCARD constexpr auto end() const requires range { if constexpr (common_range) { return _Iterator{_As_sentinel{}, _RANGES begin(_Range), _RANGES end(_Range)}; } else { return _Sentinel{_RANGES end(_Range)}; } } _NODISCARD constexpr auto size() noexcept(noexcept(_RANGES size(_Range))) // strengthened requires sized_range<_Vw> { using _Size_type = decltype(_RANGES size(_Range)); using _Common_size_type = common_type_t<_Size_type, size_t>; auto _Size = static_cast<_Common_size_type>(_RANGES size(_Range)); _Size -= (_STD min)(_Size, static_cast<_Common_size_type>(_Nx - 1)); return static_cast<_Size_type>(_Size); } _NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(_Range))) // strengthened requires sized_range { using _Size_type = decltype(_RANGES size(_Range)); using _Common_size_type = common_type_t<_Size_type, size_t>; auto _Size = static_cast<_Common_size_type>(_RANGES size(_Range)); _Size -= (_STD min)(_Size, static_cast<_Common_size_type>(_Nx - 1)); return static_cast<_Size_type>(_Size); } }; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { template class _Adjacent_fn : public _Pipe::_Base<_Adjacent_fn<_Nx>> { public: template _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(noexcept(adjacent_view, _Nx>{_STD forward<_Rng>(_Range)})) requires requires { adjacent_view, _Nx>{_STD forward<_Rng>(_Range)}; } { return adjacent_view, _Nx>{_STD forward<_Rng>(_Range)}; } template _NODISCARD constexpr auto operator()(_Rng&&) const noexcept requires (_Nx == 0) { return empty_view>{}; } }; _EXPORT_STD template inline constexpr _Adjacent_fn<_Nx> adjacent; _EXPORT_STD inline constexpr _Adjacent_fn<2> pairwise; } // namespace views _EXPORT_STD template requires view<_Vw> && (_Nx > 0) && is_object_v<_Fn> && _Regular_invocable_with_repeated_type<_Fn&, range_reference_t<_Vw>, _Nx> && _Can_reference<_Invoke_result_with_repeated_type<_Fn&, range_reference_t<_Vw>, _Nx>> class adjacent_transform_view : public view_interface> { private: using _Inner_view = adjacent_view<_Vw, _Nx>; template using _Inner_iterator = iterator_t<_Maybe_const<_Const, _Inner_view>>; template using _Inner_sentinel = sentinel_t<_Maybe_const<_Const, _Inner_view>>; /* [[no_unique_address]] */ _Movable_box<_Fn> _Func; /* [[no_unique_address]] */ _Inner_view _Inner; template class _Iterator { private: friend adjacent_transform_view; using _Parent_t = _Maybe_const<_Const, adjacent_transform_view>; using _Base = _Maybe_const<_Const, _Vw>; _Parent_t* _Parent = nullptr; _Inner_iterator<_Const> _Inner; constexpr _Iterator(_Parent_t& _Parent_, _Inner_iterator<_Const> _Inner_) noexcept( is_nothrow_move_constructible_v<_Inner_iterator<_Const>>) // strengthened : _Parent(_STD addressof(_Parent_)), _Inner(_STD move(_Inner_)) {} _NODISCARD static _CONSTEVAL auto _Get_iterator_category() noexcept { if constexpr (!is_reference_v<_Invoke_result_with_repeated_type<_Maybe_const<_Const, _Fn>&, range_reference_t<_Base>, _Nx>>) { return input_iterator_tag{}; } else { using _Cat = typename iterator_traits>::iterator_category; if constexpr (derived_from<_Cat, random_access_iterator_tag>) { return random_access_iterator_tag{}; } else if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) { return bidirectional_iterator_tag{}; } else if constexpr (derived_from<_Cat, forward_iterator_tag>) { return forward_iterator_tag{}; } else { return input_iterator_tag{}; } } } template _NODISCARD static _CONSTEVAL bool _Is_indirection_nothrow(index_sequence<_Indices...>) noexcept { return noexcept(_STD invoke(_STD declval<_Maybe_const<_Const, _Fn>&>(), *_STD get<_Indices>(_STD declval&>()._Current)...)); } public: using iterator_category = decltype(_Get_iterator_category()); using iterator_concept = typename _Inner_iterator<_Const>::iterator_concept; using value_type = remove_cvref_t< _Invoke_result_with_repeated_type<_Maybe_const<_Const, _Fn>&, range_reference_t<_Base>, _Nx>>; using difference_type = range_difference_t<_Base>; _Iterator() = default; constexpr _Iterator(_Iterator _Other) requires _Const && convertible_to<_Inner_iterator, _Inner_iterator<_Const>> : _Parent(_Other._Parent), _Inner(_STD move(_Other._Inner)) {} _NODISCARD constexpr decltype(auto) operator*() const noexcept(_Is_indirection_nothrow(make_index_sequence<_Nx>{})) { return _STD apply( [&](const auto&... _Iters) -> decltype(auto) { return _STD invoke(*_Parent->_Func, *_Iters...); }, _Inner._Current); } constexpr _Iterator& operator++() noexcept(noexcept(++_Inner)) /* strengthened */ { ++_Inner; return *this; } constexpr _Iterator operator++(int) noexcept( noexcept(++*this) && is_nothrow_copy_constructible_v<_Iterator>) /* strengthened */ { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() noexcept(noexcept(--_Inner)) /* strengthened */ requires bidirectional_range<_Base> { --_Inner; return *this; } constexpr _Iterator operator--(int) noexcept( noexcept(--*this) && is_nothrow_copy_constructible_v<_Iterator>) // strengthened requires bidirectional_range<_Base> { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(const difference_type _Off) noexcept( noexcept(_Inner += _Off)) // strengthened requires random_access_range<_Base> { _Inner += _Off; return *this; } constexpr _Iterator& operator-=(const difference_type _Off) noexcept( noexcept(_Inner -= _Off)) // strengthened requires random_access_range<_Base> { _Inner -= _Off; return *this; } _NODISCARD constexpr decltype(auto) operator[](const difference_type _Off) const requires random_access_range<_Base> { return _STD apply( [&](const auto&... _Iters) -> decltype(auto) { return _STD invoke(*_Parent->_Func, _Iters[_Off]...); }, _Inner._Current); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Inner == _Right._Inner)) /* strengthened */ { return _Left._Inner == _Right._Inner; } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Inner < _Right._Inner)) // strengthened requires random_access_range<_Base> { return _Left._Inner < _Right._Inner; } _NODISCARD_FRIEND constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Inner > _Right._Inner)) // strengthened requires random_access_range<_Base> { return _Left._Inner > _Right._Inner; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Inner <= _Right._Inner)) // strengthened requires random_access_range<_Base> { return _Left._Inner <= _Right._Inner; } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Inner >= _Right._Inner)) // strengthened requires random_access_range<_Base> { return _Left._Inner >= _Right._Inner; } _NODISCARD_FRIEND constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right) noexcept( noexcept(_Left._Inner <=> _Right._Inner)) // strengthened requires random_access_range<_Base> && three_way_comparable<_Inner_iterator<_Const>> { return _Left._Inner <=> _Right._Inner; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) noexcept( noexcept(_It._Inner + _Off) && is_nothrow_move_constructible_v<_Inner_iterator<_Const>>) // strengthened requires random_access_range<_Base> { return _Iterator{*_It._Parent, _It._Inner + _Off}; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) noexcept( noexcept(_It._Inner + _Off) && is_nothrow_move_constructible_v<_Inner_iterator<_Const>>) // strengthened requires random_access_range<_Base> { return _Iterator{*_It._Parent, _It._Inner + _Off}; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) noexcept( noexcept(_It._Inner - _Off) && is_nothrow_move_constructible_v<_Inner_iterator<_Const>>) // strengthened requires random_access_range<_Base> { return _Iterator{*_It._Parent, _It._Inner - _Off}; } _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _Left, const _Iterator& _Right) // noexcept(noexcept(_Left._Inner - _Right._Inner)) // strengthened requires sized_sentinel_for<_Inner_iterator<_Const>, _Inner_iterator<_Const>> { return _Left._Inner - _Right._Inner; } }; template class _Sentinel { private: friend adjacent_transform_view; /* [[no_unique_address]] */ _Inner_sentinel<_Const> _Inner; constexpr explicit _Sentinel(_Inner_sentinel<_Const> _Inner_) : _Inner(_Inner_) {} template requires sentinel_for<_Inner_sentinel<_Const>, _Inner_iterator<_OtherConst>> _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const noexcept(noexcept(_It._Inner == _Inner)) { return _It._Inner == _Inner; } template requires sized_sentinel_for<_Inner_sentinel<_Const>, _Inner_iterator<_OtherConst>> _NODISCARD constexpr range_difference_t<_Maybe_const<_OtherConst, _Inner_view>> _Distance_from( const _Iterator<_OtherConst>& _It) const noexcept(noexcept(_Inner - _It._Inner)) { return _Inner - _It._Inner; } public: _Sentinel() = default; constexpr _Sentinel(_Sentinel _Other) requires _Const && convertible_to<_Inner_sentinel, _Inner_sentinel<_Const>> : _Inner(_STD move(_Other._Inner)) {} template requires sentinel_for<_Inner_sentinel<_Const>, _Inner_iterator<_OtherConst>> _NODISCARD_FRIEND constexpr bool operator==(const _Iterator<_OtherConst>& _It, const _Sentinel& _Se) noexcept(noexcept(_Se._Equal(_It))) /* strengthened */ { return _Se._Equal(_It); } template requires sized_sentinel_for<_Inner_sentinel<_Const>, _Inner_iterator<_OtherConst>> _NODISCARD_FRIEND constexpr range_difference_t<_Maybe_const<_OtherConst, _Inner_view>> operator-( const _Iterator<_OtherConst>& _It, const _Sentinel& _Se) noexcept( // noexcept(_Se._Distance_from(_It))) /* strengthened */ { return -_Se._Distance_from(_It); } template requires sized_sentinel_for<_Inner_sentinel<_Const>, _Inner_iterator<_OtherConst>> _NODISCARD_FRIEND constexpr range_difference_t<_Maybe_const<_OtherConst, _Inner_view>> operator-( const _Sentinel& _Se, const _Iterator<_OtherConst>& _It) noexcept( // noexcept(_Se._Distance_from(_It))) /* strengthened */ { return _Se._Distance_from(_It); } }; public: adjacent_transform_view() = default; constexpr explicit adjacent_transform_view(_Vw _Range_, _Fn _Func_) noexcept( is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Fn>) // strengthened : _Func(in_place, _STD move(_Func_)), _Inner(_STD move(_Range_)) {} _NODISCARD constexpr _Vw base() const& noexcept(noexcept(_Inner.base())) // strengthened requires copy_constructible<_Inner_view> { return _Inner.base(); } _NODISCARD constexpr _Vw base() && noexcept(noexcept(_STD move(_Inner).base())) /* strengthened */ { return _STD move(_Inner).base(); } _NODISCARD constexpr auto begin() { return _Iterator{*this, _Inner.begin()}; } _NODISCARD constexpr auto begin() const requires range && _Regular_invocable_with_repeated_type, _Nx> { return _Iterator{*this, _Inner.begin()}; } _NODISCARD constexpr auto end() { if constexpr (common_range<_Inner_view>) { return _Iterator{*this, _Inner.end()}; } else { return _Sentinel{_Inner.end()}; } } _NODISCARD constexpr auto end() const requires range && _Regular_invocable_with_repeated_type, _Nx> { if constexpr (common_range) { return _Iterator{*this, _Inner.end()}; } else { return _Sentinel{_Inner.end()}; } } _NODISCARD constexpr auto size() noexcept(noexcept(_Inner.size())) // strengthened requires sized_range<_Inner_view> { return _Inner.size(); } _NODISCARD constexpr auto size() const noexcept(noexcept(_Inner.size())) // strengthened requires sized_range { return _Inner.size(); } }; namespace views { template class _Adjacent_transform_fn { public: template _NODISCARD constexpr auto operator()(_Rng&&, _Fn&& _Func) const noexcept(noexcept(views::zip_transform(_STD forward<_Fn>(_Func)))) requires (_Nx == 0) #ifndef __clang__ // TRANSITION, Clang 16 && requires { views::zip_transform(_STD forward<_Fn>(_Func)); } #endif // __clang__ { return views::zip_transform(_STD forward<_Fn>(_Func)); } template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Fn&& _Func) const noexcept(noexcept(adjacent_transform_view, decay_t<_Fn>, _Nx>( _STD forward<_Rng>(_Range), _STD forward<_Fn>(_Func)))) requires requires { adjacent_transform_view, decay_t<_Fn>, _Nx>( _STD forward<_Rng>(_Range), _STD forward<_Fn>(_Func)); } { return adjacent_transform_view, decay_t<_Fn>, _Nx>( _STD forward<_Rng>(_Range), _STD forward<_Fn>(_Func)); } template requires constructible_from, _Fn> _NODISCARD constexpr auto operator()(_Fn&& _Func) const noexcept(is_nothrow_constructible_v, _Fn>) { return _Range_closure<_Adjacent_transform_fn, decay_t<_Fn>>{_STD forward<_Fn>(_Func)}; } }; _EXPORT_STD template inline constexpr _Adjacent_transform_fn<_Nx> adjacent_transform; _EXPORT_STD inline constexpr _Adjacent_transform_fn<2> pairwise_transform; } // namespace views template <_Integer_like _Int> _NODISCARD constexpr bool _Add_with_overflow_check(const _Int _Left, const _Int _Right, _Int& _Out) { #ifdef __clang__ if constexpr (integral<_Int>) { return __builtin_add_overflow(_Left, _Right, &_Out); } else #endif // __clang__ { if constexpr (!_Signed_integer_like<_Int>) { _Out = static_cast<_Int>(_Left + _Right); return _Out < _Left || _Out < _Right; } else { using _UInt = _Make_unsigned_like_t<_Int>; _Out = static_cast<_Int>(static_cast<_UInt>(_Left) + static_cast<_UInt>(_Right)); return (_Left > 0 && _Right > 0 && _Out <= 0) || (_Left < 0 && _Right < 0 && _Out >= 0); } } } template <_Integer_like _Int> _NODISCARD constexpr bool _Multiply_with_overflow_check(const _Int _Left, const _Int _Right, _Int& _Out) { #ifdef __clang__ if constexpr (integral<_Int>) { return __builtin_mul_overflow(_Left, _Right, &_Out); } else #endif // __clang__ { if constexpr (!_Signed_integer_like<_Int>) { _Out = static_cast<_Int>(_Left * _Right); return _Left != 0 && _Right > (numeric_limits<_Int>::max)() / _Left; } else { // vvv Based on llvm::MulOverflow vvv // https://github.com/llvm/llvm-project/blob/88e5206/llvm/include/llvm/Support/MathExtras.h#L725-L750 //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// using _UInt = _Make_unsigned_like_t<_Int>; const _UInt _ULeft = _Left < 0 ? (0 - static_cast<_UInt>(_Left)) : static_cast<_UInt>(_Left); const _UInt _URight = _Right < 0 ? (0 - static_cast<_UInt>(_Right)) : static_cast<_UInt>(_Right); const _UInt _UResult = static_cast<_UInt>(_ULeft * _URight); const bool _Negative = (_Left < 0) != (_Right < 0); _Out = static_cast<_Int>(_Negative ? (0 - _UResult) : _UResult); if (_ULeft == 0 || _URight == 0) { return false; } if (_Negative) { return _ULeft > (static_cast<_UInt>((numeric_limits<_Int>::max)()) + _UInt{1}) / _URight; } else { return _ULeft > static_cast<_UInt>((numeric_limits<_Int>::max)()) / _URight; } // ^^^ Based on llvm::MulOverflow ^^^ } } } template concept _Cartesian_product_is_random_access = (random_access_range<_Maybe_const<_Const, _First>> && ... && (random_access_range<_Maybe_const<_Const, _Rest>> && sized_range<_Maybe_const<_Const, _Rest>>) ); template concept _Cartesian_product_common_arg = common_range<_Rng> || (sized_range<_Rng> && random_access_range<_Rng>); template concept _Cartesian_product_is_bidirectional = (bidirectional_range<_Maybe_const<_Const, _First>> && ... && (bidirectional_range<_Maybe_const<_Const, _Rest>> && _Cartesian_product_common_arg<_Maybe_const<_Const, _Rest>>) ); template concept _Cartesian_product_is_common = _Cartesian_product_common_arg<_First>; template concept _Cartesian_product_is_sized = (sized_range<_Rngs> && ...); template class _FirstSent, class _First, class... _Rest> concept _Cartesian_is_sized_sentinel = (sized_sentinel_for<_FirstSent<_Maybe_const<_Const, _First>>, iterator_t<_Maybe_const<_Const, _First>>> && ... && (sized_range<_Maybe_const<_Const, _Rest>> && sized_sentinel_for>, iterator_t<_Maybe_const<_Const, _Rest>>>) ); template <_Cartesian_product_common_arg _Rng> _NODISCARD constexpr auto _Cartesian_common_arg_end(_Rng& _Range) { if constexpr (common_range<_Rng>) { return _RANGES end(_Range); } else { return _RANGES begin(_Range) + _RANGES distance(_Range); } } template inline constexpr auto _Compile_time_max_size = (numeric_limits>::max)(); template concept _Constant_sized_range = sized_range<_Ty> && requires { typename _Require_constant::size()>; }; template <_Constant_sized_range _Ty> inline constexpr auto _Compile_time_max_size<_Ty> = remove_reference_t<_Ty>::size(); template inline constexpr auto _Compile_time_max_size> = _Size; template inline constexpr auto _Compile_time_max_size> = _Size; template requires (_Extent != dynamic_extent) inline constexpr auto _Compile_time_max_size> = _Extent; template requires (_Extent != dynamic_extent) inline constexpr auto _Compile_time_max_size> = _Extent; template inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Ty>; template requires sized_range inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; template inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Ty>; template requires sized_range inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; template _NODISCARD _CONSTEVAL int _Cartesian_product_max_size_bit_width() noexcept { if constexpr (sized_range<_Rng>) { if constexpr (requires(range_size_t<_Rng> _Val) { _STD bit_width(_Val); }) { return _STD bit_width(_Compile_time_max_size<_Rng>); } else { return numeric_limits>::digits; } } else { return numeric_limits<_Make_unsigned_like_t>>::digits; } } template _NODISCARD _CONSTEVAL auto _Cartesian_product_optimal_size_type() noexcept { constexpr int _Optimal_size_type_bit_width = (_Cartesian_product_max_size_bit_width<_First>() + ... + _Cartesian_product_max_size_bit_width<_Rest>()); if constexpr (_Optimal_size_type_bit_width <= 8) { return uint_least8_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 16) { return uint_least16_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 32) { return uint_least32_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 64) { return uint_least64_t{}; } else { return _Unsigned128{}; } } _EXPORT_STD template requires (view<_First> && ... && view<_Rest>) class cartesian_product_view : public view_interface> { private: template using _Optimal_size_type = decltype(_Cartesian_product_optimal_size_type<_Maybe_const<_Const, _First>, _Maybe_const<_Const, _Rest>...>()); template using _Difference_type = common_type_t<_Make_signed_like_t<_Optimal_size_type<_Const>>, range_difference_t<_Maybe_const<_Const, _First>>, range_difference_t<_Maybe_const<_Const, _Rest>>...>; template using _Size_type = common_type_t<_Optimal_size_type<_Const>, range_size_t<_Maybe_const<_Const, _First>>, range_size_t<_Maybe_const<_Const, _Rest>>...>; /* [[no_unique_address]] */ tuple<_First, _Rest...> _Bases; template class _Iterator { private: friend cartesian_product_view; using _Parent_t = _Maybe_const<_Const, cartesian_product_view>; _Parent_t* _Parent = nullptr; tuple>, iterator_t<_Maybe_const<_Const, _Rest>>...> _Current; template constexpr void _Next() { auto& _It = _STD get<_Index>(_Current); ++_It; if constexpr (_Index > 0) { auto& _Range = _STD get<_Index>(_Parent->_Bases); if (_It == _RANGES end(_Range)) { _It = _RANGES begin(_Range); _Next<_Index - 1>(); } } } template constexpr void _Prev() { auto& _It = _STD get<_Index>(_Current); if constexpr (_Index > 0) { auto& _Range = _STD get<_Index>(_Parent->_Bases); if (_It == _RANGES begin(_Range)) { _It = _Cartesian_common_arg_end(_Range); _Prev<_Index - 1>(); } } --_It; } template _NODISCARD constexpr bool _Entire_tail_at_begin(index_sequence<_Indices...>) const { return ((_STD get<_Indices + 1>(_Current) == _RANGES begin(_STD get<_Indices + 1>(_Parent->_Bases))) && ...); } template constexpr void _Advance(const _Difference_type<_Const> _Off) { if (_Off == 0) { return; } auto& _Range = _STD get<_Index>(_Parent->_Bases); auto& _It = _STD get<_Index>(_Current); using _Iter = remove_reference_t; using _Diff = _Difference_type<_Const>; if constexpr (_Index > 0) { const auto _Size = static_cast<_Diff>(_RANGES ssize(_Range)); const auto _Begin = _RANGES begin(_Range); const auto _It_off = static_cast<_Diff>(_It - _Begin); const auto _It_new_off = static_cast<_Diff>((_It_off + _Off) % _Size); const auto _Next_off = static_cast<_Diff>((_It_off + _Off) / _Size); if (_It_new_off < 0) { _It = _Begin + static_cast>(_It_new_off + _Size); _Advance<_Index - 1>(_Next_off - 1); } else { _It = _Begin + static_cast>(_It_new_off); _Advance<_Index - 1>(_Next_off); } } else { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _It_off = static_cast<_Diff>(_It - _RANGES begin(_Range)); _STL_VERIFY(_It_off + _Off >= 0, "Cannot advance cartesian_product_view iterator before begin " "(N4928 [range.cartesian.iterator]/19)."); if constexpr (sized_range) { const auto _Size = static_cast<_Diff>(_RANGES ssize(_Range)); _STL_VERIFY(_It_off + _Off < _Size || (_It_off + _Off == _Size && _Entire_tail_at_begin(make_index_sequence{})), "Cannot advance cartesian_product_view iterator past end (N4928 " "[range.cartesian.iterator]/19)."); } #endif // _ITERATOR_DEBUG_LEVEL != 0 _It += static_cast>(_Off); } } template _NODISCARD constexpr bool _Is_end(index_sequence<_Indices...>) const { return ((_STD get<_Indices>(_Current) == _RANGES end(_STD get<_Indices>(_Parent->_Bases))) || ...); } template _NODISCARD constexpr auto _End_tuple(index_sequence<_Indices...>) const { return tuple>, iterator_t<_Maybe_const<_Const, _Rest>>...>{ _RANGES end(_STD get<0>(_Parent->_Bases)), _RANGES begin(_STD get<_Indices + 1>(_Parent->_Bases))...}; } template _NODISCARD constexpr _Difference_type<_Const> _Distance_from(const _Tuple& _Tpl) const { const auto _Diff = static_cast<_Difference_type<_Const>>(_STD get<_Index>(_Current) - _STD get<_Index>(_Tpl)); if constexpr (_Index > 0) { _Difference_type<_Const> _Result{1}; const auto _Size = static_cast<_Difference_type<_Const>>(_RANGES size(_STD get<_Index>(_Parent->_Bases))); [[maybe_unused]] const bool _Overflow = _Multiply_with_overflow_check(_Size, _Distance_from<_Index - 1>(_Tpl), _Result) || _Add_with_overflow_check(_Result, _Diff, _Result); #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Overflow, "Scaled-sum cannot be represented by difference_type (N4928 " "[range.cartesian.iterator]/8)."); #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Result; } else { return _Diff; } } template _NODISCARD static _CONSTEVAL bool _Is_iter_move_nothrow(index_sequence<_Indices...>) noexcept { return conjunction_v< is_nothrow_move_constructible>>, is_nothrow_move_constructible>>...> && (noexcept(_RANGES iter_move(_STD get<_Indices>(_STD declval()._Current))) && ...); } template _NODISCARD static _CONSTEVAL bool _Is_iter_swap_nothrow(index_sequence<_Indices...>) noexcept { return (noexcept(_RANGES iter_swap(_STD get<_Indices>(_STD declval()._Current), _STD get<_Indices>(_STD declval()._Current))) && ...); } constexpr _Iterator(_Parent_t& _Parent_, tuple>, iterator_t<_Maybe_const<_Const, _Rest>>...> _Current_) : _Parent(_STD addressof(_Parent_)), _Current(_STD move(_Current_)) {} public: using iterator_category = input_iterator_tag; using iterator_concept = conditional_t<_Cartesian_product_is_random_access<_Const, _First, _Rest...>, random_access_iterator_tag, conditional_t<_Cartesian_product_is_bidirectional<_Const, _First, _Rest...>, bidirectional_iterator_tag, conditional_t>, forward_iterator_tag, input_iterator_tag>>>; using value_type = tuple>, range_value_t<_Maybe_const<_Const, _Rest>>...>; using reference = tuple>, range_reference_t<_Maybe_const<_Const, _Rest>>...>; using difference_type = _Difference_type<_Const>; _Iterator() = default; constexpr _Iterator(_Iterator _It) requires _Const && (convertible_to, iterator_t> && ... && convertible_to, iterator_t>) : _Parent(_It._Parent), _Current(_STD move(_It._Current)) {} _NODISCARD constexpr auto operator*() const { return _RANGES _Tuple_transform([](auto& _It) -> decltype(auto) { return *_It; }, _Current); } constexpr _Iterator& operator++() { _Next(); return *this; } constexpr void operator++(int) { ++*this; } constexpr _Iterator operator++(int) requires forward_range<_Maybe_const<_Const, _First>> { auto _Tmp = *this; ++*this; return _Tmp; } constexpr _Iterator& operator--() requires _Cartesian_product_is_bidirectional<_Const, _First, _Rest...> { _Prev(); return *this; } constexpr _Iterator operator--(int) requires _Cartesian_product_is_bidirectional<_Const, _First, _Rest...> { auto _Tmp = *this; --*this; return _Tmp; } constexpr _Iterator& operator+=(const difference_type _Off) requires _Cartesian_product_is_random_access<_Const, _First, _Rest...> { _Advance(_Off); return *this; } constexpr _Iterator& operator-=(const difference_type _Off) requires _Cartesian_product_is_random_access<_Const, _First, _Rest...> { _Advance(-_Off); return *this; } _NODISCARD constexpr reference operator[](const difference_type _Off) const requires _Cartesian_product_is_random_access<_Const, _First, _Rest...> { return *(*this + _Off); } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) requires equality_comparable>> { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _It, default_sentinel_t) { return _It._Is_end(make_index_sequence<1 + sizeof...(_Rest)>{}); } _NODISCARD_FRIEND constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right) requires _All_random_access<_Const, _First, _Rest...> { return _Left._Current <=> _Right._Current; } _NODISCARD_FRIEND constexpr _Iterator operator+(const _Iterator& _It, const difference_type _Off) requires _Cartesian_product_is_random_access<_Const, _First, _Rest...> { return _Iterator{_It} += _Off; } _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, const _Iterator& _It) requires _Cartesian_product_is_random_access<_Const, _First, _Rest...> { return _It + _Off; } _NODISCARD_FRIEND constexpr _Iterator operator-(const _Iterator& _It, const difference_type _Off) requires _Cartesian_product_is_random_access<_Const, _First, _Rest...> { return _Iterator{_It} -= _Off; } _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _Left, const _Iterator& _Right) requires _Cartesian_is_sized_sentinel<_Const, iterator_t, _First, _Rest...> { return _Left._Distance_from(_Right._Current); } _NODISCARD_FRIEND constexpr difference_type operator-(const _Iterator& _It, default_sentinel_t) requires _Cartesian_is_sized_sentinel<_Const, sentinel_t, _First, _Rest...> { return _It._Distance_from(_It._End_tuple(make_index_sequence{})); } _NODISCARD_FRIEND constexpr difference_type operator-(default_sentinel_t _Se, const _Iterator& _It) requires _Cartesian_is_sized_sentinel<_Const, sentinel_t, _First, _Rest...> { return -(_It - _Se); } _NODISCARD_FRIEND constexpr auto iter_move(const _Iterator& _It) noexcept( _Is_iter_move_nothrow(make_index_sequence<1 + sizeof...(_Rest)>{})) { return _RANGES _Tuple_transform(_RANGES iter_move, _It._Current); } friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) noexcept( _Is_iter_swap_nothrow(make_index_sequence<1 + sizeof...(_Rest)>{})) requires (indirectly_swappable>> && ... && indirectly_swappable>>) { return [&](index_sequence<_Indices...>) { return (_RANGES iter_swap(_STD get<_Indices>(_Left._Current), _STD get<_Indices>(_Right._Current)), ...); } (make_index_sequence<1 + sizeof...(_Rest)>{}); } }; template _NODISCARD constexpr auto _Begin_or_first_end([[maybe_unused]] const bool _Is_empty) { if constexpr (_Index == 0) { return _Is_empty ? _RANGES begin(_STD get<_Index>(_Bases)) : _Cartesian_common_arg_end(_STD get<_Index>(_Bases)); } else { return _RANGES begin(_STD get<_Index>(_Bases)); } } template _NODISCARD constexpr auto _Begin_or_first_end([[maybe_unused]] const bool _Is_empty) const { if constexpr (_Index == 0) { return _Is_empty ? _RANGES begin(_STD get<_Index>(_Bases)) : _Cartesian_common_arg_end(_STD get<_Index>(_Bases)); } else { return _RANGES begin(_STD get<_Index>(_Bases)); } } public: constexpr cartesian_product_view() = default; constexpr explicit cartesian_product_view(_First _First_base, _Rest... _Other_bases) noexcept( (is_nothrow_move_constructible_v<_First> && ... && is_nothrow_move_constructible_v<_Rest>) ) // strengthened : _Bases(_STD move(_First_base), _STD move(_Other_bases)...) {} _NODISCARD constexpr _Iterator begin() requires (!_Simple_view<_First> || ... || !_Simple_view<_Rest>) { return _Iterator{*this, _RANGES _Tuple_transform(_RANGES begin, _Bases)}; } _NODISCARD constexpr _Iterator begin() const requires (range && ... && range) { return _Iterator{*this, _RANGES _Tuple_transform(_RANGES begin, _Bases)}; } _NODISCARD constexpr _Iterator end() requires ((!_Simple_view<_First> || ... || !_Simple_view<_Rest>) && _Cartesian_product_is_common<_First>) { const bool _Is_empty = [&](index_sequence<_Indices...>) { return (_RANGES empty(_STD get<_Indices + 1>(_Bases)) || ...); } (make_index_sequence{}); const auto _Make_iter_tuple = [&](index_sequence<_Indices...>) { return tuple, iterator_t<_Rest>...>{_Begin_or_first_end<_Indices>(_Is_empty)...}; }; return _Iterator{*this, _Make_iter_tuple(make_index_sequence<1 + sizeof...(_Rest)>{})}; } _NODISCARD constexpr _Iterator end() const requires _Cartesian_product_is_common { const bool _Is_empty = [&](index_sequence<_Indices...>) { return (_RANGES empty(_STD get<_Indices + 1>(_Bases)) || ...); } (make_index_sequence{}); const auto _Make_iter_tuple = [&](index_sequence<_Indices...>) { return tuple, iterator_t...>{ _Begin_or_first_end<_Indices>(_Is_empty)...}; }; return _Iterator{*this, _Make_iter_tuple(make_index_sequence<1 + sizeof...(_Rest)>{})}; } _NODISCARD constexpr default_sentinel_t end() const noexcept { return default_sentinel; } _NODISCARD constexpr auto size() requires _Cartesian_product_is_sized<_First, _Rest...> { return [&](index_sequence<_Indices...>) { #if _CONTAINER_DEBUG_LEVEL > 0 _Size_type _Product{1}; const bool _Overflow = (_Multiply_with_overflow_check( _Product, static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases))), _Product) || ...); _STL_VERIFY(!_Overflow, "Size of cartesian product cannot be represented by size type (N4928 " "[range.cartesian.view]/10)."); return _Product; #else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL == 0 vvv return (static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases))) * ...); #endif // ^^^ _CONTAINER_DEBUG_LEVEL == 0 ^^^ } (make_index_sequence<1 + sizeof...(_Rest)>{}); } _NODISCARD constexpr auto size() const requires _Cartesian_product_is_sized { return [&](index_sequence<_Indices...>) { #if _CONTAINER_DEBUG_LEVEL > 0 _Size_type _Product{1}; const bool _Overflow = (_Multiply_with_overflow_check( _Product, static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases))), _Product) || ...); _STL_VERIFY(!_Overflow, "Size of cartesian product cannot be represented by size type (N4928 " "[range.cartesian.view]/10)."); return _Product; #else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL == 0 vvv return (static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases))) * ...); #endif // ^^^ _CONTAINER_DEBUG_LEVEL == 0 ^^^ } (make_index_sequence<1 + sizeof...(_Rest)>{}); } }; template cartesian_product_view(_Rngs&&...) -> cartesian_product_view...>; namespace views { class _Cartesian_product_fn { public: _NODISCARD constexpr auto operator()() const noexcept { return views::single(tuple{}); } template _NODISCARD constexpr auto operator()(_Rngs&&... _Ranges) const noexcept(noexcept(cartesian_product_view...>{_STD forward<_Rngs>(_Ranges)...})) requires requires { cartesian_product_view...>{_STD forward<_Rngs>(_Ranges)...}; } { return cartesian_product_view...>{_STD forward<_Rngs>(_Ranges)...}; } }; _EXPORT_STD inline constexpr _Cartesian_product_fn cartesian_product; } // namespace views #ifdef __cpp_lib_ranges_to_container // clang-format off template concept _Sized_and_reservable = sized_range<_Range> && sized_range<_Container> && requires(_Container& _Cont, const range_size_t<_Container> _Count) { _Cont.reserve(_Count); { _Cont.capacity() } -> same_as>; { _Cont.max_size() } -> same_as>; }; // clang-format on template concept _Ref_converts = (!input_range<_Container>) || convertible_to, range_value_t<_Container>>; template concept _Converts_direct_constructible = _Ref_converts<_Rng, _Container> // && constructible_from<_Container, _Rng, _Types...>; template concept _Converts_tag_constructible = _Ref_converts<_Rng, _Container> // per LWG issue unnumbered as of 2022-08-08 && constructible_from<_Container, const from_range_t&, _Rng, _Types...>; template concept _Converts_and_common_constructible = _Ref_converts<_Rng, _Container> && common_range<_Rng> // && requires { typename iterator_traits>::iterator_category; } && derived_from>::iterator_category, input_iterator_tag> && constructible_from<_Container, iterator_t<_Rng>, iterator_t<_Rng>, _Types...>; template concept _Can_push_back = requires(_Container& _Cont) { _Cont.push_back(_STD declval<_Reference>()); }; template concept _Can_insert_end = requires(_Container& _Cont) { _Cont.insert(_Cont.end(), _STD declval<_Reference>()); }; // clang-format off template concept _Converts_constructible_insertable = _Ref_converts<_Rng, _Container> && constructible_from<_Container, _Types...> && (_Can_push_back<_Container, range_reference_t<_Rng>> || _Can_insert_end<_Container, range_reference_t<_Rng>>); // clang-format on template _NODISCARD constexpr auto _Container_inserter(_Container& _Cont) { if constexpr (_Can_push_back<_Container, _Reference>) { return back_insert_iterator{_Cont}; } else { return insert_iterator{_Cont, _Cont.end()}; } } _EXPORT_STD template requires (!view<_Container>) _NODISCARD constexpr _Container to(_Rng&& _Range, _Types&&... _Args) { static_assert(!is_const_v<_Container>, "C must not be const. ([range.utility.conv.to])"); static_assert(!is_volatile_v<_Container>, "C must not be volatile. ([range.utility.conv.to])"); static_assert(is_class_v<_Container>, "C must be a class type. ([range.utility.conv.to])"); if constexpr (_Converts_direct_constructible<_Rng, _Container, _Types...>) { return _Container(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...); } else if constexpr (_Converts_tag_constructible<_Rng, _Container, _Types...>) { return _Container(from_range, _STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...); } else if constexpr (_Converts_and_common_constructible<_Rng, _Container, _Types...>) { return _Container(_RANGES begin(_Range), _RANGES end(_Range), _STD forward<_Types...>(_Args)...); } else if constexpr (_Converts_constructible_insertable<_Rng, _Container, _Types...>) { _Container _Cont(_STD forward<_Types>(_Args)...); if constexpr (_Sized_and_reservable<_Rng, _Container>) { _Cont.reserve(static_cast>(_RANGES size(_Range))); } _RANGES copy(_Range, _Container_inserter>(_Cont)); return _Cont; } else if constexpr (input_range>) { const auto _Xform = [](auto&& _Elem) { return _RANGES to>(_STD forward(_Elem)); }; return _RANGES to<_Container>(views::transform(_Range, _Xform), _STD forward<_Types>(_Args)...); } else { static_assert(_Always_false<_Container>, "the program is ill-formed per N4910 [range.utility.conv.to]/1.3"); } } template struct _To_class_fn { _STL_INTERNAL_STATIC_ASSERT(!is_const_v<_Container>); _STL_INTERNAL_STATIC_ASSERT(!is_volatile_v<_Container>); _STL_INTERNAL_STATIC_ASSERT(is_class_v<_Container>); _STL_INTERNAL_STATIC_ASSERT(!view<_Container>); template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Types&&... _Args) const requires requires { _RANGES to<_Container>(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...); } { return _RANGES to<_Container>(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...); } }; _EXPORT_STD template requires (!view<_Container>) _NODISCARD constexpr auto to(_Types&&... _Args) { static_assert(!is_const_v<_Container>, "C must not be const. ([range.utility.conv.adaptors])"); static_assert(!is_volatile_v<_Container>, "C must not be volatile. ([range.utility.conv.adaptors])"); static_assert(is_class_v<_Container>, "C must be a class type. ([range.utility.conv.adaptors])"); return _Range_closure<_To_class_fn<_Container>, decay_t<_Types>...>{_STD forward<_Types>(_Args)...}; } template struct _Phony_input_iterator { using iterator_category = input_iterator_tag; using value_type = range_value_t<_Rng>; using difference_type = ptrdiff_t; using pointer = add_pointer_t>; using reference = range_reference_t<_Rng>; reference operator*() const; pointer operator->() const; _Phony_input_iterator& operator++(); _Phony_input_iterator operator++(int); bool operator==(const _Phony_input_iterator&) const; }; template