From cbaea378c5e08a90cb38cbb0f313298a192c315e Mon Sep 17 00:00:00 2001 From: "S. B. Tam" Date: Sat, 27 Apr 2024 06:43:45 +0800 Subject: [PATCH] ``: Refactor `ranges::to` (#4608) --- stl/inc/ranges | 83 +++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index d639701ec7..0c6e7db1c5 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -10297,17 +10297,8 @@ namespace ranges { !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> // + 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...>; @@ -10325,12 +10316,11 @@ namespace ranges { concept _Can_insert_end = requires(_Container& _Cont) { _Cont.insert(_Cont.end(), _STD declval<_Reference>()); }; template - concept _Converts_constructible_appendable = - _Ref_converts<_Rng, _Container> && 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>>); + 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>) @@ -10338,38 +10328,47 @@ namespace ranges { 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_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)); + 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)"); } - return _Cont; - } else if constexpr (!_Ref_converts<_Rng, _Container> && input_range>) { + } 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, "the program is ill-formed per N4950 [range.utility.conv.to]/2.3"); + 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)"); } }