STL/stl/inc/__msvc_ranges_to.hpp

1239 строки
54 KiB
C++
Исходник Постоянная ссылка Обычный вид История

// __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 <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#if !_HAS_CXX20
#error The contents of <ranges> are only available with C++20. (Also, you should not include this internal header.)
#endif // !_HAS_CXX20
#include <tuple>
#include <xutility>
#if _HAS_CXX23
#include <xmemory>
#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 <class _Ty>
constexpr bool _Is_initializer_list = _Is_specialization_v<remove_cvref_t<_Ty>, initializer_list>;
_EXPORT_STD template <class _Rng>
concept viewable_range = range<_Rng>
&& ((view<remove_cvref_t<_Rng>> && constructible_from<remove_cvref_t<_Rng>, _Rng>)
|| (!view<remove_cvref_t<_Rng>>
&& (is_lvalue_reference_v<_Rng>
|| (movable<remove_reference_t<_Rng>> && !_Is_initializer_list<_Rng>) )));
namespace _Pipe {
template <class _Derived>
struct _Base {};
template <class _Ty>
_Ty* _Derived_from_range_adaptor_closure(_Base<_Ty>&); // not defined
template <class _Ty>
concept _Range_adaptor_closure_object = !range<remove_cvref_t<_Ty>> && requires(remove_cvref_t<_Ty>& __t) {
{ _Pipe::_Derived_from_range_adaptor_closure(__t) } -> same_as<remove_cvref_t<_Ty>*>;
};
template <class _ClosureLeft, class _ClosureRight>
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 <class _Ty1, class _Ty2>
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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty1, class _Ty2>
_Pipeline(_Ty1, _Ty2) -> _Pipeline<_Ty1, _Ty2>;
_EXPORT_STD template <class _Left, class _Right>
requires _Range_adaptor_closure_object<_Left> && _Range_adaptor_closure_object<_Right>
&& constructible_from<remove_cvref_t<_Left>, _Left>
&& constructible_from<remove_cvref_t<_Right>, _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 <class _Left, class _Right>
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 <class _Ty>
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 <class... _Types>
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();
}
}
~_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;
constexpr _Movable_box(const _Movable_box& _That)
requires copy_constructible<_Ty>
: _Engaged{_That._Engaged} {
if (_That._Engaged) {
_STD _Construct_in_place(_Val, static_cast<const _Ty&>(_That._Val));
}
}
_Movable_box(_Movable_box&&)
requires is_trivially_move_constructible_v<_Ty>
= default;
constexpr _Movable_box(_Movable_box&& _That) : _Engaged{_That._Engaged} {
if (_That._Engaged) {
_STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val));
}
}
_Movable_box& operator=(const _Movable_box&) noexcept
requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty>
= default;
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<const _Ty&>(_That._Val);
} else {
_Val.~_Ty();
_Engaged = false;
}
} else {
if (_That._Engaged) {
_STD _Construct_in_place(_Val, static_cast<const _Ty&>(_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<const _Ty&>(_That._Val));
_Engaged = true;
}
return *this;
}
_Movable_box& operator=(_Movable_box&&) noexcept
requires movable<_Ty> && is_trivially_move_assignable_v<_Ty>
= default;
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 <class _Ty>
concept _Use_simple_movable_box_wrapper =
(copy_constructible<_Ty>
// 1. If copy_constructible<T> is true, movable-box<T> should store only a T if either T models
// copyable, or is_nothrow_move_constructible_v<T> && is_nothrow_copy_constructible_v<T> is true.
? copyable<_Ty> || (is_nothrow_move_constructible_v<_Ty> && is_nothrow_copy_constructible_v<_Ty>)
// 2. Otherwise, movable-box<T> should store only a T if either T models movable or
// is_nothrow_move_constructible_v<T> is true.
: movable<_Ty> || is_nothrow_move_constructible_v<_Ty>);
template <class _Ty>
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:
_Movable_box()
requires default_initializable<_Ty>
= default;
template <class... _Types>
constexpr _Movable_box(in_place_t, _Types&&... _Args)
noexcept(is_nothrow_constructible_v<_Ty, _Types...>) // strengthened
: _Val(_STD forward<_Types>(_Args)...) {}
_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;
constexpr _Movable_box(const _Movable_box& _That) noexcept(is_nothrow_copy_constructible_v<_Ty>)
requires _Copy_constructible_for_box<_Ty>
: _Val(static_cast<const _Ty&>(_That._Val)) {}
constexpr _Movable_box(_Movable_box&& _That) noexcept(is_nothrow_move_constructible_v<_Ty>)
: _Val(static_cast<_Ty&&>(_That._Val)) {}
_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;
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<const _Ty&>(_That._Val);
} else {
if (_STD addressof(_That) != this) {
_Val.~_Ty();
_STD _Construct_in_place(_Val, static_cast<const _Ty&>(_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 _Fn, class... _Types>
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<decay_t<_Types>, _Types> && ...));
_STL_INTERNAL_STATIC_ASSERT(is_empty_v<_Fn>&& is_default_constructible_v<_Fn>);
template <class... _UTypes>
requires (same_as<decay_t<_UTypes>, _Types> && ...)
constexpr explicit _Range_closure(_UTypes&&... _Args)
noexcept(conjunction_v<is_nothrow_constructible<_Types, _UTypes>...>)
: _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 <class _Ty>
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 <class _Ty>
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 <class _Ty>
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 <class _Ty>
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 <class _SelfTy, class _Ty, size_t... _Idx>
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<index_sequence<_Idx...>, _Indices>);
return _Fn{}(_STD forward<_Ty>(_Arg), _STD get<_Idx>(_STD forward<_SelfTy>(_Self)._Captures)...);
}
tuple<_Types...> _Captures;
};
_EXPORT_STD template <range _Rng>
requires is_object_v<_Rng>
class ref_view : public view_interface<ref_view<_Rng>> {
private:
_Rng* _Range;
static void _Rvalue_poison(_Rng&);
static void _Rvalue_poison(_Rng&&) = delete;
public:
template <_Different_from<ref_view> _OtherRng>
constexpr ref_view(_OtherRng&& _Other)
noexcept(noexcept(static_cast<_Rng&>(_STD forward<_OtherRng>(_Other)))) // strengthened
requires convertible_to<_OtherRng, _Rng&> && requires { _Rvalue_poison(static_cast<_OtherRng&&>(_Other)); }
: _Range{_STD addressof(static_cast<_Rng&>(_STD forward<_OtherRng>(_Other)))} {}
_NODISCARD constexpr _Rng& base() const noexcept /* strengthened */ {
return *_Range;
}
_NODISCARD constexpr iterator_t<_Rng> begin() const
noexcept(noexcept(_RANGES begin(*_Range))) /* strengthened */ {
return _RANGES begin(*_Range);
}
_NODISCARD constexpr sentinel_t<_Rng> end() const noexcept(noexcept(_RANGES end(*_Range))) /* strengthened */ {
return _RANGES end(*_Range);
}
_NODISCARD constexpr bool empty() const noexcept(noexcept(_RANGES empty(*_Range))) /* strengthened */
requires _Can_empty<_Rng>
{
return _RANGES empty(*_Range);
}
_NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(*_Range))) /* strengthened */
requires sized_range<_Rng>
{
return _RANGES size(*_Range);
}
_NODISCARD constexpr auto data() const noexcept(noexcept(_RANGES data(*_Range))) /* strengthened */
requires contiguous_range<_Rng>
{
return _RANGES data(*_Range);
}
};
template <class _Rng>
ref_view(_Rng&) -> ref_view<_Rng>;
template <class _Rng>
constexpr bool enable_borrowed_range<ref_view<_Rng>> = true;
_EXPORT_STD template <range _Rng>
requires (movable<_Rng> && !_Is_initializer_list<_Rng>)
class owning_view : public view_interface<owning_view<_Rng>> {
private:
_Rng _Range{};
public:
owning_view()
requires default_initializable<_Rng>
= default;
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<const _Rng>
{
return _RANGES begin(_Range);
}
_NODISCARD constexpr auto end() const noexcept(noexcept(_RANGES end(_Range))) /* strengthened */
requires range<const _Rng>
{
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<const _Rng>
{
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<const _Rng>
{
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<const _Rng>
{
return _RANGES data(_Range);
}
};
template <class _Rng>
constexpr bool enable_borrowed_range<owning_view<_Rng>> = enable_borrowed_range<_Rng>;
namespace views {
template <class _Rng>
concept _Can_ref_view = requires(_Rng&& __r) { ref_view{static_cast<_Rng&&>(__r)}; };
template <class _Rng>
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 <class _Rng>
_NODISCARD static consteval _Choice_t<_St> _Choose() noexcept {
if constexpr (view<remove_cvref_t<_Rng>>) {
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 <class _Rng>
static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>();
public:
template <viewable_range _Rng>
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 <viewable_range _Rng>
using all_t = decltype(all(_STD declval<_Rng>()));
} // namespace views
_EXPORT_STD template <input_range _Vw, _Valid_movable_box_object _Fn>
requires view<_Vw> && regular_invocable<_Fn&, range_reference_t<_Vw>>
&& _Can_reference<invoke_result_t<_Fn&, range_reference_t<_Vw>>>
class transform_view : public view_interface<transform_view<_Vw, _Fn>> {
private:
/* [[no_unique_address]] */ _Vw _Range{};
/* [[no_unique_address]] */ _Movable_box<_Fn> _Fun{};
template <bool _Const>
struct _Category_base {};
template <bool _Const>
requires forward_range<_Maybe_const<_Const, _Vw>>
struct _Category_base<_Const> {
using _Base = _Maybe_const<_Const, _Vw>;
using iterator_category =
conditional_t<is_reference_v<invoke_result_t<_Maybe_const<_Const, _Fn>&, range_reference_t<_Base>>>,
conditional_t<derived_from<_Iter_cat_t<iterator_t<_Base>>, contiguous_iterator_tag>,
random_access_iterator_tag, _Iter_cat_t<iterator_t<_Base>>>,
input_iterator_tag>;
};
template <bool _Const>
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_range<_Base>, random_access_iterator_tag,
conditional_t<bidirectional_range<_Base>, bidirectional_iterator_tag,
conditional_t<forward_range<_Base>, forward_iterator_tag, input_iterator_tag>>>;
using value_type = remove_cvref_t<invoke_result_t<_Maybe_const<_Const, _Fn>&, range_reference_t<_Base>>>;
using difference_type = range_difference_t<_Base>;
_Iterator()
requires default_initializable<iterator_t<_Base>>
= default;
constexpr _Iterator(_Parent_t& _Parent_, iterator_t<_Base> _Current_)
noexcept(is_nothrow_move_constructible_v<iterator_t<_Base>>) // strengthened
: _Current{_STD move(_Current_)}, _Parent{_STD addressof(_Parent_)} {
#if _ITERATOR_DEBUG_LEVEL != 0
_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<!_Const> _It)
noexcept(is_nothrow_constructible_v<iterator_t<_Base>, iterator_t<_Vw>>) // strengthened
requires _Const && convertible_to<iterator_t<_Vw>, iterator_t<_Base>>
: _Current(_STD move(_It._Current)), _Parent(_It._Parent) {}
_NODISCARD constexpr const iterator_t<_Base>& base() const& noexcept {
return _Current;
}
_NODISCARD constexpr iterator_t<_Base> base() && noexcept(
is_nothrow_move_constructible_v<iterator_t<_Base>>) /* strengthened */ {
return _STD move(_Current);
}
_NODISCARD constexpr decltype(auto) operator*() const
noexcept(noexcept(_STD 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<iterator_t<_Base>>) ) /* strengthened */ {
if constexpr (forward_range<_Base>) {
auto _Tmp = *this;
++*this;
return _Tmp;
} else {
++*this;
}
}
constexpr _Iterator& operator--() noexcept(noexcept(--_Current)) /* strengthened */
requires bidirectional_range<_Base>
{
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Parent != nullptr, "Cannot decrement value-initialized transform_view iterator");
if constexpr (forward_range<_Vw>) {
_STL_VERIFY(_Current != _RANGES begin(_Parent->_Range),
"Cannot decrement transform_view iterator before begin");
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
--_Current;
return *this;
}
constexpr _Iterator operator--(int)
noexcept(noexcept(--_Current) && is_nothrow_copy_constructible_v<iterator_t<_Base>>) /* strengthened */
requires bidirectional_range<_Base>
{
auto _Tmp = *this;
--*this;
return _Tmp;
}
#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<iterator_t<_Base>>) {
_Current._Verify_offset(_Off);
}
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
constexpr _Iterator& operator+=(const difference_type _Off)
noexcept(noexcept(_Current += _Off)) /* strengthened */
requires random_access_range<_Base>
{
#if _ITERATOR_DEBUG_LEVEL != 0
_Verify_offset(_Off);
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current += _Off;
return *this;
}
constexpr _Iterator& operator-=(const difference_type _Off)
noexcept(noexcept(_Current -= _Off)) /* strengthened */
requires random_access_range<_Base>
{
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Off != _Min_possible_v<difference_type>, "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<iterator_t<_Base>>
{
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current == _Right._Current;
}
_NODISCARD friend constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right)
noexcept(noexcept(_Left._Current < _Right._Current)) /* strengthened */
requires random_access_range<_Base>
{
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current < _Right._Current;
}
_NODISCARD friend constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right)
noexcept(noexcept(_Left._Current < _Right._Current)) /* strengthened */
requires random_access_range<_Base>
{
return _Right < _Left;
}
_NODISCARD friend constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right)
noexcept(noexcept(_Left._Current < _Right._Current)) /* strengthened */
requires random_access_range<_Base>
{
return !(_Right < _Left);
}
_NODISCARD friend constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right)
noexcept(noexcept(_Left._Current < _Right._Current)) /* strengthened */
requires random_access_range<_Base>
{
return !(_Left < _Right);
}
_NODISCARD friend constexpr auto operator<=>(const _Iterator& _Left, const _Iterator& _Right)
noexcept(noexcept(_Left._Current <=> _Right._Current)) /* strengthened */
requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
{
#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<difference_type>, "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>, iterator_t<_Base>>
{
#if _ITERATOR_DEBUG_LEVEL != 0
_Left._Same_range(_Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _Left._Current - _Right._Current;
}
};
template <bool _Const>
class _Sentinel {
private:
friend transform_view;
using _Parent_t = _Maybe_const<_Const, transform_view>;
using _Base = _Maybe_const<_Const, _Vw>;
template <bool _OtherConst>
using _Maybe_const_iter = iterator_t<_Maybe_const<_OtherConst, _Vw>>;
sentinel_t<_Base> _Last{};
template <bool _OtherConst>
_NODISCARD static constexpr const _Maybe_const_iter<_OtherConst>& _Get_current(
const _Iterator<_OtherConst>& _It) noexcept {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(
_It._Parent != nullptr, "cannot compare transform_view sentinel with value-initialized iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return _It._Current;
}
public:
_Sentinel() = default;
constexpr explicit _Sentinel(sentinel_t<_Base> _Last_)
noexcept(is_nothrow_move_constructible_v<sentinel_t<_Base>>) // strengthened
: _Last(_STD move(_Last_)) {}
constexpr _Sentinel(_Sentinel<!_Const> _Se)
noexcept(is_nothrow_constructible_v<sentinel_t<_Base>, sentinel_t<_Vw>>) // strengthened
requires _Const && convertible_to<sentinel_t<_Vw>, sentinel_t<_Base>>
: _Last(_STD move(_Se._Last)) {}
_NODISCARD constexpr sentinel_t<_Base> base() const
noexcept(is_nothrow_copy_constructible_v<sentinel_t<_Base>>) /* strengthened */ {
return _Last;
}
template <bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr bool operator==(const _Iterator<_OtherConst>& _Left, const _Sentinel& _Right)
noexcept(noexcept(_Get_current(_Left) == _Right._Last)) /* strengthened */ {
return _Get_current(_Left) == _Right._Last;
}
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-(
const _Iterator<_OtherConst>& _Left, const _Sentinel& _Right)
noexcept(noexcept(_Get_current(_Left) - _Right._Last)) /* strengthened */ {
return _Get_current(_Left) - _Right._Last;
}
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, _Maybe_const_iter<_OtherConst>>
_NODISCARD friend constexpr range_difference_t<_Maybe_const<_OtherConst, _Vw>> operator-(
const _Sentinel& _Left, const _Iterator<_OtherConst>& _Right)
noexcept(noexcept(_Left._Last - _Get_current(_Right))) /* strengthened */ {
return _Left._Last - _Get_current(_Right);
}
};
public:
transform_view()
requires default_initializable<_Vw> && default_initializable<_Fn>
= default;
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<false> begin() noexcept(
noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */ {
return _Iterator<false>{*this, _RANGES begin(_Range)};
}
_NODISCARD constexpr _Iterator<true> begin() const noexcept(
noexcept(_RANGES begin(_Range)) && is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */
requires range<const _Vw> && regular_invocable<const _Fn&, range_reference_t<const _Vw>>
{
return _Iterator<true>{*this, _RANGES begin(_Range)};
}
_NODISCARD constexpr auto end()
noexcept(noexcept(_RANGES end(_Range))
&& is_nothrow_move_constructible_v<decltype(_RANGES end(_Range))>) /* strengthened */ {
if constexpr (common_range<_Vw>) {
return _Iterator<false>{*this, _RANGES end(_Range)};
} else {
return _Sentinel<false>{_RANGES end(_Range)};
}
}
_NODISCARD constexpr auto end() const
noexcept(noexcept(_RANGES end(_Range))
&& is_nothrow_move_constructible_v<decltype(_RANGES end(_Range))>) /* strengthened */
requires range<const _Vw> && regular_invocable<const _Fn&, range_reference_t<const _Vw>>
{
if constexpr (common_range<_Vw>) {
return _Iterator<true>{*this, _RANGES end(_Range)};
} else {
return _Sentinel<true>{_RANGES end(_Range)};
}
}
_NODISCARD constexpr auto size() noexcept(noexcept(_RANGES size(_Range))) /* strengthened */
requires sized_range<_Vw>
{
return _RANGES size(_Range);
}
_NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(_Range))) /* strengthened */
requires sized_range<const _Vw>
{
return _RANGES size(_Range);
}
};
template <class _Rng, class _Fn>
transform_view(_Rng&&, _Fn) -> transform_view<views::all_t<_Rng>, _Fn>;
namespace views {
struct _Transform_fn {
template <viewable_range _Rng, class _Fn>
_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 <class _Fn>
requires constructible_from<decay_t<_Fn>, _Fn>
_NODISCARD _STATIC_CALL_OPERATOR constexpr auto operator()(_Fn&& _Fun) _CONST_CALL_OPERATOR
noexcept(is_nothrow_constructible_v<decay_t<_Fn>, _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 <class _Range, class _Container>
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<range_size_t<_Container>>;
{ _Cont.max_size() } -> same_as<range_size_t<_Container>>;
};
template <class _Rng, class _Container>
concept _Ref_converts =
!input_range<_Container> || convertible_to<range_reference_t<_Rng>, range_value_t<_Container>>;
template <class _Rng, class _Container, class... _Types>
concept _Common_constructible =
common_range<_Rng> //
&& requires { typename iterator_traits<iterator_t<_Rng>>::iterator_category; }
&& derived_from<typename iterator_traits<iterator_t<_Rng>>::iterator_category, input_iterator_tag>
&& constructible_from<_Container, iterator_t<_Rng>, iterator_t<_Rng>, _Types...>;
template <class _Container, class _Reference>
concept _Can_emplace_back = requires(_Container& _Cont) { _Cont.emplace_back(_STD declval<_Reference>()); };
template <class _Container, class _Reference>
concept _Can_push_back = requires(_Container& _Cont) { _Cont.push_back(_STD declval<_Reference>()); };
template <class _Container, class _Reference>
concept _Can_emplace_end = requires(_Container& _Cont) { _Cont.emplace(_Cont.end(), _STD declval<_Reference>()); };
template <class _Container, class _Reference>
concept _Can_insert_end = requires(_Container& _Cont) { _Cont.insert(_Cont.end(), _STD declval<_Reference>()); };
template <class _Rng, class _Container, class... _Types>
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 <class _Container, input_range _Rng, class... _Types>
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<range_size_t<_Container>>(_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<range_reference_t<_Rng>>) {
const auto _Xform = [](auto&& _Elem) _STATIC_CALL_OPERATOR {
return _RANGES to<range_value_t<_Container>>(_STD forward<decltype(_Elem)>(_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 <class _Container>
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 <input_range _Rng, class... _Types>
_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 <class _Container, class... _Types>
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 <input_range _Rng>
struct _Phony_input_iterator {
using value_type = range_value_t<_Rng>;
using difference_type = ptrdiff_t;
// These member functions are never defined:
range_reference_t<_Rng> operator*() const;
add_pointer_t<range_reference_t<_Rng>> operator->() const;
_Phony_input_iterator& operator++();
_Phony_input_iterator operator++(int);
bool operator==(const _Phony_input_iterator&) const;
};
template <template <class...> class _Cnt, class _Rng, class... _Args>
auto _To_helper() {
if constexpr (requires { _Cnt(_STD declval<_Rng>(), _STD declval<_Args>()...); }) {
return static_cast<decltype(_Cnt(_STD declval<_Rng>(), _STD declval<_Args>()...))*>(nullptr);
} else if constexpr (requires { _Cnt(from_range, _STD declval<_Rng>(), _STD declval<_Args>()...); }) {
return static_cast<decltype(_Cnt(from_range, _STD declval<_Rng>(), _STD declval<_Args>()...))*>(nullptr);
} else if constexpr (requires {
_Cnt(_STD declval<_Phony_input_iterator<_Rng>>(),
_STD declval<_Phony_input_iterator<_Rng>>(), _STD declval<_Args>()...);
}) {
return static_cast<decltype(_Cnt(_STD declval<_Phony_input_iterator<_Rng>>(),
_STD declval<_Phony_input_iterator<_Rng>>(), _STD declval<_Args>()...))*>(nullptr);
}
}
_EXPORT_STD template <template <class...> class _Container, input_range _Rng, class... _Types,
class _Deduced = remove_pointer_t<decltype(_To_helper<_Container, _Rng, _Types...>())>>
_NODISCARD constexpr _Deduced to(_Rng&& _Range, _Types&&... _Args) {
return _RANGES to<_Deduced>(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...);
}
template <template <class...> class _Container>
struct _To_template_fn {
template <input_range _Rng, class... _Types,
class _Deduced = remove_pointer_t<decltype(_To_helper<_Container, _Rng, _Types...>())>>
_NODISCARD _STATIC_CALL_OPERATOR constexpr auto operator()(
_Rng&& _Range, _Types&&... _Args) _CONST_CALL_OPERATOR {
return _RANGES to<_Deduced>(_STD forward<_Rng>(_Range), _STD forward<_Types>(_Args)...);
}
};
_EXPORT_STD template <template <class...> class _Container, class... _Types>
_NODISCARD constexpr auto to(_Types&&... _Args) {
return _Range_closure<_To_template_fn<_Container>, decay_t<_Types>...>{_STD forward<_Types>(_Args)...};
}
#endif // _HAS_CXX23
} // namespace ranges
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // __MSVC_RANGES_TO_HPP