File indexing completed on 2025-01-18 10:09:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
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
0245
0246 RANGES_INLINE_VARIABLE(intersperse_fn, intersperse)
0247 }
0248 }
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