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 2013-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 
0014 #ifndef RANGES_V3_VIEW_INTERSPERSE_HPP
0015 #define RANGES_V3_VIEW_INTERSPERSE_HPP
0016 
0017 #include <type_traits>
0018 #include <utility>
0019 
0020 #include <meta/meta.hpp>
0021 
0022 #include <range/v3/range_fwd.hpp>
0023 
0024 #include <range/v3/functional/bind_back.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 #include <range/v3/utility/static_const.hpp>
0031 #include <range/v3/view/adaptor.hpp>
0032 #include <range/v3/view/view.hpp>
0033 
0034 #include <range/v3/detail/prologue.hpp>
0035 
0036 namespace ranges
0037 {
0038     /// \addtogroup group-views
0039     /// @{
0040     template<typename Rng>
0041     struct intersperse_view
0042       : view_adaptor<intersperse_view<Rng>, Rng,
0043                      (range_cardinality<Rng>::value > 0)
0044                          ? static_cast<cardinality>(range_cardinality<Rng>::value * 2 - 1)
0045                          : range_cardinality<Rng>::value>
0046     {
0047         intersperse_view() = default;
0048         constexpr intersperse_view(Rng rng, range_value_t<Rng> val)
0049           : intersperse_view::view_adaptor{detail::move(rng)}
0050           , val_(detail::move(val))
0051         {}
0052         CPP_auto_member
0053         constexpr auto CPP_fun(size)()(const //
0054             requires sized_range<Rng const>)
0055         {
0056             auto const n = ranges::size(this->base());
0057             return n ? n * 2 - 1 : 0;
0058         }
0059         CPP_auto_member
0060         constexpr auto CPP_fun(size)()(
0061             requires sized_range<Rng>)
0062         {
0063             auto const n = ranges::size(this->base());
0064             return n ? n * 2 - 1 : 0;
0065         }
0066 
0067     private:
0068         friend range_access;
0069         template<bool Const>
0070         struct cursor_adaptor : adaptor_base
0071         {
0072         private:
0073             friend struct cursor_adaptor<!Const>;
0074             using CRng = meta::const_if_c<Const, Rng>;
0075             bool toggle_ = false;
0076             range_value_t<Rng> val_;
0077 
0078         public:
0079             cursor_adaptor() = default;
0080             constexpr explicit cursor_adaptor(range_value_t<Rng> const & val)
0081               : val_{val}
0082             {}
0083             template(bool Other)(
0084                 requires Const AND CPP_NOT(Other)) //
0085             cursor_adaptor(cursor_adaptor<Other> that)
0086               : toggle_(that.toggle_)
0087               , val_(std::move(that.val_))
0088             {}
0089             template<typename View>
0090             constexpr iterator_t<CRng> begin(View & view)
0091             {
0092                 auto first = ranges::begin(view.base());
0093                 toggle_ = first != ranges::end(view.base());
0094                 return first;
0095             }
0096             constexpr range_value_t<Rng> read(iterator_t<CRng> const & it) const
0097             {
0098                 return toggle_ ? *it : val_;
0099             }
0100             CPP_member
0101             constexpr auto equal(iterator_t<CRng> const & it0,
0102                                  iterator_t<CRng> const & it1,
0103                                  cursor_adaptor const & other) const //
0104                 -> CPP_ret(bool)(
0105                     requires sentinel_for<iterator_t<CRng>, iterator_t<CRng>>)
0106             {
0107                 return it0 == it1 && toggle_ == other.toggle_;
0108             }
0109             constexpr void next(iterator_t<CRng> & it)
0110             {
0111                 if(toggle_)
0112                     ++it;
0113                 toggle_ = !toggle_;
0114             }
0115             CPP_member
0116             constexpr auto prev(iterator_t<CRng> & it) //
0117                 -> CPP_ret(void)(
0118                     requires bidirectional_range<CRng>)
0119             {
0120                 toggle_ = !toggle_;
0121                 if(toggle_)
0122                     --it;
0123             }
0124             CPP_member
0125             constexpr auto distance_to(iterator_t<CRng> const & it,
0126                                        iterator_t<CRng> const & other_it,
0127                                        cursor_adaptor const & other) const
0128                 -> CPP_ret(range_difference_t<Rng>)(
0129                     requires sized_sentinel_for<iterator_t<CRng>, iterator_t<CRng>>)
0130             {
0131                 return (other_it - it) * 2 + (other.toggle_ - toggle_);
0132             }
0133             CPP_member
0134             constexpr auto advance(iterator_t<CRng> & it, range_difference_t<CRng> n) //
0135                 -> CPP_ret(void)(
0136                     requires random_access_range<CRng>)
0137             {
0138                 ranges::advance(it, n >= 0 ? (n + toggle_) / 2 : (n - !toggle_) / 2);
0139                 if(n % 2 != 0)
0140                     toggle_ = !toggle_;
0141             }
0142         };
0143         template<bool Const>
0144         struct sentinel_adaptor : adaptor_base
0145         {
0146         private:
0147             using CRng = meta::const_if_c<Const, Rng>;
0148 
0149         public:
0150             sentinel_adaptor() = default;
0151             template(bool Other)(
0152                 requires Const AND CPP_NOT(Other)) //
0153             sentinel_adaptor(sentinel_adaptor<Other>)
0154             {}
0155             static constexpr bool empty(iterator_t<CRng> const & it,
0156                                         cursor_adaptor<Const> const &,
0157                                         sentinel_t<CRng> const & sent)
0158             {
0159                 return it == sent;
0160             }
0161         };
0162         constexpr cursor_adaptor<false> begin_adaptor()
0163         {
0164             return cursor_adaptor<false>{val_};
0165         }
0166         CPP_member
0167         constexpr auto begin_adaptor() const //
0168             -> CPP_ret(cursor_adaptor<true>)(
0169                 requires range<Rng const>)
0170         {
0171             return cursor_adaptor<true>{val_};
0172         }
0173         CPP_member
0174         constexpr auto end_adaptor() //
0175             -> CPP_ret(cursor_adaptor<false>)(
0176                 requires common_range<Rng> && (!single_pass_iterator_<iterator_t<Rng>>))
0177         {
0178             return cursor_adaptor<false>{val_};
0179         }
0180         CPP_member
0181         constexpr auto end_adaptor() noexcept //
0182             -> CPP_ret(sentinel_adaptor<false>)(
0183                 requires (!common_range<Rng>) || single_pass_iterator_<iterator_t<Rng>>)
0184         {
0185             return {};
0186         }
0187         template(bool Const = true)(
0188             requires Const AND range<meta::const_if_c<Const, Rng>> AND
0189                 common_range<meta::const_if_c<Const, Rng>> AND
0190             (!single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>)) //
0191         constexpr cursor_adaptor<Const> end_adaptor() const
0192         {
0193             return cursor_adaptor<true>{val_};
0194         }
0195         template(bool Const = true)(
0196             requires Const AND range<meta::const_if_c<Const, Rng>> AND
0197                 (!common_range<meta::const_if_c<Const, Rng>> ||
0198                  single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>)) //
0199         constexpr sentinel_adaptor<Const> end_adaptor() const noexcept
0200         {
0201             return {};
0202         }
0203 
0204         range_value_t<Rng> val_;
0205     };
0206 
0207     template<typename Rng>
0208     RANGES_INLINE_VAR constexpr bool enable_borrowed_range<intersperse_view<Rng>> = //
0209         enable_borrowed_range<Rng>;
0210 
0211 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0212     template<typename Rng>
0213     intersperse_view(Rng &&, range_value_t<Rng>)
0214         -> intersperse_view<views::all_t<Rng>>;
0215 #endif
0216 
0217     namespace views
0218     {
0219         struct intersperse_base_fn
0220         {
0221             template(typename Rng)(
0222                 requires viewable_range<Rng> AND input_range<Rng> AND
0223                     convertible_to<range_reference_t<Rng>, range_value_t<Rng>> AND
0224                         semiregular<range_value_t<Rng>>)
0225             constexpr intersperse_view<all_t<Rng>> //
0226             operator()(Rng && rng, range_value_t<Rng> val) const
0227             {
0228                 return {all(static_cast<Rng &&>(rng)), std::move(val)};
0229             }
0230         };
0231 
0232         struct intersperse_fn : intersperse_base_fn
0233         {
0234             using intersperse_base_fn::operator();
0235 
0236             template(typename T)(
0237                 requires copyable<T>)
0238             constexpr auto operator()(T t) const
0239             {
0240                 return make_view_closure(bind_back(intersperse_base_fn{}, std::move(t)));
0241             }
0242         };
0243 
0244         /// \relates intersperse_fn
0245         /// \ingroup group-views
0246         RANGES_INLINE_VARIABLE(intersperse_fn, intersperse)
0247     } // namespace views
0248 } // namespace ranges
0249 
0250 #include <range/v3/detail/epilogue.hpp>
0251 #include <range/v3/detail/satisfy_boost_range.hpp>
0252 RANGES_SATISFY_BOOST_RANGE(::ranges::intersperse_view)
0253 
0254 #endif