File indexing completed on 2025-01-18 10:09:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef RANGES_V3_VIEW_INTERFACE_HPP
0014 #define RANGES_V3_VIEW_INTERFACE_HPP
0015
0016 #include <iosfwd>
0017
0018 #include <meta/meta.hpp>
0019
0020 #include <concepts/concepts.hpp>
0021
0022 #include <range/v3/range_fwd.hpp>
0023
0024 #include <range/v3/iterator/common_iterator.hpp>
0025 #include <range/v3/iterator/operations.hpp>
0026 #include <range/v3/range/access.hpp>
0027 #include <range/v3/range/concepts.hpp>
0028 #include <range/v3/range/primitives.hpp>
0029 #include <range/v3/range/traits.hpp>
0030
0031 #include <range/v3/detail/prologue.hpp>
0032
0033 #if defined(RANGES_WORKAROUND_GCC_91525)
0034 #define CPP_template_gcc_workaround CPP_template_sfinae
0035 #else
0036 #define CPP_template_gcc_workaround template
0037 #endif
0038
0039 namespace ranges
0040 {
0041
0042 namespace detail
0043 {
0044 template<typename From, typename To = From>
0045 struct slice_bounds
0046 {
0047 From from;
0048 To to;
0049 template(typename F, typename T)(
0050 requires convertible_to<F, From> AND convertible_to<T, To>)
0051 constexpr slice_bounds(F f, T t)
0052 : from(static_cast<From>(f))
0053 , to(static_cast<To>(t))
0054 {}
0055 };
0056
0057 template<typename Int>
0058 struct from_end_
0059 {
0060 Int dist_;
0061
0062 constexpr explicit from_end_(Int dist)
0063 : dist_(dist)
0064 {}
0065
0066 template(typename Other)(
0067 requires integer_like_<Other> AND explicitly_convertible_to<Other, Int>)
0068 constexpr operator from_end_<Other>() const
0069 {
0070 return from_end_<Other>{static_cast<Other>(dist_)};
0071 }
0072 };
0073
0074 template<typename Rng>
0075 using from_end_of_t = from_end_<range_difference_t<Rng>>;
0076
0077
0078
0079
0080 template<typename Rng>
0081 CPP_requires(_can_empty_,
0082 requires(Rng & rng)
0083 (
0084 ranges::empty(rng)
0085 ));
0086
0087
0088 template<typename Rng>
0089 CPP_concept can_empty_ =
0090 CPP_requires_ref(detail::_can_empty_, Rng);
0091
0092
0093 template<cardinality C>
0094 RANGES_INLINE_VAR constexpr bool has_fixed_size_ = (C >= 0 || C == infinite);
0095
0096 template<bool>
0097 struct dependent_
0098 {
0099 template<typename T>
0100 using invoke = T;
0101 };
0102
0103 template<typename Stream, typename Rng>
0104 Stream & print_rng_(Stream & sout, Rng & rng)
0105 {
0106 sout << '[';
0107 auto it = ranges::begin(rng);
0108 auto const e = ranges::end(rng);
0109 if(it != e)
0110 {
0111 for(;;)
0112 {
0113 sout << *it;
0114 if(++it == e)
0115 break;
0116 sout << ',';
0117 }
0118 }
0119 sout << ']';
0120 return sout;
0121 }
0122 }
0123
0124
0125
0126
0127 template<typename Derived, cardinality Cardinality >
0128 struct view_interface : basic_view<Cardinality>
0129 {
0130 protected:
0131 template<bool B>
0132 using D = meta::invoke<detail::dependent_<B>, Derived>;
0133
0134 constexpr Derived & derived() noexcept
0135 {
0136 CPP_assert(derived_from<Derived, view_interface>);
0137 return static_cast<Derived &>(*this);
0138 }
0139
0140 constexpr Derived const & derived() const noexcept
0141 {
0142 CPP_assert(derived_from<Derived, view_interface>);
0143 return static_cast<Derived const &>(*this);
0144 }
0145
0146 public:
0147 view_interface() = default;
0148 view_interface(view_interface &&) = default;
0149 view_interface(view_interface const &) = default;
0150 view_interface & operator=(view_interface &&) = default;
0151 view_interface & operator=(view_interface const &) = default;
0152
0153 CPP_member
0154 constexpr auto empty() const noexcept
0155 -> CPP_ret(bool)(
0156 requires (detail::has_fixed_size_<Cardinality>))
0157 {
0158 return Cardinality == 0;
0159 }
0160
0161 template(bool True = true)(
0162 requires True AND (Cardinality < 0) AND (Cardinality != infinite) AND
0163 (!forward_range<D<True>>) AND sized_range<D<True>>)
0164 constexpr bool empty()
0165 noexcept(noexcept(bool(ranges::size(std::declval<D<True> &>()) == 0)))
0166 {
0167 return ranges::size(derived()) == 0;
0168 }
0169
0170 template(bool True = true)(
0171 requires True AND (Cardinality < 0) AND (Cardinality != infinite) AND
0172 (!forward_range<D<True> const>) AND sized_range<D<True> const>)
0173 constexpr bool empty() const
0174 noexcept(noexcept(bool(ranges::size(std::declval<D<True> const &>()) == 0)))
0175 {
0176 return ranges::size(derived()) == 0;
0177 }
0178
0179 template(bool True = true)(
0180 requires True AND (!detail::has_fixed_size_<Cardinality>) AND
0181 forward_range<D<True>>)
0182 constexpr bool empty() noexcept(
0183 noexcept(bool(ranges::begin(std::declval<D<True> &>()) ==
0184 ranges::end(std::declval<D<True> &>()))))
0185 {
0186 return bool(ranges::begin(derived()) == ranges::end(derived()));
0187 }
0188
0189 template(bool True = true)(
0190 requires True AND (!detail::has_fixed_size_<Cardinality>) AND
0191 forward_range<D<True> const>)
0192 constexpr bool empty() const
0193 noexcept(noexcept(bool(ranges::begin(std::declval<D<True> const &>()) ==
0194 ranges::end(std::declval<D<True> const &>()))))
0195 {
0196 return bool(ranges::begin(derived()) == ranges::end(derived()));
0197 }
0198 CPP_template_gcc_workaround(bool True = true)(
0199 requires True && detail::can_empty_<D<True>>)
0200 constexpr explicit operator bool()
0201 noexcept(noexcept(ranges::empty(std::declval<D<True> &>())))
0202 {
0203 return !ranges::empty(derived());
0204 }
0205
0206
0207 CPP_template_gcc_workaround(bool True = true)(
0208 requires True && detail::can_empty_<D<True> const>)
0209 constexpr explicit operator bool() const
0210 noexcept(noexcept(ranges::empty(std::declval<D<True> const &>())))
0211 {
0212 return !ranges::empty(derived());
0213 }
0214
0215
0216
0217 template(bool True = true, int = 42)(
0218 requires True AND (Cardinality >= 0))
0219 static constexpr std::size_t size() noexcept
0220 {
0221 return static_cast<std::size_t>(Cardinality);
0222 }
0223
0224
0225
0226 template(bool True = true)(
0227 requires True AND (Cardinality < 0) AND
0228 sized_sentinel_for<sentinel_t<D<True>>, iterator_t<D<True>>> AND
0229 forward_range<D<True>>)
0230 constexpr detail::iter_size_t<iterator_t<D<True>>> size()
0231 {
0232 using size_type = detail::iter_size_t<iterator_t<D<True>>>;
0233 return static_cast<size_type>(derived().end() - derived().begin());
0234 }
0235
0236 template(bool True = true)(
0237 requires True AND (Cardinality < 0) AND
0238 sized_sentinel_for<sentinel_t<D<True> const>,
0239 iterator_t<D<True> const>> AND
0240 forward_range<D<True> const>)
0241 constexpr detail::iter_size_t<iterator_t<D<True>>> size() const
0242 {
0243 using size_type = detail::iter_size_t<iterator_t<D<True>>>;
0244 return static_cast<size_type>(derived().end() - derived().begin());
0245 }
0246
0247 template(bool True = true)(
0248 requires True AND forward_range<D<True>>)
0249 constexpr range_reference_t<D<True>> front()
0250 {
0251 return *derived().begin();
0252 }
0253
0254 template(bool True = true)(
0255 requires True AND forward_range<D<True> const>)
0256 constexpr range_reference_t<D<True> const> front() const
0257 {
0258 return *derived().begin();
0259 }
0260
0261 template(bool True = true)(
0262 requires True AND common_range<D<True>> AND bidirectional_range<D<True>>)
0263 constexpr range_reference_t<D<True>> back()
0264 {
0265 return *prev(derived().end());
0266 }
0267
0268 template(bool True = true)(
0269 requires True AND common_range<D<True> const> AND
0270 bidirectional_range<D<True> const>)
0271 constexpr range_reference_t<D<True> const> back() const
0272 {
0273 return *prev(derived().end());
0274 }
0275
0276 template(bool True = true)(
0277 requires True AND random_access_range<D<True>>)
0278 constexpr range_reference_t<D<True>> operator[](range_difference_t<D<True>> n)
0279 {
0280 return derived().begin()[n];
0281 }
0282
0283 template(bool True = true)(
0284 requires True AND random_access_range<D<True> const>)
0285 constexpr range_reference_t<D<True> const>
0286 operator[](range_difference_t<D<True>> n) const
0287 {
0288 return derived().begin()[n];
0289 }
0290
0291
0292 template(bool True = true)(
0293 requires True AND contiguous_iterator<iterator_t<D<True>>>)
0294 constexpr std::add_pointer_t<range_reference_t<D<True>>> data()
0295 {
0296 return std::addressof(*ranges::begin(derived()));
0297 }
0298
0299 template(bool True = true)(
0300 requires True AND contiguous_iterator<iterator_t<D<True> const>>)
0301 constexpr std::add_pointer_t<range_reference_t<D<True> const>> data() const
0302 {
0303 return std::addressof(*ranges::begin(derived()));
0304 }
0305
0306
0307 template(bool True = true)(
0308 requires True AND random_access_range<D<True>> AND sized_range<D<True>>)
0309 constexpr range_reference_t<D<True>> at(range_difference_t<D<True>> n)
0310 {
0311 using size_type = range_size_t<Derived>;
0312 if(n < 0 || size_type(n) >= ranges::size(derived()))
0313 {
0314 throw std::out_of_range("view_interface::at");
0315 }
0316 return derived().begin()[n];
0317 }
0318
0319 template(bool True = true)(
0320 requires True AND random_access_range<D<True> const> AND
0321 sized_range<D<True> const>)
0322 constexpr range_reference_t<D<True> const> at(range_difference_t<D<True>> n) const
0323 {
0324 using size_type = range_size_t<Derived const>;
0325 if(n < 0 || size_type(n) >= ranges::size(derived()))
0326 {
0327 throw std::out_of_range("view_interface::at");
0328 }
0329 return derived().begin()[n];
0330 }
0331
0332
0333 template(bool True = true, typename Slice = views::slice_fn)(
0334 requires True AND input_range<D<True> &>)
0335 constexpr auto
0336 operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) &
0337 {
0338 return Slice{}(derived(), offs.from, offs.to);
0339 }
0340
0341 template(bool True = true, typename Slice = views::slice_fn)(
0342 requires True AND input_range<D<True> const &>)
0343 constexpr auto
0344 operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) const &
0345 {
0346 return Slice{}(derived(), offs.from, offs.to);
0347 }
0348
0349 template(bool True = true, typename Slice = views::slice_fn)(
0350 requires True AND input_range<D<True>>)
0351 constexpr auto
0352 operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) &&
0353 {
0354 return Slice{}(detail::move(derived()), offs.from, offs.to);
0355 }
0356
0357
0358 template(bool True = true, typename Slice = views::slice_fn)(
0359 requires True AND input_range<D<True> &> AND sized_range<D<True> &>)
0360 constexpr auto
0361 operator[](detail::slice_bounds<range_difference_t<D<True>>,
0362 detail::from_end_of_t<D<True>>> offs) &
0363 {
0364 return Slice{}(derived(), offs.from, offs.to);
0365 }
0366
0367 template(bool True = true, typename Slice = views::slice_fn)(
0368 requires True AND input_range<D<True> const &> AND
0369 sized_range<D<True> const &>)
0370 constexpr auto
0371 operator[](detail::slice_bounds<range_difference_t<D<True>>,
0372 detail::from_end_of_t<D<True>>> offs) const &
0373 {
0374 return Slice{}(derived(), offs.from, offs.to);
0375 }
0376
0377 template(bool True = true, typename Slice = views::slice_fn)(
0378 requires True AND input_range<D<True>> AND sized_range<D<True>>)
0379 constexpr auto
0380 operator[](detail::slice_bounds<range_difference_t<D<True>>,
0381 detail::from_end_of_t<D<True>>> offs) &&
0382 {
0383 return Slice{}(detail::move(derived()), offs.from, offs.to);
0384 }
0385
0386
0387 template(bool True = true, typename Slice = views::slice_fn)(
0388 requires True AND (forward_range<D<True> &> ||
0389 (input_range<D<True> &> && sized_range<D<True> &>)))
0390 constexpr auto
0391 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
0392 detail::from_end_of_t<D<True>>> offs) &
0393 {
0394 return Slice{}(derived(), offs.from, offs.to);
0395 }
0396
0397 template(bool True = true, typename Slice = views::slice_fn)(
0398 requires True AND
0399 (forward_range<D<True> const &> ||
0400 (input_range<D<True> const &> && sized_range<D<True> const &>)))
0401 constexpr auto
0402 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
0403 detail::from_end_of_t<D<True>>> offs) const &
0404 {
0405 return Slice{}(derived(), offs.from, offs.to);
0406 }
0407
0408 template(bool True = true, typename Slice = views::slice_fn)(
0409 requires True AND
0410 (forward_range<D<True>> ||
0411 (input_range<D<True>> && sized_range<D<True>>)))
0412 constexpr auto
0413 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
0414 detail::from_end_of_t<D<True>>> offs) &&
0415 {
0416 return Slice{}(detail::move(derived()), offs.from, offs.to);
0417 }
0418
0419
0420 template(bool True = true, typename Slice = views::slice_fn)(
0421 requires True AND input_range<D<True> &>)
0422 constexpr auto
0423 operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) &
0424 {
0425 return Slice{}(derived(), offs.from, offs.to);
0426 }
0427
0428 template(bool True = true, typename Slice = views::slice_fn)(
0429 requires True AND input_range<D<True> const &>)
0430 constexpr auto
0431 operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) const &
0432 {
0433 return Slice{}(derived(), offs.from, offs.to);
0434 }
0435
0436 template(bool True = true, typename Slice = views::slice_fn)(
0437 requires True AND input_range<D<True>>)
0438 constexpr auto
0439 operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) &&
0440 {
0441 return Slice{}(detail::move(derived()), offs.from, offs.to);
0442 }
0443
0444
0445 template(bool True = true, typename Slice = views::slice_fn)(
0446 requires True AND
0447 (forward_range<D<True> &> ||
0448 (input_range<D<True> &> && sized_range<D<True> &>)))
0449 constexpr auto
0450 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) &
0451 {
0452 return Slice{}(derived(), offs.from, offs.to);
0453 }
0454
0455 template(bool True = true, typename Slice = views::slice_fn)(
0456 requires True AND
0457 (forward_range<D<True> const &> ||
0458 (input_range<D<True> const &> && sized_range<D<True> const &>)))
0459 constexpr auto
0460 operator[](
0461 detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) const &
0462 {
0463 return Slice{}(derived(), offs.from, offs.to);
0464 }
0465
0466 template(bool True = true, typename Slice = views::slice_fn)(
0467 requires True AND
0468 (forward_range<D<True>> ||
0469 (input_range<D<True>> && sized_range<D<True>>)))
0470 constexpr auto
0471 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) &&
0472 {
0473 return Slice{}(detail::move(derived()), offs.from, offs.to);
0474 }
0475 private:
0476 #ifndef RANGES_V3_DISABLE_IO
0477
0478 template<bool True = true>
0479 friend auto operator<<(std::ostream & sout, Derived const & rng)
0480 -> CPP_broken_friend_ret(std::ostream &)(
0481 requires True && input_range<D<True> const>)
0482 {
0483 return detail::print_rng_(sout, rng);
0484 }
0485
0486 template<bool True = true>
0487 friend auto operator<<(std::ostream & sout, Derived & rng)
0488 -> CPP_broken_friend_ret(std::ostream &)(
0489 requires True && (!range<D<True> const>) && input_range<D<True>>)
0490 {
0491 return detail::print_rng_(sout, rng);
0492 }
0493
0494 template<bool True = true>
0495 friend auto operator<<(std::ostream & sout, Derived && rng)
0496 -> CPP_broken_friend_ret(std::ostream &)(
0497 requires True && (!range<D<True> const>) && input_range<D<True>>)
0498 {
0499 return detail::print_rng_(sout, rng);
0500 }
0501 #endif
0502 };
0503 namespace cpp20
0504 {
0505 template(typename Derived)(
0506 requires std::is_class<Derived>::value AND
0507 same_as<Derived, meta::_t<std::remove_cv<Derived>>>)
0508 using view_interface = ranges::view_interface<Derived, ranges::unknown>;
0509 }
0510
0511 }
0512
0513 #include <range/v3/detail/epilogue.hpp>
0514
0515 #endif