split.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_SPLIT_HPP
  14. #define RANGES_V3_VIEW_SPLIT_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/algorithm/mismatch.hpp>
  20. #include <range/v3/functional/bind_back.hpp>
  21. #include <range/v3/iterator/default_sentinel.hpp>
  22. #include <range/v3/range/access.hpp>
  23. #include <range/v3/range/concepts.hpp>
  24. #include <range/v3/range/traits.hpp>
  25. #include <range/v3/utility/static_const.hpp>
  26. #include <range/v3/view/all.hpp>
  27. #include <range/v3/view/interface.hpp>
  28. #include <range/v3/view/single.hpp>
  29. #include <range/v3/view/view.hpp>
  30. #include <range/v3/detail/prologue.hpp>
  31. namespace ranges
  32. {
  33. /// \addtogroup group-views
  34. /// @{
  35. /// \cond
  36. namespace detail
  37. {
  38. // clang-format off
  39. #if defined(_MSC_VER) && !defined(__clang__) && \
  40. RANGES_CXX_VER <= RANGES_CXX_STD_17
  41. template<typename R, std::size_t Sz = static_cast<std::size_t>(R::size())>
  42. constexpr bool _is_tiny_range_(R const *) noexcept
  43. {
  44. return R::size() <= 1u;
  45. }
  46. constexpr bool _is_tiny_range_(void const*) noexcept
  47. {
  48. return false;
  49. }
  50. /// \concept tiny_range
  51. /// \brief The \c tiny_range concept
  52. template<typename R>
  53. CPP_concept tiny_range =
  54. sized_range<R> &&
  55. detail::_is_tiny_range_(static_cast<std::add_pointer_t<R>>(nullptr));
  56. #else // ^^^^ workaround / no workaround vvvv
  57. /// \concept tiny_range_
  58. /// \brief The \c tiny_range_ concept
  59. template(typename R)(
  60. concept (tiny_range_)(R),
  61. ranges::type<
  62. std::integral_constant<decltype(R::size()), R::size()>> AND
  63. (R::size() <= 1)
  64. );
  65. /// \concept tiny_range
  66. /// \brief The \c tiny_range concept
  67. template<typename R>
  68. CPP_concept tiny_range =
  69. sized_range<R> &&
  70. CPP_concept_ref(detail::tiny_range_, std::remove_reference_t<R>);
  71. #endif
  72. // clang-format on
  73. } // namespace detail
  74. template<typename V, typename Pattern>
  75. #if CPP_CXX_CONCEPTS
  76. requires input_range<V> && forward_range<Pattern> && view_<V> && view_<
  77. Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>,
  78. ranges::equal_to> &&
  79. (forward_range<V> || detail::tiny_range<Pattern>)
  80. #endif
  81. struct split_view;
  82. namespace detail
  83. {
  84. struct there
  85. {
  86. template<typename T>
  87. static decltype(auto) current_(T & t) noexcept
  88. {
  89. return (t.curr_);
  90. }
  91. };
  92. template<typename It>
  93. struct here
  94. {
  95. It curr_ = It();
  96. It & current_(ignore_t) noexcept
  97. {
  98. return curr_;
  99. }
  100. It const & current_(ignore_t) const noexcept
  101. {
  102. return curr_;
  103. }
  104. };
  105. template<bool>
  106. struct here_or_there_
  107. {
  108. template<typename>
  109. using invoke = there;
  110. };
  111. template<>
  112. struct here_or_there_<true>
  113. {
  114. template<typename It>
  115. using invoke = here<It>;
  116. };
  117. template<typename It>
  118. using split_view_base = meta::invoke<here_or_there_<!forward_iterator<It>>, It>;
  119. template<typename JoinView, bool Const>
  120. struct split_outer_iterator;
  121. template<typename JoinView, bool Const>
  122. struct split_inner_iterator;
  123. template<typename V, typename Pattern, bool Const>
  124. struct split_inner_iterator<split_view<V, Pattern>, Const>
  125. {
  126. private:
  127. using Outer = split_outer_iterator<split_view<V, Pattern>, Const>;
  128. using Base = meta::const_if_c<Const, V>;
  129. using BaseIterCategory =
  130. typename std::iterator_traits<iterator_t<Base>>::iterator_category;
  131. Outer i_ = Outer();
  132. bool incremented_ = false;
  133. constexpr decltype(auto) current_() noexcept
  134. {
  135. return i_.current_();
  136. }
  137. constexpr decltype(auto) current_() const noexcept
  138. {
  139. return i_.current_();
  140. }
  141. constexpr bool done_() const
  142. {
  143. auto cur = current_();
  144. auto last = ranges::end(i_.parent_->base_);
  145. if(cur == last)
  146. return true;
  147. auto pcur = ranges::begin(i_.parent_->pattern_);
  148. auto pend = ranges::end(i_.parent_->pattern_);
  149. if(pcur == pend)
  150. return incremented_;
  151. do
  152. {
  153. if(*cur != *pcur)
  154. return false;
  155. if(++pcur == pend)
  156. return true;
  157. } while(++cur != last);
  158. return false;
  159. }
  160. #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
  161. constexpr void pre_inc(std::true_type) // Forward
  162. {
  163. ++current_();
  164. }
  165. constexpr void pre_inc(std::false_type) // Input
  166. {
  167. if(Pattern::size() != 0)
  168. ++current_();
  169. }
  170. constexpr split_inner_iterator post_inc(std::true_type) // Forward
  171. {
  172. auto tmp = *this;
  173. pre_inc(std::true_type{});
  174. return tmp;
  175. }
  176. constexpr void post_inc(std::false_type) // Input
  177. {
  178. pre_inc(std::false_type{});
  179. }
  180. #endif
  181. public:
  182. using iterator_concept = typename Outer::iterator_concept;
  183. using iterator_category =
  184. meta::conditional_t<
  185. derived_from<BaseIterCategory, std::forward_iterator_tag>,
  186. std::forward_iterator_tag,
  187. std::input_iterator_tag>;
  188. using value_type = range_value_t<Base>;
  189. using difference_type = range_difference_t<Base>;
  190. using reference = range_reference_t<Base>; // Not to spec
  191. using pointer = iter_pointer_t<iterator_t<Base>>; // Not to spec
  192. split_inner_iterator() = default;
  193. constexpr explicit split_inner_iterator(Outer i)
  194. : i_(std::move(i))
  195. {}
  196. constexpr decltype(auto) operator*() const
  197. {
  198. return *current_();
  199. }
  200. constexpr split_inner_iterator & operator++()
  201. {
  202. incremented_ = true;
  203. #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
  204. if constexpr(!forward_range<Base>)
  205. if constexpr(Pattern::size() == 0)
  206. return *this;
  207. ++current_();
  208. #else
  209. pre_inc(meta::bool_<forward_range<Base>>{});
  210. #endif
  211. return *this;
  212. }
  213. constexpr decltype(auto) operator++(int)
  214. {
  215. #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
  216. if constexpr(forward_range<V>)
  217. {
  218. auto tmp = *this;
  219. ++*this;
  220. return tmp;
  221. }
  222. else
  223. ++*this;
  224. #else
  225. return post_inc(meta::bool_<forward_range<V>>{});
  226. #endif
  227. }
  228. CPP_broken_friend_member
  229. friend constexpr auto operator==(split_inner_iterator const & x,
  230. split_inner_iterator const & y)
  231. -> CPP_broken_friend_ret(bool)(
  232. requires forward_range<Base>)
  233. {
  234. return x.i_.curr_ == y.i_.curr_;
  235. }
  236. CPP_broken_friend_member
  237. friend constexpr auto operator!=(split_inner_iterator const & x,
  238. split_inner_iterator const & y)
  239. -> CPP_broken_friend_ret(bool)(
  240. requires forward_range<Base>)
  241. {
  242. return x.i_.curr_ != y.i_.curr_;
  243. }
  244. #ifdef RANGES_WORKAROUND_MSVC_756601
  245. template<typename = void>
  246. #endif // RANGES_WORKAROUND_MSVC_756601
  247. friend constexpr bool operator==(split_inner_iterator const & x,
  248. default_sentinel_t)
  249. {
  250. return x.done_();
  251. }
  252. #ifdef RANGES_WORKAROUND_MSVC_756601
  253. template<typename = void>
  254. #endif // RANGES_WORKAROUND_MSVC_756601
  255. friend constexpr bool operator==(default_sentinel_t,
  256. split_inner_iterator const & x)
  257. {
  258. return x.done_();
  259. }
  260. #ifdef RANGES_WORKAROUND_MSVC_756601
  261. template<typename = void>
  262. #endif // RANGES_WORKAROUND_MSVC_756601
  263. friend constexpr bool operator!=(split_inner_iterator const & x,
  264. default_sentinel_t)
  265. {
  266. return !x.done_();
  267. }
  268. #ifdef RANGES_WORKAROUND_MSVC_756601
  269. template<typename = void>
  270. #endif // RANGES_WORKAROUND_MSVC_756601
  271. friend constexpr bool operator!=(default_sentinel_t,
  272. split_inner_iterator const & x)
  273. {
  274. return !x.done_();
  275. }
  276. #ifdef RANGES_WORKAROUND_MSVC_756601
  277. template<typename = void>
  278. #endif // RANGES_WORKAROUND_MSVC_756601
  279. friend constexpr decltype(auto) iter_move(
  280. split_inner_iterator const &
  281. i) noexcept(noexcept(ranges::iter_move(i.current_())))
  282. {
  283. return ranges::iter_move(i.current_());
  284. }
  285. CPP_broken_friend_member
  286. friend constexpr auto iter_swap(
  287. split_inner_iterator const & x,
  288. split_inner_iterator const &
  289. y) noexcept(noexcept(ranges::iter_swap(x.current_(), y.current_())))
  290. -> CPP_broken_friend_ret(void)(
  291. requires indirectly_swappable<iterator_t<Base>>)
  292. {
  293. ranges::iter_swap(x.current_(), y.current_());
  294. }
  295. };
  296. template<typename It>
  297. using split_outer_iterator_base =
  298. meta::invoke<here_or_there_<forward_iterator<It>>, It>;
  299. template<typename JoinView, bool Const>
  300. struct split_outer_iterator;
  301. template<typename V, typename Pattern, bool Const>
  302. struct split_outer_iterator<split_view<V, Pattern>, Const>
  303. : split_outer_iterator_base<iterator_t<meta::const_if_c<Const, V>>>
  304. {
  305. private:
  306. friend struct split_inner_iterator<split_view<V, Pattern>, Const>;
  307. using Parent = meta::const_if_c<Const, split_view<V, Pattern>>;
  308. using Base = meta::const_if_c<Const, V>;
  309. using Current = split_outer_iterator_base<iterator_t<Base>>;
  310. Parent * parent_ = nullptr;
  311. constexpr decltype(auto) current_() noexcept
  312. {
  313. return parent_->current_(*this);
  314. }
  315. constexpr decltype(auto) current_() const noexcept
  316. {
  317. return parent_->current_(*this);
  318. }
  319. constexpr decltype(auto) base_() const noexcept
  320. {
  321. return (parent_->base_);
  322. }
  323. #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
  324. constexpr split_outer_iterator post_inc(std::true_type) // Forward
  325. {
  326. auto tmp = *this;
  327. ++*this;
  328. return tmp;
  329. }
  330. constexpr void post_inc(std::false_type) // Input
  331. {
  332. ++*this;
  333. }
  334. #endif
  335. public:
  336. using iterator_concept =
  337. meta::conditional_t<forward_range<Base>, std::forward_iterator_tag,
  338. std::input_iterator_tag>;
  339. using iterator_category = std::input_iterator_tag;
  340. struct value_type : view_interface<value_type>
  341. {
  342. private:
  343. split_outer_iterator i_ = split_outer_iterator();
  344. public:
  345. value_type() = default;
  346. constexpr explicit value_type(split_outer_iterator i)
  347. : i_(std::move(i))
  348. {}
  349. constexpr split_inner_iterator<split_view<V, Pattern>, Const> begin()
  350. const
  351. {
  352. return split_inner_iterator<split_view<V, Pattern>, Const>(i_);
  353. }
  354. constexpr default_sentinel_t end() const
  355. {
  356. return default_sentinel;
  357. }
  358. };
  359. using difference_type = range_difference_t<Base>;
  360. using reference = value_type; // Not to spec
  361. using pointer = value_type *; // Not to spec
  362. split_outer_iterator() = default;
  363. CPP_member
  364. constexpr explicit CPP_ctor(split_outer_iterator)(Parent * parent)(
  365. requires (!forward_range<Base>))
  366. : parent_(parent)
  367. {}
  368. CPP_member
  369. constexpr CPP_ctor(split_outer_iterator)(Parent * parent,
  370. iterator_t<Base> current)(
  371. requires forward_range<Base>)
  372. : Current{std::move(current)}
  373. , parent_(parent)
  374. {}
  375. template(bool Other)(
  376. requires Const AND CPP_NOT(Other) AND
  377. convertible_to<iterator_t<V>, iterator_t<Base>>)
  378. constexpr split_outer_iterator(
  379. split_outer_iterator<split_view<V, Pattern>, Other> i)
  380. : Current{std::move(i.curr_)}
  381. , parent_(i.parent_)
  382. {}
  383. constexpr value_type operator*() const
  384. {
  385. return value_type{*this};
  386. }
  387. constexpr split_outer_iterator & operator++()
  388. {
  389. auto & current = current_();
  390. const auto last = ranges::end(base_());
  391. if(current == last)
  392. return *this;
  393. auto const pbegin = ranges::begin(parent_->pattern_);
  394. auto const pend = ranges::end(parent_->pattern_);
  395. if(pbegin == pend)
  396. ++current;
  397. else
  398. do
  399. {
  400. const auto ret = ranges::mismatch(current, last, pbegin, pend);
  401. if(ret.in2 == pend)
  402. {
  403. current = ret.in1; // The pattern matched; skip it
  404. break;
  405. }
  406. } while(++current != last);
  407. return *this;
  408. }
  409. constexpr decltype(auto) operator++(int)
  410. {
  411. #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
  412. if constexpr(forward_range<Base>)
  413. {
  414. auto tmp = *this;
  415. ++*this;
  416. return tmp;
  417. }
  418. else
  419. ++*this;
  420. #else
  421. return post_inc(meta::bool_<forward_range<Base>>{});
  422. #endif
  423. }
  424. CPP_broken_friend_member
  425. friend constexpr auto operator==(split_outer_iterator const & x,
  426. split_outer_iterator const & y)
  427. -> CPP_broken_friend_ret(bool)(
  428. requires forward_range<Base>)
  429. {
  430. return x.curr_ == y.curr_;
  431. }
  432. CPP_broken_friend_member
  433. friend constexpr auto operator!=(split_outer_iterator const & x,
  434. split_outer_iterator const & y)
  435. -> CPP_broken_friend_ret(bool)(
  436. requires forward_range<Base>)
  437. {
  438. return x.curr_ != y.curr_;
  439. }
  440. #ifdef RANGES_WORKAROUND_MSVC_756601
  441. template<typename = void>
  442. #endif // RANGES_WORKAROUND_MSVC_756601
  443. friend constexpr bool operator==(split_outer_iterator const & x,
  444. default_sentinel_t)
  445. {
  446. return x.current_() == ranges::end(x.base_());
  447. }
  448. #ifdef RANGES_WORKAROUND_MSVC_756601
  449. template<typename = void>
  450. #endif // RANGES_WORKAROUND_MSVC_756601
  451. friend constexpr bool operator==(default_sentinel_t,
  452. split_outer_iterator const & x)
  453. {
  454. return x.current_() == ranges::end(x.base_());
  455. }
  456. #ifdef RANGES_WORKAROUND_MSVC_756601
  457. template<typename = void>
  458. #endif // RANGES_WORKAROUND_MSVC_756601
  459. friend constexpr bool operator!=(split_outer_iterator const & x,
  460. default_sentinel_t)
  461. {
  462. return x.current_() != ranges::end(x.base_());
  463. }
  464. #ifdef RANGES_WORKAROUND_MSVC_756601
  465. template<typename = void>
  466. #endif // RANGES_WORKAROUND_MSVC_756601
  467. friend constexpr bool operator!=(default_sentinel_t,
  468. split_outer_iterator const & x)
  469. {
  470. return x.current_() != ranges::end(x.base_());
  471. }
  472. };
  473. } // namespace detail
  474. /// \endcond
  475. template<typename V, typename Pattern>
  476. #if CPP_CXX_CONCEPTS
  477. requires input_range<V> && forward_range<Pattern> && view_<V> && view_<
  478. Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>,
  479. ranges::equal_to> &&
  480. (forward_range<V> || detail::tiny_range<Pattern>)
  481. #endif
  482. struct RANGES_EMPTY_BASES split_view
  483. : view_interface<split_view<V, Pattern>, is_finite<V>::value ? finite : unknown>
  484. , private detail::split_view_base<iterator_t<V>>
  485. {
  486. private:
  487. template<typename, bool>
  488. friend struct detail::split_outer_iterator;
  489. template<typename, bool>
  490. friend struct detail::split_inner_iterator;
  491. V base_ = V();
  492. Pattern pattern_ = Pattern();
  493. template<bool Const>
  494. using outer_iterator = detail::split_outer_iterator<split_view, Const>;
  495. #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
  496. outer_iterator<simple_view<V>()> begin_(std::true_type)
  497. {
  498. return outer_iterator<simple_view<V>()>{this, ranges::begin(base_)};
  499. }
  500. outer_iterator<false> begin_(std::false_type)
  501. {
  502. this->curr_ = ranges::begin(base_);
  503. return outer_iterator<false>{this};
  504. }
  505. outer_iterator<simple_view<V>()> end_(std::true_type) const
  506. {
  507. return outer_iterator<true>{this, ranges::end(base_)};
  508. }
  509. default_sentinel_t end_(std::false_type) const
  510. {
  511. return default_sentinel;
  512. }
  513. #endif
  514. public:
  515. split_view() = default;
  516. constexpr split_view(V base, Pattern pattern)
  517. : base_((V &&) base)
  518. , pattern_((Pattern &&) pattern)
  519. {}
  520. CPP_member
  521. constexpr CPP_ctor(split_view)(V base, range_value_t<V> e)(
  522. requires constructible_from<Pattern, range_value_t<V>>)
  523. : base_(std::move(base))
  524. , pattern_(e)
  525. {}
  526. constexpr V base() const
  527. {
  528. return base_;
  529. }
  530. constexpr outer_iterator<forward_range<V> && simple_view<V>()> begin()
  531. {
  532. #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
  533. if constexpr(forward_range<V>)
  534. return outer_iterator<simple_view<V>()>{this, ranges::begin(base_)};
  535. else
  536. {
  537. this->curr_ = ranges::begin(base_);
  538. return outer_iterator<false>{this};
  539. }
  540. #else
  541. return begin_(meta::bool_<forward_range<V>>{});
  542. #endif
  543. }
  544. CPP_member
  545. constexpr auto begin() const //
  546. -> CPP_ret(outer_iterator<true>)(
  547. requires forward_range<V> && forward_range<const V>)
  548. {
  549. return {this, ranges::begin(base_)};
  550. }
  551. CPP_member
  552. constexpr auto end() //
  553. -> CPP_ret(outer_iterator<simple_view<V>()>)(
  554. requires forward_range<V> && common_range<V>)
  555. {
  556. return outer_iterator<simple_view<V>()>{this, ranges::end(base_)};
  557. }
  558. constexpr auto end() const
  559. {
  560. #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
  561. if constexpr(forward_range<V> && forward_range<const V> &&
  562. common_range<const V>)
  563. return outer_iterator<true>{this, ranges::end(base_)};
  564. else
  565. return default_sentinel;
  566. #else
  567. return end_(meta::bool_ < forward_range<V> && forward_range<const V> &&
  568. common_range<const V> > {});
  569. #endif
  570. }
  571. };
  572. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  573. template(typename R, typename P)(
  574. requires input_range<R> AND forward_range<P> AND viewable_range<R> AND
  575. viewable_range<P> AND
  576. indirectly_comparable<iterator_t<R>, iterator_t<P>, ranges::equal_to> AND
  577. (forward_range<R> || detail::tiny_range<P>)) //
  578. split_view(R &&, P &&)
  579. ->split_view<views::all_t<R>, views::all_t<P>>;
  580. template(typename R)(
  581. requires input_range<R>)
  582. split_view(R &&, range_value_t<R>)
  583. ->split_view<views::all_t<R>, single_view<range_value_t<R>>>;
  584. #endif
  585. namespace views
  586. {
  587. struct split_base_fn
  588. {
  589. template(typename Rng)(
  590. requires viewable_range<Rng> AND input_range<Rng> AND
  591. indirectly_comparable<iterator_t<Rng>,
  592. range_value_t<Rng> const *,
  593. ranges::equal_to>)
  594. constexpr split_view<all_t<Rng>, single_view<range_value_t<Rng>>> //
  595. operator()(Rng && rng, range_value_t<Rng> val) const
  596. {
  597. return {all(static_cast<Rng &&>(rng)), single(std::move(val))};
  598. }
  599. template(typename Rng, typename Pattern)(
  600. requires viewable_range<Rng> AND input_range<Rng> AND
  601. viewable_range<Pattern> AND forward_range<Pattern> AND
  602. indirectly_comparable<
  603. iterator_t<Rng>,
  604. iterator_t<Pattern>,
  605. ranges::equal_to> AND
  606. (forward_range<Rng> || detail::tiny_range<Pattern>)) //
  607. constexpr split_view<all_t<Rng>, all_t<Pattern>> //
  608. operator()(Rng && rng, Pattern && pattern) const
  609. {
  610. return {all((Rng &&) rng), all((Pattern &&) pattern)};
  611. }
  612. };
  613. struct split_fn : split_base_fn
  614. {
  615. using split_base_fn::operator();
  616. template<typename T>
  617. constexpr auto operator()(T t) const
  618. {
  619. return make_view_closure(bind_back(split_base_fn{}, std::move(t)));
  620. }
  621. };
  622. /// \relates split_fn
  623. /// \ingroup group-views
  624. RANGES_INLINE_VARIABLE(split_fn, split)
  625. } // namespace views
  626. namespace cpp20
  627. {
  628. namespace views
  629. {
  630. using ranges::views::split;
  631. }
  632. template(typename Rng, typename Pattern)(
  633. requires input_range<Rng> AND forward_range<Pattern> AND view_<Rng> AND
  634. view_<Pattern> AND
  635. indirectly_comparable<
  636. iterator_t<Rng>,
  637. iterator_t<Pattern>,
  638. ranges::equal_to> AND
  639. (forward_range<Rng> || ranges::detail::tiny_range<Pattern>)) //
  640. using split_view =
  641. ranges::split_view<Rng, Pattern>;
  642. } // namespace cpp20
  643. /// @}
  644. } // namespace ranges
  645. #include <range/v3/detail/epilogue.hpp>
  646. #include <range/v3/detail/satisfy_boost_range.hpp>
  647. RANGES_SATISFY_BOOST_RANGE(::ranges::split_view)
  648. #endif