From 767401edabdb35162c8f90c268eec4e231ff7b26 Mon Sep 17 00:00:00 2001 From: cpplearner Date: Fri, 19 Apr 2024 20:35:08 +0800 Subject: [PATCH 1/2] Extract `_Ref_converts` tests --- stl/inc/ranges | 78 +++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index d639701ec7..cffe1b1443 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,42 @@ 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, "the program is ill-formed per 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, "the program is ill-formed per N4981 [range.utility.conv.to]/2.3"); } } From baba83250956c61349d03dfbc00f82c86e66e3d8 Mon Sep 17 00:00:00 2001 From: cpplearner Date: Sat, 20 Apr 2024 07:01:20 +0800 Subject: [PATCH 2/2] Add details to the error messages --- stl/inc/ranges | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index cffe1b1443..0c6e7db1c5 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -10355,7 +10355,9 @@ namespace ranges { } return _Cont; } else { - static_assert(false, "the program is ill-formed per N4981 [range.utility.conv.to]/2.1.5"); + 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 { @@ -10363,7 +10365,10 @@ namespace ranges { }; return _RANGES to<_Container>(views::transform(ref_view{_Range}, _Xform), _STD forward<_Types>(_Args)...); } else { - static_assert(false, "the program is ill-formed per N4981 [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)"); } }