@@ -103,123 +103,86 @@ inline constexpr bool enable_borrowed_range<as_const_view<_Tp>> = enable_borrowe
103103namespace views {
104104namespace __as_const {
105105
106- template <class _Case >
107- concept __case = requires { _Case::__impl; };
108-
109- template <class _Range >
110- struct __already_constant_case {};
111- template <class _Range >
112- requires constant_range<all_t <_Range>>
113- struct __already_constant_case <_Range> {
114- _LIBCPP_HIDE_FROM_ABI static constexpr auto __impl (_Range& __range) noexcept (
115- noexcept (views::all(std::forward<_Range>(__range)))) -> decltype(views::all(std::forward<_Range>(__range))) {
116- return views::all (std::forward<_Range>(__range));
117- }
118- };
119-
120- template <class _Range , class _UType = std::remove_cvref_t <_Range>>
121- struct __empty_view_case {};
122- template <class _Range , class _XType >
123- requires (!__case<__already_constant_case<_Range>>)
124- struct __empty_view_case<_Range, empty_view<_XType>> {
125- _LIBCPP_HIDE_FROM_ABI static constexpr auto
126- __impl (_Range&) noexcept (noexcept (auto (views::empty<const _XType>))) -> decltype (auto (views::empty<const _XType>)) {
127- return auto (views::empty<const _XType>);
128- }
129- };
106+ template <class _Tp >
107+ inline constexpr bool __is_span_v = false ; // true if and only if _Tp is a specialization of span
108+ template <class _Tp , size_t _Extent>
109+ inline constexpr bool __is_span_v<span<_Tp, _Extent>> = true ;
130110
131- template <class _Range , class _UType = std::remove_cvref_t <_Range>>
132- struct __span_case {};
133- template <class _Range , class _XType , size_t _Extent>
134- requires (!__case<__already_constant_case<_Range>>)
135- struct __span_case<_Range, span<_XType, _Extent>> {
136- _LIBCPP_HIDE_FROM_ABI static constexpr auto __impl (_Range& __range) noexcept (noexcept (span<const _XType, _Extent>(
137- std::forward<_Range>(__range)))) -> decltype (span<const _XType, _Extent>(std::forward<_Range>(__range))) {
138- return span<const _XType, _Extent>(std::forward<_Range>(__range));
139- }
111+ template <class _UType >
112+ struct __xtype {
113+ using type = void ;
140114};
141-
142- template <class _Range , class _UType = std::remove_cvref_t <_Range>>
143- struct __ref_view_case {};
144- template <class _Range , class _XType >
145- requires (!__case<__already_constant_case<_Range>>) && constant_range<const _XType>
146- struct __ref_view_case<_Range, ref_view<_XType>> {
147- _LIBCPP_HIDE_FROM_ABI static constexpr auto
148- __impl (_Range& __range) noexcept (noexcept (ref_view (static_cast <const _XType&>(std::forward<_Range>(__range).base ()))))
149- -> decltype (ref_view (static_cast <const _XType&>(std::forward<_Range>(__range).base ()))) {
150- return ref_view (static_cast <const _XType&>(std::forward<_Range>(__range).base ()));
151- }
115+ template <class _XType >
116+ struct __xtype <empty_view<_XType>> {
117+ using type = _XType;
152118};
153-
154- template <class _Range , class _UType = std::remove_cvref_t <_Range>>
155- struct __constant_range_case {};
156- template <class _Range , class _UType >
157- requires (!__case<__already_constant_case<_Range>>) && (!__case<__empty_view_case<_Range>>) &&
158- (!__case<__span_case<_Range>>) &&
159- (!__case<__ref_view_case<_Range>>) && is_lvalue_reference_v<_Range> && constant_range<const _UType> &&
160- (!view<_UType>)
161- struct __constant_range_case<_Range, _UType> {
162- _LIBCPP_HIDE_FROM_ABI static constexpr auto
163- __impl (_Range& __range) noexcept (noexcept (ref_view (static_cast <const _UType&>(std::forward<_Range>(__range)))))
164- -> decltype (ref_view (static_cast <const _UType&>(std::forward<_Range>(__range)))) {
165- return ref_view (static_cast <const _UType&>(std::forward<_Range>(__range)));
166- }
119+ template <class _XType , size_t _Extent>
120+ struct __xtype <span<_XType, _Extent>> {
121+ using type = _XType;
122+ constexpr static size_t __extent = _Extent;
167123};
168-
169- template <class _Range >
170- struct __otherwise_case {};
171- template <class _Range >
172- requires (!__case<__already_constant_case<_Range>>) && (!__case<__empty_view_case<_Range>>) &&
173- (!__case<__span_case<_Range>>) && (!__case<__ref_view_case<_Range>>) &&
174- (!__case<__constant_range_case<_Range>>)
175- struct __otherwise_case<_Range> {
176- _LIBCPP_HIDE_FROM_ABI static constexpr auto __impl (_Range& __range) noexcept (noexcept (
177- as_const_view (std::forward<_Range>(__range)))) -> decltype (as_const_view (std::forward<_Range>(__range))) {
178- return as_const_view (std::forward<_Range>(__range));
179- }
124+ template <class _XType >
125+ struct __xtype <ref_view<_XType>> {
126+ using type = _XType;
180127};
181128
182129struct __fn : __range_adaptor_closure<__fn> {
183- // [range.as.const.overview]: the basic `constant_range` case
184- template <class _Range >
185- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator ()(_Range&& __range) noexcept (noexcept (
186- __already_constant_case<_Range>::__impl(__range))) -> decltype(__already_constant_case<_Range>::__impl(__range)) {
187- return __already_constant_case<_Range>::__impl (__range);
188- }
189-
190- // [range.as.const.overview]: the `empty_view` case
191- template <class _Range >
192- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator ()(_Range&& __range) noexcept (
193- noexcept (__empty_view_case<_Range>::__impl(__range))) -> decltype(__empty_view_case<_Range>::__impl(__range)) {
194- return __empty_view_case<_Range>::__impl (__range);
195- }
196-
197- // [range.as.const.overview]: the `span` case
198- template <class _Range >
199- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator ()(_Range&& __range) noexcept (
200- noexcept (__span_case<_Range>::__impl(__range))) -> decltype(__span_case<_Range>::__impl(__range)) {
201- return __span_case<_Range>::__impl (__range);
202- }
203-
204- // [range.as.const.overview]: the `ref_view` case
205- template <class _Range >
206- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator ()(_Range&& __range) noexcept (
207- noexcept (__ref_view_case<_Range>::__impl(__range))) -> decltype(__ref_view_case<_Range>::__impl(__range)) {
208- return __ref_view_case<_Range>::__impl (__range);
209- }
210-
211- // [range.as.const.overview]: the second `constant_range` case
212- template <class _Range >
213- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator ()(_Range&& __range) noexcept (noexcept (
214- __constant_range_case<_Range>::__impl(__range))) -> decltype(__constant_range_case<_Range>::__impl(__range)) {
215- return __constant_range_case<_Range>::__impl (__range);
216- }
217-
218- // [range.as.const.overview]: otherwise
219- template <class _Range >
220- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator ()(_Range&& __range) noexcept (
221- noexcept (__otherwise_case<_Range>::__impl(__range))) -> decltype(__otherwise_case<_Range>::__impl(__range)) {
222- return __otherwise_case<_Range>::__impl (__range);
130+ // implementation strategy taken from Microsoft's STL
131+ enum class __strategy {
132+ __already_const,
133+ __empty_view,
134+ __span,
135+ __ref_view,
136+ __const_is_constant_range,
137+ __otherwise,
138+ __none,
139+ };
140+
141+ template <class _Type >
142+ static consteval pair<__strategy, bool > __choose_strategy () {
143+ using _UType = std::remove_cvref_t <_Type>;
144+ using _XType = __xtype<_UType>::type;
145+
146+ if constexpr (!requires { typename all_t <_Type>; }) {
147+ return {__strategy::__none, false };
148+ } else if constexpr (constant_range<all_t <_Type>>) {
149+ return {__strategy::__already_const, noexcept (views::all (std::declval<_Type>()))};
150+ } else if constexpr (__is_specialization_v<_UType, empty_view>) {
151+ return {__strategy::__empty_view, true };
152+ } else if constexpr (__is_span_v<_UType>) {
153+ return {__strategy::__span, true };
154+ } else if constexpr (__is_specialization_v<_UType, ref_view> && constant_range<const _XType>) {
155+ return {__strategy::__ref_view, noexcept (ref_view (static_cast <const _XType&>(std::declval<_Type>().base ())))};
156+ } else if constexpr (is_lvalue_reference_v<_Type> && constant_range<const _UType> && !view<_UType>) {
157+ return {__strategy::__const_is_constant_range,
158+ noexcept (ref_view (static_cast <const _UType&>(std::declval<_Type>())))};
159+ } else {
160+ return {__strategy::__otherwise, noexcept (as_const_view (std::declval<_Type>()))};
161+ }
162+ }
163+
164+ template <class _Type >
165+ requires (__choose_strategy<_Type>().first != __strategy::__none)
166+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static auto
167+ operator ()(_Type&& __range) noexcept (__choose_strategy<_Type>().second) {
168+ using _UType = std::remove_cvref_t <_Type>;
169+ using _XType = __xtype<_UType>::type;
170+
171+ constexpr auto __st = __choose_strategy<_Type>().first ;
172+
173+ if constexpr (__st == __strategy::__already_const) {
174+ return views::all (std::forward<_Type>(__range));
175+ } else if constexpr (__st == __strategy::__empty_view) {
176+ return auto (views::empty<const _XType>);
177+ } else if constexpr (__st == __strategy::__span) {
178+ return span<const _XType, __xtype<_UType>::__extent>(std::forward<_Type>(__range));
179+ } else if constexpr (__st == __strategy::__ref_view) {
180+ return ref_view (static_cast <const _XType&>(std::forward<_Type>(__range).base ()));
181+ } else if constexpr (__st == __strategy::__const_is_constant_range) {
182+ return ref_view (static_cast <const _UType&>(std::forward<_Type>(__range)));
183+ } else if constexpr (__st == __strategy::__otherwise) {
184+ return as_const_view (std::forward<_Type>(__range));
185+ }
223186 }
224187};
225188
0 commit comments