14#ifndef RANGES_V3_VIEW_SPLIT_HPP
15#define RANGES_V3_VIEW_SPLIT_HPP
30#include <range/v3/utility/static_const.hpp>
36#include <range/v3/detail/prologue.hpp>
47#if defined(_MSC_VER) && !defined(__clang__) && \
48 RANGES_CXX_VER <= RANGES_CXX_STD_17
49 template<typename R, std::size_t Sz = static_cast<std::size_t>(R::size())>
50 constexpr bool _is_tiny_range_(R
const *)
noexcept
52 return R::size() <= 1u;
54 constexpr bool _is_tiny_range_(
void const*)
noexcept
61 CPP_concept tiny_range =
63 detail::_is_tiny_range_(
static_cast<std::add_pointer_t<R>
>(
nullptr));
68 concept (tiny_range_)(R),
70 std::integral_constant<
decltype(R::size()), R::size()>> AND
76 CPP_concept tiny_range =
78 CPP_concept_ref(detail::tiny_range_, std::remove_reference_t<R>);
83 template<
typename V,
typename Pattern>
85 requires input_range<V> && forward_range<Pattern> && view_<V> && view_<
86 Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>,
88 (forward_range<V> || detail::tiny_range<Pattern>)
97 static decltype(
auto) current_(T & t)
noexcept
103 template<
typename It>
107 It & current_(ignore_t)
noexcept
111 It
const & current_(ignore_t)
const noexcept
118 struct here_or_there_
125 struct here_or_there_<true>
127 template<
typename It>
131 template<
typename It>
134 template<
typename JoinView,
bool Const>
135 struct split_outer_iterator;
137 template<
typename JoinView,
bool Const>
138 struct split_inner_iterator;
140 template<
typename V,
typename Pattern,
bool Const>
141 struct split_inner_iterator<split_view<V, Pattern>, Const>
144 using Outer = split_outer_iterator<split_view<V, Pattern>, Const>;
145 using Base = meta::const_if_c<Const, V>;
146 using BaseIterCategory =
147 typename std::iterator_traits<iterator_t<Base>>::iterator_category;
149 bool incremented_ =
false;
150 constexpr decltype(
auto) current_()
noexcept
152 return i_.current_();
154 constexpr decltype(
auto) current_()
const noexcept
156 return i_.current_();
158 constexpr bool done_()
const
160 auto cur = current_();
161 auto last = ranges::end(i_.parent_->base_);
164 auto pcur = ranges::begin(i_.parent_->pattern_);
165 auto pend = ranges::end(i_.parent_->pattern_);
174 }
while(++cur != last);
177#if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
178 constexpr void pre_inc(std::true_type)
182 constexpr void pre_inc(std::false_type)
184 if(Pattern::size() != 0)
187 constexpr split_inner_iterator post_inc(std::true_type)
190 pre_inc(std::true_type{});
193 constexpr void post_inc(std::false_type)
195 pre_inc(std::false_type{});
199 using iterator_concept =
typename Outer::iterator_concept;
200 using iterator_category =
202 derived_from<BaseIterCategory, std::forward_iterator_tag>,
203 std::forward_iterator_tag,
204 std::input_iterator_tag>;
205 using value_type = range_value_t<Base>;
206 using difference_type = range_difference_t<Base>;
207 using reference = range_reference_t<Base>;
208 using pointer = iter_pointer_t<iterator_t<Base>>;
210 split_inner_iterator() =
default;
212 constexpr explicit split_inner_iterator(Outer i)
216 constexpr decltype(
auto)
operator*()
const
221 constexpr split_inner_iterator & operator++()
224#if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
225 if constexpr(!forward_range<Base>)
226 if constexpr(Pattern::size() == 0)
235 constexpr decltype(
auto)
operator++(
int)
237#if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
238 if constexpr(forward_range<V>)
252 friend constexpr auto operator==(split_inner_iterator
const & x,
253 split_inner_iterator
const & y)
254 -> CPP_broken_friend_ret(
bool)(
255 requires forward_range<Base>)
257 return x.i_.curr_ == y.i_.curr_;
260 friend constexpr auto operator!=(split_inner_iterator
const & x,
261 split_inner_iterator
const & y)
262 -> CPP_broken_friend_ret(
bool)(
263 requires forward_range<Base>)
265 return x.i_.curr_ != y.i_.curr_;
267#ifdef RANGES_WORKAROUND_MSVC_756601
268 template<
typename =
void>
270 friend constexpr bool operator==(split_inner_iterator
const & x,
275#ifdef RANGES_WORKAROUND_MSVC_756601
276 template<
typename =
void>
278 friend constexpr bool operator==(default_sentinel_t,
279 split_inner_iterator
const & x)
283#ifdef RANGES_WORKAROUND_MSVC_756601
284 template<
typename =
void>
286 friend constexpr bool operator!=(split_inner_iterator
const & x,
291#ifdef RANGES_WORKAROUND_MSVC_756601
292 template<
typename =
void>
294 friend constexpr bool operator!=(default_sentinel_t,
295 split_inner_iterator
const & x)
299#ifdef RANGES_WORKAROUND_MSVC_756601
300 template<
typename =
void>
302 friend constexpr decltype(
auto) iter_move(
303 split_inner_iterator
const &
304 i)
noexcept(
noexcept(ranges::iter_move(i.current_())))
306 return ranges::iter_move(i.current_());
309 friend constexpr auto iter_swap(
310 split_inner_iterator
const & x,
311 split_inner_iterator
const &
312 y)
noexcept(
noexcept(ranges::iter_swap(x.current_(), y.current_())))
313 -> CPP_broken_friend_ret(
void)(
314 requires indirectly_swappable<iterator_t<Base>>)
316 ranges::iter_swap(x.current_(), y.current_());
320 template<
typename It>
321 using split_outer_iterator_base =
324 template<
typename JoinView,
bool Const>
325 struct split_outer_iterator;
327 template<
typename V,
typename Pattern,
bool Const>
328 struct split_outer_iterator<split_view<V, Pattern>, Const>
329 : split_outer_iterator_base<iterator_t<meta::const_if_c<Const, V>>>
332 friend struct split_inner_iterator<split_view<V, Pattern>, Const>;
333 using Parent = meta::const_if_c<Const, split_view<V, Pattern>>;
334 using Base = meta::const_if_c<Const, V>;
335 using Current = split_outer_iterator_base<iterator_t<Base>>;
337 Parent * parent_ =
nullptr;
338 constexpr decltype(
auto) current_()
noexcept
340 return parent_->current_(*
this);
342 constexpr decltype(
auto) current_()
const noexcept
344 return parent_->current_(*
this);
346 constexpr decltype(
auto) base_()
const noexcept
348 return (parent_->base_);
350#if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
351 constexpr split_outer_iterator post_inc(std::true_type)
357 constexpr void post_inc(std::false_type)
364 using iterator_concept =
366 std::input_iterator_tag>;
367 using iterator_category = std::input_iterator_tag;
368 struct value_type : view_interface<value_type>
371 split_outer_iterator i_ = split_outer_iterator();
374 value_type() =
default;
375 constexpr explicit value_type(split_outer_iterator i)
378 constexpr split_inner_iterator<split_view<V, Pattern>, Const> begin()
381 return split_inner_iterator<split_view<V, Pattern>, Const>(i_);
383 constexpr default_sentinel_t end()
const
385 return default_sentinel;
388 using difference_type = range_difference_t<Base>;
389 using reference = value_type;
390 using pointer = value_type *;
392 split_outer_iterator() =
default;
395 constexpr explicit CPP_ctor(split_outer_iterator)(Parent * parent)(
396 requires (!forward_range<Base>))
401 constexpr CPP_ctor(split_outer_iterator)(Parent * parent,
402 iterator_t<Base> current)(
403 requires forward_range<Base>)
404 : Current{std::move(current)}
408 template(
bool Other)(
409 requires Const AND CPP_NOT(Other) AND
410 convertible_to<iterator_t<V>, iterator_t<Base>>)
411 constexpr split_outer_iterator(
412 split_outer_iterator<split_view<V, Pattern>, Other> i)
413 : Current{std::move(i.curr_)}
419 return value_type{*
this};
422 constexpr split_outer_iterator & operator++()
424 auto & current = current_();
425 const auto last = ranges::end(base_());
428 auto const pbegin = ranges::begin(parent_->pattern_);
429 auto const pend = ranges::end(parent_->pattern_);
435 const auto ret = ranges::mismatch(current, last, pbegin, pend);
441 }
while(++current != last);
445 constexpr decltype(
auto)
operator++(
int)
447#if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
448 if constexpr(forward_range<Base>)
457 return post_inc(
meta::bool_<forward_range<Base>>{});
462 friend constexpr auto operator==(split_outer_iterator
const & x,
463 split_outer_iterator
const & y)
464 -> CPP_broken_friend_ret(
bool)(
465 requires forward_range<Base>)
467 return x.curr_ == y.curr_;
470 friend constexpr auto operator!=(split_outer_iterator
const & x,
471 split_outer_iterator
const & y)
472 -> CPP_broken_friend_ret(
bool)(
473 requires forward_range<Base>)
475 return x.curr_ != y.curr_;
477#ifdef RANGES_WORKAROUND_MSVC_756601
478 template<
typename =
void>
480 friend constexpr bool operator==(split_outer_iterator
const & x,
483 return x.current_() == ranges::end(x.base_());
485#ifdef RANGES_WORKAROUND_MSVC_756601
486 template<
typename =
void>
488 friend constexpr bool operator==(default_sentinel_t,
489 split_outer_iterator
const & x)
491 return x.current_() == ranges::end(x.base_());
493#ifdef RANGES_WORKAROUND_MSVC_756601
494 template<
typename =
void>
496 friend constexpr bool operator!=(split_outer_iterator
const & x,
499 return x.current_() != ranges::end(x.base_());
501#ifdef RANGES_WORKAROUND_MSVC_756601
502 template<
typename =
void>
504 friend constexpr bool operator!=(default_sentinel_t,
505 split_outer_iterator
const & x)
507 return x.current_() != ranges::end(x.base_());
513 template<
typename V,
typename Pattern>
515 requires input_range<V> && forward_range<Pattern> && view_<V> && view_<
516 Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>,
518 (forward_range<V> || detail::tiny_range<Pattern>)
522 , private detail::split_view_base<
iterator_t<V>>
525 template<
typename,
bool>
526 friend struct detail::split_outer_iterator;
527 template<
typename,
bool>
528 friend struct detail::split_inner_iterator;
531 Pattern pattern_ = Pattern();
533 using outer_iterator = detail::split_outer_iterator<split_view, Const>;
535#if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
536 outer_iterator<simple_view<V>()> begin_(std::true_type)
538 return outer_iterator<simple_view<V>()>{
this, ranges::begin(base_)};
540 outer_iterator<false> begin_(std::false_type)
542 this->curr_ = ranges::begin(base_);
543 return outer_iterator<false>{
this};
546 outer_iterator<simple_view<V>()> end_(std::true_type)
const
548 return outer_iterator<true>{
this, ranges::end(base_)};
552 return default_sentinel;
561 , pattern_((Pattern &&) pattern)
565 constexpr CPP_ctor(
split_view)(V base, range_value_t<V> e)(
566 requires constructible_from<Pattern, range_value_t<V>>)
567 : base_(std::move(base))
571 constexpr V base()
const
576 constexpr outer_iterator<forward_range<V> && simple_view<V>()> begin()
578#if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
580 return outer_iterator<simple_view<V>()>{
this, ranges::begin(base_)};
583 this->curr_ = ranges::begin(base_);
584 return outer_iterator<false>{
this};
591 constexpr auto begin()
const
592 -> CPP_ret(outer_iterator<true>)(
595 return {
this, ranges::begin(base_)};
599 -> CPP_ret(outer_iterator<simple_view<V>()>)(
602 return outer_iterator<simple_view<V>()>{
this, ranges::end(base_)};
604 constexpr auto end()
const
606#if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
609 return outer_iterator<true>{
this, ranges::end(base_)};
611 return default_sentinel;
619#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
620 template(
typename R,
typename P)(
626 ->split_view<views::all_t<R>, views::all_t<P>>;
628 template(
typename R)(
638 template(
typename Rng)(
641 range_value_t<Rng>
const *,
644 operator()(Rng && rng, range_value_t<Rng> val)
const
646 return {all(
static_cast<Rng &&
>(rng)), single(std::move(val))};
649 template(
typename Rng,
typename Pattern)(
657 constexpr split_view<all_t<Rng>, all_t<Pattern>>
658 operator()(Rng && rng, Pattern && pattern)
const
660 return {all((Rng &&) rng), all((Pattern &&) pattern)};
666 using split_base_fn::operator();
669 constexpr auto operator()(T t)
const
671 return make_view_closure(bind_back(
split_base_fn{}, std::move(t)));
677 RANGES_INLINE_VARIABLE(
split_fn, split)
684 using ranges::views::split;
686 template(
typename Rng,
typename Pattern)(
687 requires input_range<Rng> AND forward_range<Pattern> AND view_<Rng> AND
689 indirectly_comparable<
693 (forward_range<Rng> || ranges::detail::tiny_range<Pattern>))
701#include <range/v3/detail/epilogue.hpp>
703#include <range/v3/detail/satisfy_boost_range.hpp>
The common_range concept.
The forward_range concept.
The indirectly_comparable concept.
The viewable_range concept.
#define CPP_broken_friend_member
INTERNAL ONLY.
Definition concepts.hpp:447
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition meta.hpp:168
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1148
Point operator*(double s, const Point &a)
Multiply point by scalar.
Definition shapes.h:250
Definition default_sentinel.hpp:26
Definition comparisons.hpp:28
Definition interface.hpp:129