@@ -103,123 +103,86 @@ inline constexpr bool enable_borrowed_range<as_const_view<_Tp>> = enable_borrowe
103
103
namespace views {
104
104
namespace __as_const {
105
105
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 ;
130
110
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 ;
140
114
};
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;
152
118
};
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;
167
123
};
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;
180
127
};
181
128
182
129
struct __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
+ }
223
186
}
224
187
};
225
188
0 commit comments