diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index 60bfcbd83..376f4ef9c 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -13,10 +13,12 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_filebuf.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_format_ucd_tables.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_formatter.hpp + ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_heap_algorithms.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_int128.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_iter_core.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_minmax.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_print.hpp + ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_ranges_to.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_sanitizer_annotate_container.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_string_view.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_system_error_abi.hpp diff --git a/stl/inc/__msvc_heap_algorithms.hpp b/stl/inc/__msvc_heap_algorithms.hpp new file mode 100644 index 000000000..3a06b5934 --- /dev/null +++ b/stl/inc/__msvc_heap_algorithms.hpp @@ -0,0 +1,150 @@ +// __msvc_heap_algorithms.hpp internal header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef __MSVC_HEAP_ALGORITHMS_HPP +#define __MSVC_HEAP_ALGORITHMS_HPP +#include +#if _STL_COMPILER_PREPROCESSOR + +#include + +#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 +template +_CONSTEXPR20 void _Push_heap_by_index( + _RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Top, _Ty&& _Val, _Pr _Pred) { + // percolate _Hole to _Top or where _Val belongs + using _Diff = _Iter_diff_t<_RanIt>; + for (_Diff _Idx = (_Hole - 1) >> 1; // shift for codegen + _Top < _Hole && _DEBUG_LT_PRED(_Pred, *(_First + _Idx), _Val); _Idx = (_Hole - 1) >> 1) { // shift for codegen + // move _Hole up to parent + *(_First + _Hole) = _STD move(*(_First + _Idx)); + _Hole = _Idx; + } + + *(_First + _Hole) = _STD forward<_Ty>(_Val); // drop _Val into final hole +} + +_EXPORT_STD template +_CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // push *(_Last - 1) onto heap at [_First, _Last - 1) + _STD _Adl_verify_range(_First, _Last); + const auto _UFirst = _STD _Get_unwrapped(_First); + auto _ULast = _STD _Get_unwrapped(_Last); + using _Diff = _Iter_diff_t<_RanIt>; + _Diff _Count = _ULast - _UFirst; + if (2 <= _Count) { + _Iter_value_t<_RanIt> _Val(_STD move(*--_ULast)); + _STD _Push_heap_by_index(_UFirst, --_Count, _Diff(0), _STD move(_Val), _STD _Pass_fn(_Pred)); + } +} + +_EXPORT_STD template +_CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last) { + // push *(_Last - 1) onto heap at [_First, _Last - 1) + _STD push_heap(_First, _Last, less<>{}); +} + +template +_CONSTEXPR20 void _Pop_heap_hole_by_index( + _RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Bottom, _Ty&& _Val, _Pr _Pred) { + // percolate _Hole to _Bottom, then push _Val + _STL_INTERNAL_CHECK(_Bottom > 0); + + using _Diff = _Iter_diff_t<_RanIt>; + const _Diff _Top = _Hole; + _Diff _Idx = _Hole; + + // Check whether _Idx can have a child before calculating that child's index, since + // calculating the child's index can trigger integer overflows + const _Diff _Max_sequence_non_leaf = (_Bottom - 1) >> 1; // shift for codegen + while (_Idx < _Max_sequence_non_leaf) { // move _Hole down to larger child + _Idx = 2 * _Idx + 2; + if (_DEBUG_LT_PRED(_Pred, *(_First + _Idx), *(_First + (_Idx - 1)))) { + --_Idx; + } + *(_First + _Hole) = _STD move(*(_First + _Idx)); + _Hole = _Idx; + } + + if (_Idx == _Max_sequence_non_leaf && _Bottom % 2 == 0) { // only child at bottom, move _Hole down to it + *(_First + _Hole) = _STD move(*(_First + (_Bottom - 1))); + _Hole = _Bottom - 1; + } + + _STD _Push_heap_by_index(_First, _Hole, _Top, _STD forward<_Ty>(_Val), _Pred); +} + +template +_CONSTEXPR20 void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _Dest, _Ty&& _Val, _Pr _Pred) { + // pop *_First to *_Dest and reheap + // precondition: _First != _Last + // precondition: _First != _Dest + *_Dest = _STD move(*_First); + using _Diff = _Iter_diff_t<_RanIt>; + _STD _Pop_heap_hole_by_index( + _First, static_cast<_Diff>(0), static_cast<_Diff>(_Last - _First), _STD forward<_Ty>(_Val), _Pred); +} + +template +_CONSTEXPR20 void _Pop_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // pop *_First to *(_Last - 1) and reheap + if (2 <= _Last - _First) { + --_Last; + _Iter_value_t<_RanIt> _Val(_STD move(*_Last)); + _STD _Pop_heap_hole_unchecked(_First, _Last, _Last, _STD move(_Val), _Pred); + } +} + +_EXPORT_STD template +_CONSTEXPR20 void pop_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // pop *_First to *(_Last - 1) and reheap + _STD _Adl_verify_range(_First, _Last); + _STD _Pop_heap_unchecked(_STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last), _STD _Pass_fn(_Pred)); +} + +_EXPORT_STD template +_CONSTEXPR20 void pop_heap(_RanIt _First, _RanIt _Last) { + // pop *_First to *(_Last - 1) and reheap + _STD pop_heap(_First, _Last, less<>{}); +} + +template +_CONSTEXPR20 void _Make_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // make [_First, _Last) into a heap + using _Diff = _Iter_diff_t<_RanIt>; + _Diff _Bottom = _Last - _First; + for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen + // reheap top half, bottom to top + --_Hole; + _Iter_value_t<_RanIt> _Val(_STD move(*(_First + _Hole))); + _STD _Pop_heap_hole_by_index(_First, _Hole, _Bottom, _STD move(_Val), _Pred); + } +} + +_EXPORT_STD template +_CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // make [_First, _Last) into a heap + _STD _Adl_verify_range(_First, _Last); + _STD _Make_heap_unchecked(_STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last), _STD _Pass_fn(_Pred)); +} + +_EXPORT_STD template +_CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last) { // make [_First, _Last) into a heap + _STD make_heap(_First, _Last, less<>{}); +} +_STD_END + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // _STL_COMPILER_PREPROCESSOR +#endif // __MSVC_HEAP_ALGORITHMS_HPP diff --git a/stl/inc/__msvc_ranges_to.hpp b/stl/inc/__msvc_ranges_to.hpp new file mode 100644 index 000000000..bd4cfaea5 --- /dev/null +++ b/stl/inc/__msvc_ranges_to.hpp @@ -0,0 +1,1246 @@ +// __msvc_ranges_to.hpp internal header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// This header provides ranges::to (C++23) and supporting machinery (C++20). + +#ifndef __MSVC_RANGES_TO_HPP +#define __MSVC_RANGES_TO_HPP +#include +#if _STL_COMPILER_PREPROCESSOR + +#if !_HAS_CXX20 +#error The contents of are only available with C++20. (Also, you should not include this internal header.) +#endif // !_HAS_CXX20 + +#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 { + template + constexpr bool _Is_initializer_list = _Is_specialization_v, initializer_list>; + + // 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>)))); + // clang-format on + + namespace _Pipe { + template + struct _Base {}; + + template + _Ty* _Derived_from_range_adaptor_closure(_Base<_Ty>&); // not defined + + template + concept _Range_adaptor_closure_object = !range> && requires(remove_cvref_t<_Ty>& __t) { + { _Pipe::_Derived_from_range_adaptor_closure(__t) } -> same_as*>; + }; + + 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)) {} + + void operator()(auto&&) & = delete; + void operator()(auto&&) const& = delete; + void operator()(auto&&) && = delete; + void operator()(auto&&) const&& = delete; + + template + _NODISCARD constexpr decltype(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 decltype(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 decltype(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 decltype(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 decltype(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 + concept _Valid_movable_box_object = +#if _HAS_CXX23 + move_constructible<_Ty> +#else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv + copy_constructible<_Ty> +#endif // ^^^ !_HAS_CXX23 ^^^ + && _Destructible_object<_Ty>; + + // 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 _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<_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 + 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 + 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 _STATIC_CALL_OPERATOR constexpr auto operator()(_Rng&& _Range) _CONST_CALL_OPERATOR + 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 { + _STL_INTERNAL_STATIC_ASSERT(false); // unexpected strategy + } + } + }; + + _EXPORT_STD inline constexpr _All_fn all; + + _EXPORT_STD template + using all_t = decltype(all(_STD declval<_Rng>())); + } // namespace views + + _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 + _STD _Adl_verify_range(_Current, _RANGES end(_Parent_._Range)); + if constexpr (forward_range<_Base>) { + _STD _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); + } + _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> + { +#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_)) {} + + 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)) {} + + _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; + } + + 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; + } + + 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 */ + requires range && regular_invocable> + { + return _Iterator{*this, _RANGES begin(_Range)}; + } + + _NODISCARD constexpr auto end() noexcept( + noexcept(_RANGES end(_Range)) + && is_nothrow_move_constructible_v) /* strengthened */ { + if constexpr (common_range<_Vw>) { + return _Iterator{*this, _RANGES end(_Range)}; + } else { + return _Sentinel{_RANGES end(_Range)}; + } + } + + _NODISCARD constexpr auto end() const + noexcept(noexcept(_RANGES end(_Range)) + && is_nothrow_move_constructible_v) /* strengthened */ + requires range && regular_invocable> + { + 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 { + template + _NODISCARD _STATIC_CALL_OPERATOR constexpr auto operator()(_Rng&& _Range, _Fn _Fun) _CONST_CALL_OPERATOR + noexcept(noexcept(transform_view(_STD forward<_Rng>(_Range), _STD move(_Fun)))) + requires requires { transform_view(static_cast<_Rng&&>(_Range), _STD move(_Fun)); } + { + return transform_view(_STD forward<_Rng>(_Range), _STD move(_Fun)); + } + + template + requires constructible_from, _Fn> + _NODISCARD _STATIC_CALL_OPERATOR constexpr auto operator()(_Fn&& _Fun) _CONST_CALL_OPERATOR + 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 + +#if _HAS_CXX23 + 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>; + }; + + template + concept _Ref_converts = + !input_range<_Container> || convertible_to, range_value_t<_Container>>; + + template + concept _Common_constructible = + 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_emplace_back = requires(_Container& _Cont) { _Cont.emplace_back(_STD declval<_Reference>()); }; + + template + concept _Can_push_back = requires(_Container& _Cont) { _Cont.push_back(_STD declval<_Reference>()); }; + + template + concept _Can_emplace_end = requires(_Container& _Cont) { _Cont.emplace(_Cont.end(), _STD declval<_Reference>()); }; + + template + concept _Can_insert_end = requires(_Container& _Cont) { _Cont.insert(_Cont.end(), _STD declval<_Reference>()); }; + + template + concept _Constructible_appendable = constructible_from<_Container, _Types...> + && (_Can_emplace_back<_Container, range_reference_t<_Rng>> + || _Can_push_back<_Container, range_reference_t<_Rng>> + || _Can_emplace_end<_Container, range_reference_t<_Rng>> + || _Can_insert_end<_Container, range_reference_t<_Rng>>); + + _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 (_Ref_converts<_Rng, _Container>) { + if constexpr (constructible_from<_Container, _Rng, _Types...>) { + return _Container(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...); + } else if constexpr (constructible_from<_Container, const from_range_t&, _Rng, _Types...>) { // per LWG-3845 + return _Container(from_range, _STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...); + } else if constexpr (_Common_constructible<_Rng, _Container, _Types...>) { + return _Container(_RANGES begin(_Range), _RANGES end(_Range), _STD forward<_Types>(_Args)...); + } else if constexpr (_Constructible_appendable<_Rng, _Container, _Types...>) { + _Container _Cont(_STD forward<_Types>(_Args)...); + if constexpr (_Sized_and_reservable<_Rng, _Container>) { + _Cont.reserve(static_cast>(_RANGES size(_Range))); + } + for (auto&& _Elem : _Range) { + using _ElemTy = decltype(_Elem); + if constexpr (_Can_emplace_back<_Container, _ElemTy>) { + _Cont.emplace_back(_STD forward<_ElemTy>(_Elem)); + } else if constexpr (_Can_push_back<_Container, _ElemTy>) { + _Cont.push_back(_STD forward<_ElemTy>(_Elem)); + } else if constexpr (_Can_emplace_end<_Container, _ElemTy>) { + _Cont.emplace(_Cont.end(), _STD forward<_ElemTy>(_Elem)); + } else { + _STL_INTERNAL_STATIC_ASSERT(_Can_insert_end<_Container, _ElemTy>); + _Cont.insert(_Cont.end(), _STD forward<_ElemTy>(_Elem)); + } + } + return _Cont; + } else { + static_assert(false, "ranges::to requires the result to be constructible from the source range, either " + "by using a suitable constructor, or by inserting each element of the range into " + "the default-constructed object. (N4981 [range.utility.conv.to]/2.1.5)"); + } + } else if constexpr (input_range>) { + const auto _Xform = [](auto&& _Elem) _STATIC_CALL_OPERATOR { + return _RANGES to>(_STD forward(_Elem)); + }; + return _RANGES to<_Container>(views::transform(ref_view{_Range}, _Xform), _STD forward<_Types>(_Args)...); + } else { + static_assert(false, + "ranges::to requires the elements of the source range to be either implicitly convertible to the " + "elements of the destination container, or be ranges themselves for ranges::to to be applied " + "recursively. (N4981 [range.utility.conv.to]/2.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 _STATIC_CALL_OPERATOR constexpr auto operator()( + _Rng&& _Range, _Types&&... _Args) _CONST_CALL_OPERATOR + 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