|
| 1 | +// RUN: %clang_cc1 -std=c++20 -w %s |
| 2 | +// RUN: %clang_cc1 -std=c++2c -w %s |
| 3 | +// expected-no-diagnostics |
| 4 | + |
| 5 | +namespace std { |
| 6 | +template <typename _Tp, _Tp __v> struct integral_constant { |
| 7 | + static constexpr _Tp value = __v; |
| 8 | + using value_type = _Tp; |
| 9 | +}; |
| 10 | +template <bool __v> using __bool_constant = integral_constant<bool, __v>; |
| 11 | +template <typename> struct is_integral : integral_constant<bool, true> {}; |
| 12 | +template <typename> struct is_signed : integral_constant<bool, false> {}; |
| 13 | +template <typename _Tp, typename _Up = _Tp> _Up __declval(int); |
| 14 | +template <typename _Tp> auto declval() -> decltype(__declval<_Tp>(0)); |
| 15 | +template <typename> struct make_unsigned { |
| 16 | + using type = int; |
| 17 | +}; |
| 18 | +template <typename _Tp> struct decay { |
| 19 | + using type = _Tp; |
| 20 | +}; |
| 21 | +template <int, typename _Iftrue, typename> struct conditional { |
| 22 | + using type = _Iftrue; |
| 23 | +}; |
| 24 | +} // namespace std |
| 25 | +namespace meta { |
| 26 | +template <template <typename...> class> struct quote; |
| 27 | +template <template <typename> class C, typename... Ts> |
| 28 | +concept valid = requires { typename C<Ts...>; }; |
| 29 | +template <typename T> |
| 30 | +concept trait = requires { typename T; }; |
| 31 | +template <typename T> |
| 32 | +concept invocable = requires { typename quote<T::template invoke>; }; |
| 33 | +template <typename T> |
| 34 | +concept integral = requires { T::value; }; |
| 35 | +template <trait T> using _t = T::type; |
| 36 | +template <integral T> constexpr T::value_type _v = T::value; |
| 37 | +template <bool B> using bool_ = std::integral_constant<bool, B>; |
| 38 | +template <invocable Fn, typename... Args> |
| 39 | +using invoke = Fn::template invoke<Args...>; |
| 40 | +template <typename> struct id; |
| 41 | +namespace detail { |
| 42 | +template <template <typename> class, typename...> struct defer_; |
| 43 | +template <template <typename> class C, typename... Ts> |
| 44 | + requires valid<C, Ts...> |
| 45 | +struct defer_<C, Ts...> { |
| 46 | + using type = C<Ts...>; |
| 47 | +}; |
| 48 | +} // namespace detail |
| 49 | +template <template <typename> class C, typename... Ts> |
| 50 | +struct defer : detail::defer_<C, Ts...> {}; |
| 51 | +template <template <typename...> class C> struct quote { |
| 52 | + template <typename... Ts> using invoke = _t<defer<C, Ts...>>; |
| 53 | +}; |
| 54 | +namespace detail { |
| 55 | +template <int> struct _cond { |
| 56 | + template <typename Then, typename> using invoke = Then; |
| 57 | +}; |
| 58 | +template <> struct _cond<false>; |
| 59 | +} // namespace detail |
| 60 | +template <bool If, typename Then, typename Else> |
| 61 | +using conditional_t = detail::_cond<If>::template invoke<Then, Else>; |
| 62 | +namespace detail { |
| 63 | +template <typename...> struct _if_; |
| 64 | +template <typename If, typename Then, typename Else> |
| 65 | +struct _if_<If, Then, Else> : std::conditional<_v<If>, Then, Else> {}; |
| 66 | +} // namespace detail |
| 67 | +template <bool If, typename... Args> |
| 68 | +using if_c = _t<detail::_if_<bool_<If>, Args...>>; |
| 69 | +} // namespace meta |
| 70 | +template <bool> void requires_(); |
| 71 | +template <typename A, typename B> |
| 72 | +concept same_as = __is_same(B, A); |
| 73 | +namespace ranges { |
| 74 | +template <typename> struct view_closure; |
| 75 | +template <typename T> using decay_t = meta::_t<std::decay<T>>; |
| 76 | +enum cardinality { unknown }; |
| 77 | +template <cardinality> struct basic_view {}; |
| 78 | +} // namespace ranges |
| 79 | +namespace std { |
| 80 | +template <typename> struct vector {}; |
| 81 | +} // namespace std |
| 82 | +namespace ranges { |
| 83 | +struct { |
| 84 | + template <typename F, typename... Args> |
| 85 | + auto operator()(F f, Args... args) -> decltype(f(args...)); |
| 86 | +} invoke; |
| 87 | +template <typename Fun, typename... Args> |
| 88 | +using invoke_result_t = |
| 89 | + decltype(invoke(std::declval<Fun>(), std::declval<Args>()...)); |
| 90 | +namespace detail { |
| 91 | +struct with_difference_type_; |
| 92 | +template <typename T> using iter_value_t_ = T ::value_type; |
| 93 | +} // namespace detail |
| 94 | +template <typename R> using iter_value_t = detail::iter_value_t_<R>; |
| 95 | +namespace detail { |
| 96 | +template <typename I> |
| 97 | +using iter_size_t = |
| 98 | + meta::_t<meta::conditional_t<std::is_integral<I>::value, |
| 99 | + std::make_unsigned<I>, meta::id<I>>>; |
| 100 | +template <typename D> |
| 101 | +concept signed_integer_like_impl_concept_ = |
| 102 | + std::integral_constant<bool, -D()>::value; |
| 103 | +template <typename D> |
| 104 | +concept signed_integer_like_ = signed_integer_like_impl_concept_<D>; |
| 105 | +} // namespace detail |
| 106 | +template <typename S, typename I> |
| 107 | +concept sized_sentinel_for_requires_ = |
| 108 | + requires(S s, I i) { requires_<same_as<I, decltype(i - s)>>; }; |
| 109 | +template <typename S, typename I> |
| 110 | +concept sized_sentinel_for = sized_sentinel_for_requires_<S, I>; |
| 111 | +struct range_access { |
| 112 | + template <typename Rng> |
| 113 | + static auto begin_cursor(Rng rng) -> decltype(rng.begin_cursor()); |
| 114 | + template <typename Cur, typename O> |
| 115 | + static auto distance_to(Cur pos, O other) -> decltype(pos.distance_to(other)); |
| 116 | +}; |
| 117 | +namespace detail { |
| 118 | +template <typename S, typename C> |
| 119 | +concept sized_sentinel_for_cursor_requires_ = requires(S s, C c) { |
| 120 | + requires_<signed_integer_like_<decltype(range_access::distance_to(c, s))>>; |
| 121 | +}; |
| 122 | +template <typename S, typename C> |
| 123 | +concept sized_sentinel_for_cursor = sized_sentinel_for_cursor_requires_<S, C>; |
| 124 | +struct iterator_associated_types_base_ { |
| 125 | + typedef range_access value_type; |
| 126 | +}; |
| 127 | +template <typename> |
| 128 | +using iterator_associated_types_base = iterator_associated_types_base_; |
| 129 | +} // namespace detail |
| 130 | +template <typename> |
| 131 | +struct basic_iterator : detail::iterator_associated_types_base<int> {}; |
| 132 | +template <typename Cur2, typename Cur> |
| 133 | + requires detail::sized_sentinel_for_cursor<Cur2, Cur> |
| 134 | +void operator-(basic_iterator<Cur2>, basic_iterator<Cur>); |
| 135 | +namespace _begin_ { |
| 136 | +template <typename T> |
| 137 | +concept has_member_begin_requires_ = requires(T t) { t; }; |
| 138 | +template <typename T> |
| 139 | +concept has_member_begin = has_member_begin_requires_<T>; |
| 140 | +struct _member_result_ { |
| 141 | + template <typename R> |
| 142 | + using invoke = decltype(static_cast<R (*)()>(nullptr)().begin()); |
| 143 | +}; |
| 144 | +struct _non_member_result_; |
| 145 | +struct fn { |
| 146 | + template <typename R> |
| 147 | + using _result_t = |
| 148 | + meta::invoke<meta::conditional_t<has_member_begin<R>, _member_result_, |
| 149 | + _non_member_result_>, |
| 150 | + R>; |
| 151 | + template <typename R> _result_t<R> operator()(R); |
| 152 | +}; |
| 153 | +} // namespace _begin_ |
| 154 | +_begin_::fn begin; |
| 155 | +namespace _end_ { |
| 156 | +template <typename> |
| 157 | +concept has_member_end_requires_ = requires { begin; }; |
| 158 | +template <typename T> |
| 159 | +concept has_member_end = has_member_end_requires_<T>; |
| 160 | +struct _member_result_ { |
| 161 | + template <typename R> |
| 162 | + using invoke = decltype(static_cast<R (*)()>(nullptr)().end()); |
| 163 | +}; |
| 164 | +struct _non_member_result_; |
| 165 | +struct fn { |
| 166 | + template <typename R> |
| 167 | + using _result_t = |
| 168 | + meta::invoke<meta::conditional_t<has_member_end<R>, _member_result_, |
| 169 | + _non_member_result_>, |
| 170 | + R>; |
| 171 | + template <typename R> _result_t<R> operator()(R); |
| 172 | +}; |
| 173 | +} // namespace _end_ |
| 174 | +_end_::fn end; |
| 175 | +template <typename Rng> |
| 176 | +using iterator_t = decltype(begin(static_cast<Rng (*)()>(nullptr)())); |
| 177 | +template <typename Rng> |
| 178 | +using sentinel_t = decltype(end(static_cast<Rng (*)()>(nullptr)())); |
| 179 | +template <typename T> |
| 180 | +concept has_member_size_requires_ = requires(T t) { t.size(); }; |
| 181 | +template <typename T> |
| 182 | +concept has_member_size = has_member_size_requires_<T>; |
| 183 | +struct _other_result_; |
| 184 | +struct _member_result_ { |
| 185 | + template <typename> using invoke = decltype(0); |
| 186 | + template <typename R> |
| 187 | + using _result_t = meta::invoke< |
| 188 | + meta::conditional_t<has_member_size<R>, _member_result_, _other_result_>, |
| 189 | + R>; |
| 190 | + template <typename R> _result_t<R> operator()(R r) { r.size(); } |
| 191 | +} size; |
| 192 | +template <typename Rng> using range_value_t = iter_value_t<iterator_t<Rng>>; |
| 193 | +namespace detail { |
| 194 | +template <cardinality Card> |
| 195 | +std::integral_constant<cardinality, Card> test_cardinality(basic_view<Card> *); |
| 196 | +} |
| 197 | +template <typename Rng> |
| 198 | +struct range_cardinality |
| 199 | + : meta::conditional_t<__is_same(Rng, Rng), |
| 200 | + decltype(detail::test_cardinality( |
| 201 | + static_cast<Rng *>(nullptr))), |
| 202 | + Rng> {}; |
| 203 | +template <typename T> |
| 204 | +concept sized_range_requires_ = requires(T t) { size(t); }; |
| 205 | +template <typename T> |
| 206 | +concept sized_range = sized_range_requires_<T>; |
| 207 | +namespace detail { |
| 208 | +template <int> struct dependent_ { |
| 209 | + template <typename T> using invoke = T; |
| 210 | +}; |
| 211 | +} // namespace detail |
| 212 | +template <typename Derived, cardinality Cardinality> |
| 213 | +struct view_interface : basic_view<Cardinality> { |
| 214 | + template <bool B> using D = meta::invoke<detail::dependent_<B>, Derived>; |
| 215 | + Derived derived(); |
| 216 | + template <bool True = true> |
| 217 | + requires sized_sentinel_for<sentinel_t<D<True>>, iterator_t<D<True>>> |
| 218 | + detail::iter_size_t<iterator_t<D<True>>> size() { |
| 219 | + derived().end() - derived().begin(); |
| 220 | + } |
| 221 | +}; |
| 222 | +struct { |
| 223 | + template <typename Fun> view_closure<Fun> operator()(Fun); |
| 224 | +} make_view_closure; |
| 225 | +struct view_closure_base { |
| 226 | + template <typename Rng, typename ViewFn> |
| 227 | + friend auto operator|(Rng rng, ViewFn vw) { |
| 228 | + return vw(rng); |
| 229 | + } |
| 230 | +}; |
| 231 | +template <typename ViewFn> struct view_closure : view_closure_base, ViewFn {}; |
| 232 | +namespace detail { |
| 233 | +template <typename Derived> |
| 234 | +using begin_cursor_t = |
| 235 | + decay_t<decltype(range_access::begin_cursor(std::declval<Derived>()))>; |
| 236 | +template <typename Derived> |
| 237 | +using facade_iterator_t = basic_iterator<begin_cursor_t<Derived>>; |
| 238 | +template <typename Derived> |
| 239 | +using facade_sentinel_t = |
| 240 | + meta::if_c<same_as<Derived, Derived>, facade_iterator_t<Derived>, Derived>; |
| 241 | +} // namespace detail |
| 242 | +template <typename Derived, cardinality Cardinality> |
| 243 | +struct view_facade : view_interface<Derived, Cardinality> { |
| 244 | + template <typename D = Derived> auto begin() -> detail::facade_iterator_t<D>; |
| 245 | + template <typename D = Derived> auto end() -> detail::facade_sentinel_t<D>; |
| 246 | +}; |
| 247 | +template <typename Derived, cardinality Cardinality> |
| 248 | +struct view_adaptor : view_facade<Derived, Cardinality> { |
| 249 | + auto begin_cursor() -> decltype(0); |
| 250 | +}; |
| 251 | +namespace detail { |
| 252 | +template <typename...> struct bind_back_fn_; |
| 253 | +template <typename Fn, typename Arg> struct bind_back_fn_<Fn, Arg> { |
| 254 | + template <typename... CallArgs> |
| 255 | + invoke_result_t<Fn, CallArgs..., Arg> operator()(CallArgs...); |
| 256 | +}; |
| 257 | +template <typename Fn, typename... Args> |
| 258 | +using bind_back_fn = bind_back_fn_<Fn, Args...>; |
| 259 | +} // namespace detail |
| 260 | +struct { |
| 261 | + template <typename Fn, typename Arg1> |
| 262 | + detail::bind_back_fn<Fn, Arg1> operator()(Fn, Arg1); |
| 263 | +} bind_back; |
| 264 | +namespace detail { |
| 265 | +struct to_container { |
| 266 | + template <typename> struct fn; |
| 267 | + template <typename, typename> struct closure; |
| 268 | +}; |
| 269 | +template <typename, typename, typename R> |
| 270 | +concept to_container_reserve = sized_range<R>; |
| 271 | +template <typename MetaFn, typename Rng> |
| 272 | +using container_t = meta::invoke<MetaFn, Rng>; |
| 273 | +struct to_container_closure_base { |
| 274 | + template <typename Rng, typename MetaFn, typename Fn> |
| 275 | + friend auto operator|(Rng rng, to_container::closure<MetaFn, Fn> fn) { |
| 276 | + return fn(rng); |
| 277 | + } |
| 278 | +}; |
| 279 | +template <typename, typename Fn> |
| 280 | +struct to_container::closure : to_container_closure_base, Fn {}; |
| 281 | +template <typename MetaFn> struct to_container::fn { |
| 282 | + template <typename Rng> void impl(Rng, std::__bool_constant<false>); |
| 283 | + template <typename Rng> void impl(Rng rng, std::__bool_constant<true>) { |
| 284 | + size(rng); |
| 285 | + } |
| 286 | + template <typename Rng> container_t<MetaFn, Rng> operator()(Rng rng) { |
| 287 | + using cont_t = container_t<MetaFn, Rng>; |
| 288 | + using iter_t = Rng; |
| 289 | + using use_reserve_t = |
| 290 | + meta::bool_<to_container_reserve<cont_t, iter_t, Rng>>; |
| 291 | + impl(rng, use_reserve_t{}); |
| 292 | + } |
| 293 | +}; |
| 294 | +template <typename MetaFn, typename Fn> |
| 295 | +using to_container_closure = to_container::closure<MetaFn, Fn>; |
| 296 | +template <typename MetaFn> |
| 297 | +using to_container_fn = to_container_closure<MetaFn, to_container::fn<MetaFn>>; |
| 298 | +template <template <typename> class ContT> struct from_range { |
| 299 | + template <typename Rng> |
| 300 | + static auto from_rng_(long) |
| 301 | + -> meta::invoke<meta::quote<ContT>, range_value_t<Rng>>; |
| 302 | + template <typename Rng> using invoke = decltype(from_rng_<Rng>(0)); |
| 303 | +}; |
| 304 | +} // namespace detail |
| 305 | +detail::to_container_fn<detail::from_range<std::vector>> to_vector; |
| 306 | +template <typename Rng> |
| 307 | +struct remove_if_view |
| 308 | + : view_adaptor<remove_if_view<Rng>, range_cardinality<Rng>::value> {}; |
| 309 | +struct filter_base_fn { |
| 310 | + template <typename Rng, typename Pred> |
| 311 | + remove_if_view<Rng> operator()(Rng, Pred); |
| 312 | + template <typename Pred> auto operator()(Pred pred) { |
| 313 | + return make_view_closure(bind_back(filter_base_fn{}, pred)); |
| 314 | + } |
| 315 | +} filter; |
| 316 | +namespace detail { |
| 317 | +struct promote_as_signed_; |
| 318 | +template <typename I> |
| 319 | +using iota_difference_t = |
| 320 | + meta::conditional_t<std::is_integral<I>::value, promote_as_signed_, |
| 321 | + with_difference_type_>; |
| 322 | +} // namespace detail |
| 323 | +template <typename, typename> |
| 324 | +struct iota_view : view_facade<iota_view<int, int>, unknown> { |
| 325 | + struct cursor { |
| 326 | + auto distance_to(cursor) -> detail::iota_difference_t<int>; |
| 327 | + }; |
| 328 | + cursor begin_cursor(); |
| 329 | +}; |
| 330 | +struct { |
| 331 | + template <typename From, typename To> |
| 332 | + requires(std::is_signed<From>::value == std::is_signed<To>::value) |
| 333 | + iota_view<From, To> operator()(From, To); |
| 334 | +} iota; |
| 335 | +} // namespace ranges |
| 336 | +void foo() { |
| 337 | + ranges::iota(0, 1) | ranges::to_vector = |
| 338 | + ranges::iota(0, 1) | ranges::filter([] {}) | ranges::to_vector; |
| 339 | +} |
0 commit comments