Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:09:56

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Eric Niebler 2014-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
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     /// \cond
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         // clang-format off
0078         /// \concept _can_empty_
0079         /// \brief The \c _can_empty_ concept
0080         template<typename Rng>
0081         CPP_requires(_can_empty_,
0082             requires(Rng & rng) //
0083             (
0084                 ranges::empty(rng)
0085             ));
0086         /// \concept can_empty_
0087         /// \brief The \c can_empty_ concept
0088         template<typename Rng>
0089         CPP_concept can_empty_ = //
0090             CPP_requires_ref(detail::_can_empty_, Rng);
0091         // clang-format on
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     } // namespace detail
0123     /// \endcond
0124 
0125     /// \addtogroup group-views
0126     /// @{
0127     template<typename Derived, cardinality Cardinality /* = finite*/>
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         /// \overload
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         /// \brief Test whether a range can be empty:
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         /// \overload
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         /// \overload
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         /// \overload
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         /// \overload
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>>) // clang-format off
0200         constexpr explicit operator bool()
0201             noexcept(noexcept(ranges::empty(std::declval<D<True> &>())))
0202         {
0203             return !ranges::empty(derived());
0204         }
0205         // clang-format on
0206         /// \overload
0207         CPP_template_gcc_workaround(bool True = true)(
0208             requires True && detail::can_empty_<D<True> const>) // clang-format off
0209         constexpr explicit operator bool() const
0210             noexcept(noexcept(ranges::empty(std::declval<D<True> const &>())))
0211         {
0212             return !ranges::empty(derived());
0213         }
0214         // clang-format on
0215         /// If the size of the range is known at compile-time and finite,
0216         /// return it.
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         /// If `sized_sentinel_for<sentinel_t<Derived>, iterator_t<Derived>>` is
0224         /// satisfied, and if `Derived` is a `forward_range`, then return
0225         /// `end - begin` cast to an unsigned integer.
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         /// \overload
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         /// Access the first element in a range:
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         /// \overload
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         /// Access the last element in a range:
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         /// \overload
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         /// Simple indexing:
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         /// \overload
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         /// Returns a pointer to the block of memory
0291         /// containing the elements of a contiguous range:
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         /// \overload
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         /// Returns a reference to the element at specified location pos, with bounds
0306         /// checking.
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         /// \overload
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         /// Python-ic slicing:
0332         //      rng[{4,6}]
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         /// \overload
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         /// \overload
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         //      rng[{4,end-2}]
0357         /// \overload
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         /// \overload
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         /// \overload
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         //      rng[{end-4,end-2}]
0386         /// \overload
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         /// \overload
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         /// \overload
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         //      rng[{4,end}]
0419         /// \overload
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         /// \overload
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         /// \overload
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         //      rng[{end-4,end}]
0444         /// \overload
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         /// \overload
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         /// \overload
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         /// \brief Print a range to an ostream
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         /// \overload
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         /// \overload
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 } // namespace ranges
0512 
0513 #include <range/v3/detail/epilogue.hpp>
0514 
0515 #endif