Back to home page

EIC code displayed by LXR

 
 

    


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

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_SPLIT_HPP
0015 #define RANGES_V3_VIEW_SPLIT_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/algorithm/mismatch.hpp>
0025 #include <range/v3/functional/bind_back.hpp>
0026 #include <range/v3/iterator/default_sentinel.hpp>
0027 #include <range/v3/range/access.hpp>
0028 #include <range/v3/range/concepts.hpp>
0029 #include <range/v3/range/traits.hpp>
0030 #include <range/v3/utility/static_const.hpp>
0031 #include <range/v3/view/all.hpp>
0032 #include <range/v3/view/interface.hpp>
0033 #include <range/v3/view/single.hpp>
0034 #include <range/v3/view/view.hpp>
0035 
0036 #include <range/v3/detail/prologue.hpp>
0037 
0038 namespace ranges
0039 {
0040     /// \addtogroup group-views
0041     /// @{
0042 
0043     /// \cond
0044     namespace detail
0045     {
0046         // clang-format off
0047 #if defined(_MSC_VER) && !defined(__clang__) && \
0048     RANGES_CXX_VER <= RANGES_CXX_STD_17
0049         template<typename R, std::size_t Sz = static_cast<std::size_t>(R::size())>
0050         constexpr bool _is_tiny_range_(R const *) noexcept
0051         {
0052             return R::size() <= 1u;
0053         }
0054         constexpr bool _is_tiny_range_(void const*) noexcept
0055         {
0056             return false;
0057         }
0058         /// \concept tiny_range
0059         /// \brief The \c tiny_range concept
0060         template<typename R>
0061         CPP_concept tiny_range =
0062             sized_range<R> &&
0063             detail::_is_tiny_range_(static_cast<std::add_pointer_t<R>>(nullptr));
0064 #else // ^^^^ workaround / no workaround vvvv
0065         /// \concept tiny_range_
0066         /// \brief The \c tiny_range_ concept
0067         template(typename R)(
0068         concept (tiny_range_)(R),
0069             ranges::type<
0070                 std::integral_constant<decltype(R::size()), R::size()>> AND
0071             (R::size() <= 1)
0072         );
0073         /// \concept tiny_range
0074         /// \brief The \c tiny_range concept
0075         template<typename R>
0076         CPP_concept tiny_range =
0077             sized_range<R> &&
0078             CPP_concept_ref(detail::tiny_range_, std::remove_reference_t<R>);
0079 #endif
0080         // clang-format on
0081     } // namespace detail
0082 
0083     template<typename V, typename Pattern>
0084 #if CPP_CXX_CONCEPTS
0085         requires input_range<V> && forward_range<Pattern> && view_<V> && view_<
0086             Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>,
0087                                               ranges::equal_to> &&
0088         (forward_range<V> || detail::tiny_range<Pattern>)
0089 #endif
0090             struct split_view;
0091 
0092     namespace detail
0093     {
0094         struct there
0095         {
0096             template<typename T>
0097             static decltype(auto) current_(T & t) noexcept
0098             {
0099                 return (t.curr_);
0100             }
0101         };
0102 
0103         template<typename It>
0104         struct here
0105         {
0106             It curr_ = It();
0107             It & current_(ignore_t) noexcept
0108             {
0109                 return curr_;
0110             }
0111             It const & current_(ignore_t) const noexcept
0112             {
0113                 return curr_;
0114             }
0115         };
0116 
0117         template<bool>
0118         struct here_or_there_
0119         {
0120             template<typename>
0121             using invoke = there;
0122         };
0123 
0124         template<>
0125         struct here_or_there_<true>
0126         {
0127             template<typename It>
0128             using invoke = here<It>;
0129         };
0130 
0131         template<typename It>
0132         using split_view_base = meta::invoke<here_or_there_<!forward_iterator<It>>, It>;
0133 
0134         template<typename JoinView, bool Const>
0135         struct split_outer_iterator;
0136 
0137         template<typename JoinView, bool Const>
0138         struct split_inner_iterator;
0139 
0140         template<typename V, typename Pattern, bool Const>
0141         struct split_inner_iterator<split_view<V, Pattern>, Const>
0142         {
0143         private:
0144             using Outer = split_outer_iterator<split_view<V, Pattern>, Const>;
0145             using Base = meta::const_if_c<Const, V>;
0146             using BaseIterCategory =
0147                 typename std::iterator_traits<iterator_t<Base>>::iterator_category;
0148             Outer i_ = Outer();
0149             bool incremented_ = false;
0150             constexpr decltype(auto) current_() noexcept
0151             {
0152                 return i_.current_();
0153             }
0154             constexpr decltype(auto) current_() const noexcept
0155             {
0156                 return i_.current_();
0157             }
0158             constexpr bool done_() const
0159             {
0160                 auto cur = current_();
0161                 auto last = ranges::end(i_.parent_->base_);
0162                 if(cur == last)
0163                     return true;
0164                 auto pcur = ranges::begin(i_.parent_->pattern_);
0165                 auto pend = ranges::end(i_.parent_->pattern_);
0166                 if(pcur == pend)
0167                     return incremented_;
0168                 do
0169                 {
0170                     if(*cur != *pcur)
0171                         return false;
0172                     if(++pcur == pend)
0173                         return true;
0174                 } while(++cur != last);
0175                 return false;
0176             }
0177 #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
0178             constexpr void pre_inc(std::true_type) // Forward
0179             {
0180                 ++current_();
0181             }
0182             constexpr void pre_inc(std::false_type) // Input
0183             {
0184                 if(Pattern::size() != 0)
0185                     ++current_();
0186             }
0187             constexpr split_inner_iterator post_inc(std::true_type) // Forward
0188             {
0189                 auto tmp = *this;
0190                 pre_inc(std::true_type{});
0191                 return tmp;
0192             }
0193             constexpr void post_inc(std::false_type) // Input
0194             {
0195                 pre_inc(std::false_type{});
0196             }
0197 #endif
0198         public:
0199             using iterator_concept = typename Outer::iterator_concept;
0200             using iterator_category =
0201                 meta::conditional_t<
0202                     derived_from<BaseIterCategory, std::forward_iterator_tag>,
0203                     std::forward_iterator_tag,
0204                     std::input_iterator_tag>;
0205             using value_type = range_value_t<Base>;
0206             using difference_type = range_difference_t<Base>;
0207             using reference = range_reference_t<Base>;        // Not to spec
0208             using pointer = iter_pointer_t<iterator_t<Base>>; // Not to spec
0209 
0210             split_inner_iterator() = default;
0211 
0212             constexpr explicit split_inner_iterator(Outer i)
0213               : i_(std::move(i))
0214             {}
0215 
0216             constexpr decltype(auto) operator*() const
0217             {
0218                 return *current_();
0219             }
0220 
0221             constexpr split_inner_iterator & operator++()
0222             {
0223                 incremented_ = true;
0224 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0225                 if constexpr(!forward_range<Base>)
0226                     if constexpr(Pattern::size() == 0)
0227                         return *this;
0228                 ++current_();
0229 #else
0230                 pre_inc(meta::bool_<forward_range<Base>>{});
0231 #endif
0232                 return *this;
0233             }
0234 
0235             constexpr decltype(auto) operator++(int)
0236             {
0237 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0238                 if constexpr(forward_range<V>)
0239                 {
0240                     auto tmp = *this;
0241                     ++*this;
0242                     return tmp;
0243                 }
0244                 else
0245                     ++*this;
0246 #else
0247                 return post_inc(meta::bool_<forward_range<V>>{});
0248 #endif
0249             }
0250 
0251             CPP_broken_friend_member
0252             friend constexpr auto operator==(split_inner_iterator const & x,
0253                                              split_inner_iterator const & y)
0254                 -> CPP_broken_friend_ret(bool)(
0255                     requires forward_range<Base>)
0256             {
0257                 return x.i_.curr_ == y.i_.curr_;
0258             }
0259             CPP_broken_friend_member
0260             friend constexpr auto operator!=(split_inner_iterator const & x,
0261                                              split_inner_iterator const & y)
0262                 -> CPP_broken_friend_ret(bool)(
0263                     requires forward_range<Base>)
0264             {
0265                 return x.i_.curr_ != y.i_.curr_;
0266             }
0267 #ifdef RANGES_WORKAROUND_MSVC_756601
0268             template<typename = void>
0269 #endif // RANGES_WORKAROUND_MSVC_756601
0270             friend constexpr bool operator==(split_inner_iterator const & x,
0271                                              default_sentinel_t)
0272             {
0273                 return x.done_();
0274             }
0275 #ifdef RANGES_WORKAROUND_MSVC_756601
0276             template<typename = void>
0277 #endif // RANGES_WORKAROUND_MSVC_756601
0278             friend constexpr bool operator==(default_sentinel_t,
0279                                              split_inner_iterator const & x)
0280             {
0281                 return x.done_();
0282             }
0283 #ifdef RANGES_WORKAROUND_MSVC_756601
0284             template<typename = void>
0285 #endif // RANGES_WORKAROUND_MSVC_756601
0286             friend constexpr bool operator!=(split_inner_iterator const & x,
0287                                              default_sentinel_t)
0288             {
0289                 return !x.done_();
0290             }
0291 #ifdef RANGES_WORKAROUND_MSVC_756601
0292             template<typename = void>
0293 #endif // RANGES_WORKAROUND_MSVC_756601
0294             friend constexpr bool operator!=(default_sentinel_t,
0295                                              split_inner_iterator const & x)
0296             {
0297                 return !x.done_();
0298             }
0299 #ifdef RANGES_WORKAROUND_MSVC_756601
0300             template<typename = void>
0301 #endif // RANGES_WORKAROUND_MSVC_756601
0302             friend constexpr decltype(auto) iter_move(
0303                 split_inner_iterator const &
0304                     i) noexcept(noexcept(ranges::iter_move(i.current_())))
0305             {
0306                 return ranges::iter_move(i.current_());
0307             }
0308             CPP_broken_friend_member
0309             friend constexpr auto iter_swap(
0310                 split_inner_iterator const & x,
0311                 split_inner_iterator const &
0312                     y) noexcept(noexcept(ranges::iter_swap(x.current_(), y.current_())))
0313                 -> CPP_broken_friend_ret(void)(
0314                     requires indirectly_swappable<iterator_t<Base>>)
0315             {
0316                 ranges::iter_swap(x.current_(), y.current_());
0317             }
0318         };
0319 
0320         template<typename It>
0321         using split_outer_iterator_base =
0322             meta::invoke<here_or_there_<forward_iterator<It>>, It>;
0323 
0324         template<typename JoinView, bool Const>
0325         struct split_outer_iterator;
0326 
0327         template<typename V, typename Pattern, bool Const>
0328         struct split_outer_iterator<split_view<V, Pattern>, Const>
0329           : split_outer_iterator_base<iterator_t<meta::const_if_c<Const, V>>>
0330         {
0331         private:
0332             friend struct split_inner_iterator<split_view<V, Pattern>, Const>;
0333             using Parent = meta::const_if_c<Const, split_view<V, Pattern>>;
0334             using Base = meta::const_if_c<Const, V>;
0335             using Current = split_outer_iterator_base<iterator_t<Base>>;
0336 
0337             Parent * parent_ = nullptr;
0338             constexpr decltype(auto) current_() noexcept
0339             {
0340                 return parent_->current_(*this);
0341             }
0342             constexpr decltype(auto) current_() const noexcept
0343             {
0344                 return parent_->current_(*this);
0345             }
0346             constexpr decltype(auto) base_() const noexcept
0347             {
0348                 return (parent_->base_);
0349             }
0350 #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
0351             constexpr split_outer_iterator post_inc(std::true_type) // Forward
0352             {
0353                 auto tmp = *this;
0354                 ++*this;
0355                 return tmp;
0356             }
0357             constexpr void post_inc(std::false_type) // Input
0358             {
0359                 ++*this;
0360             }
0361 #endif
0362 
0363         public:
0364             using iterator_concept =
0365                 meta::conditional_t<forward_range<Base>, std::forward_iterator_tag,
0366                           std::input_iterator_tag>;
0367             using iterator_category = std::input_iterator_tag;
0368             struct value_type : view_interface<value_type>
0369             {
0370             private:
0371                 split_outer_iterator i_ = split_outer_iterator();
0372 
0373             public:
0374                 value_type() = default;
0375                 constexpr explicit value_type(split_outer_iterator i)
0376                   : i_(std::move(i))
0377                 {}
0378                 constexpr split_inner_iterator<split_view<V, Pattern>, Const> begin()
0379                     const
0380                 {
0381                     return split_inner_iterator<split_view<V, Pattern>, Const>(i_);
0382                 }
0383                 constexpr default_sentinel_t end() const
0384                 {
0385                     return default_sentinel;
0386                 }
0387             };
0388             using difference_type = range_difference_t<Base>;
0389             using reference = value_type; // Not to spec
0390             using pointer = value_type *; // Not to spec
0391 
0392             split_outer_iterator() = default;
0393 
0394             CPP_member
0395             constexpr explicit CPP_ctor(split_outer_iterator)(Parent * parent)(
0396                 requires (!forward_range<Base>))
0397               : parent_(parent)
0398             {}
0399 
0400             CPP_member
0401             constexpr CPP_ctor(split_outer_iterator)(Parent * parent,
0402                                                      iterator_t<Base> current)(
0403                 requires forward_range<Base>)
0404               : Current{std::move(current)}
0405               , parent_(parent)
0406             {}
0407 
0408             template(bool Other)(
0409                 requires Const AND CPP_NOT(Other) AND
0410                 convertible_to<iterator_t<V>, iterator_t<Base>>)
0411             constexpr split_outer_iterator(
0412                 split_outer_iterator<split_view<V, Pattern>, Other> i)
0413               : Current{std::move(i.curr_)}
0414               , parent_(i.parent_)
0415             {}
0416 
0417             constexpr value_type operator*() const
0418             {
0419                 return value_type{*this};
0420             }
0421 
0422             constexpr split_outer_iterator & operator++()
0423             {
0424                 auto & current = current_();
0425                 const auto last = ranges::end(base_());
0426                 if(current == last)
0427                     return *this;
0428                 auto const pbegin = ranges::begin(parent_->pattern_);
0429                 auto const pend = ranges::end(parent_->pattern_);
0430                 if(pbegin == pend)
0431                     ++current;
0432                 else
0433                     do
0434                     {
0435                         const auto ret = ranges::mismatch(current, last, pbegin, pend);
0436                         if(ret.in2 == pend)
0437                         {
0438                             current = ret.in1; // The pattern matched; skip it
0439                             break;
0440                         }
0441                     } while(++current != last);
0442                 return *this;
0443             }
0444 
0445             constexpr decltype(auto) operator++(int)
0446             {
0447 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0448                 if constexpr(forward_range<Base>)
0449                 {
0450                     auto tmp = *this;
0451                     ++*this;
0452                     return tmp;
0453                 }
0454                 else
0455                     ++*this;
0456 #else
0457                 return post_inc(meta::bool_<forward_range<Base>>{});
0458 #endif
0459             }
0460 
0461             CPP_broken_friend_member
0462             friend constexpr auto operator==(split_outer_iterator const & x,
0463                                              split_outer_iterator const & y)
0464                 -> CPP_broken_friend_ret(bool)(
0465                     requires forward_range<Base>)
0466             {
0467                 return x.curr_ == y.curr_;
0468             }
0469             CPP_broken_friend_member
0470             friend constexpr auto operator!=(split_outer_iterator const & x,
0471                                              split_outer_iterator const & y)
0472                 -> CPP_broken_friend_ret(bool)(
0473                     requires forward_range<Base>)
0474             {
0475                 return x.curr_ != y.curr_;
0476             }
0477 #ifdef RANGES_WORKAROUND_MSVC_756601
0478             template<typename = void>
0479 #endif // RANGES_WORKAROUND_MSVC_756601
0480             friend constexpr bool operator==(split_outer_iterator const & x,
0481                                              default_sentinel_t)
0482             {
0483                 return x.current_() == ranges::end(x.base_());
0484             }
0485 #ifdef RANGES_WORKAROUND_MSVC_756601
0486             template<typename = void>
0487 #endif // RANGES_WORKAROUND_MSVC_756601
0488             friend constexpr bool operator==(default_sentinel_t,
0489                                              split_outer_iterator const & x)
0490             {
0491                 return x.current_() == ranges::end(x.base_());
0492             }
0493 #ifdef RANGES_WORKAROUND_MSVC_756601
0494             template<typename = void>
0495 #endif // RANGES_WORKAROUND_MSVC_756601
0496             friend constexpr bool operator!=(split_outer_iterator const & x,
0497                                              default_sentinel_t)
0498             {
0499                 return x.current_() != ranges::end(x.base_());
0500             }
0501 #ifdef RANGES_WORKAROUND_MSVC_756601
0502             template<typename = void>
0503 #endif // RANGES_WORKAROUND_MSVC_756601
0504             friend constexpr bool operator!=(default_sentinel_t,
0505                                              split_outer_iterator const & x)
0506             {
0507                 return x.current_() != ranges::end(x.base_());
0508             }
0509         };
0510     } // namespace detail
0511     /// \endcond
0512 
0513     template<typename V, typename Pattern>
0514 #if CPP_CXX_CONCEPTS
0515         requires input_range<V> && forward_range<Pattern> && view_<V> && view_<
0516             Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>,
0517                                               ranges::equal_to> &&
0518         (forward_range<V> || detail::tiny_range<Pattern>)
0519 #endif
0520     struct RANGES_EMPTY_BASES split_view
0521       : view_interface<split_view<V, Pattern>, is_finite<V>::value ? finite : unknown>
0522       , private detail::split_view_base<iterator_t<V>>
0523     {
0524     private:
0525         template<typename, bool>
0526         friend struct detail::split_outer_iterator;
0527         template<typename, bool>
0528         friend struct detail::split_inner_iterator;
0529 
0530         V base_ = V();
0531         Pattern pattern_ = Pattern();
0532         template<bool Const>
0533         using outer_iterator = detail::split_outer_iterator<split_view, Const>;
0534 
0535 #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
0536         outer_iterator<simple_view<V>()> begin_(std::true_type)
0537         {
0538             return outer_iterator<simple_view<V>()>{this, ranges::begin(base_)};
0539         }
0540         outer_iterator<false> begin_(std::false_type)
0541         {
0542             this->curr_ = ranges::begin(base_);
0543             return outer_iterator<false>{this};
0544         }
0545 
0546         outer_iterator<simple_view<V>()> end_(std::true_type) const
0547         {
0548             return outer_iterator<true>{this, ranges::end(base_)};
0549         }
0550         default_sentinel_t end_(std::false_type) const
0551         {
0552             return default_sentinel;
0553         }
0554 #endif
0555 
0556     public:
0557         split_view() = default;
0558 
0559         constexpr split_view(V base, Pattern pattern)
0560           : base_((V &&) base)
0561           , pattern_((Pattern &&) pattern)
0562         {}
0563 
0564         CPP_member
0565         constexpr CPP_ctor(split_view)(V base, range_value_t<V> e)(
0566             requires constructible_from<Pattern, range_value_t<V>>)
0567           : base_(std::move(base))
0568           , pattern_(e)
0569         {}
0570 
0571         constexpr V base() const
0572         {
0573             return base_;
0574         }
0575 
0576         constexpr outer_iterator<forward_range<V> && simple_view<V>()> begin()
0577         {
0578 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0579             if constexpr(forward_range<V>)
0580                 return outer_iterator<simple_view<V>()>{this, ranges::begin(base_)};
0581             else
0582             {
0583                 this->curr_ = ranges::begin(base_);
0584                 return outer_iterator<false>{this};
0585             }
0586 #else
0587             return begin_(meta::bool_<forward_range<V>>{});
0588 #endif
0589         }
0590         CPP_member
0591         constexpr auto begin() const //
0592             -> CPP_ret(outer_iterator<true>)(
0593                 requires forward_range<V> && forward_range<const V>)
0594         {
0595             return {this, ranges::begin(base_)};
0596         }
0597         CPP_member
0598         constexpr auto end() //
0599             -> CPP_ret(outer_iterator<simple_view<V>()>)(
0600                 requires forward_range<V> && common_range<V>)
0601         {
0602             return outer_iterator<simple_view<V>()>{this, ranges::end(base_)};
0603         }
0604         constexpr auto end() const
0605         {
0606 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0607             if constexpr(forward_range<V> && forward_range<const V> &&
0608                          common_range<const V>)
0609                 return outer_iterator<true>{this, ranges::end(base_)};
0610             else
0611                 return default_sentinel;
0612 #else
0613             return end_(meta::bool_ < forward_range<V> && forward_range<const V> &&
0614                         common_range<const V> > {});
0615 #endif
0616         }
0617     };
0618 
0619 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0620     template(typename R, typename P)(
0621         requires input_range<R> AND forward_range<P> AND viewable_range<R> AND
0622             viewable_range<P> AND
0623             indirectly_comparable<iterator_t<R>, iterator_t<P>, ranges::equal_to> AND
0624             (forward_range<R> || detail::tiny_range<P>)) //
0625     split_view(R &&, P &&)
0626             ->split_view<views::all_t<R>, views::all_t<P>>;
0627 
0628     template(typename R)(
0629         requires input_range<R>)
0630         split_view(R &&, range_value_t<R>)
0631             ->split_view<views::all_t<R>, single_view<range_value_t<R>>>;
0632 #endif
0633 
0634     namespace views
0635     {
0636         struct split_base_fn
0637         {
0638             template(typename Rng)(
0639                 requires viewable_range<Rng> AND input_range<Rng> AND
0640                     indirectly_comparable<iterator_t<Rng>,
0641                                           range_value_t<Rng> const *,
0642                                           ranges::equal_to>)
0643             constexpr split_view<all_t<Rng>, single_view<range_value_t<Rng>>> //
0644             operator()(Rng && rng, range_value_t<Rng> val) const
0645             {
0646                 return {all(static_cast<Rng &&>(rng)), single(std::move(val))};
0647             }
0648 
0649             template(typename Rng, typename Pattern)(
0650                 requires viewable_range<Rng> AND input_range<Rng> AND
0651                     viewable_range<Pattern> AND forward_range<Pattern> AND
0652                     indirectly_comparable<
0653                         iterator_t<Rng>,
0654                         iterator_t<Pattern>,
0655                         ranges::equal_to> AND
0656                     (forward_range<Rng> || detail::tiny_range<Pattern>)) //
0657             constexpr split_view<all_t<Rng>, all_t<Pattern>> //
0658             operator()(Rng && rng, Pattern && pattern) const
0659             {
0660                 return {all((Rng &&) rng), all((Pattern &&) pattern)};
0661             }
0662         };
0663 
0664         struct split_fn : split_base_fn
0665         {
0666             using split_base_fn::operator();
0667 
0668             template<typename T>
0669             constexpr auto operator()(T t) const
0670             {
0671                 return make_view_closure(bind_back(split_base_fn{}, std::move(t)));
0672             }
0673         };
0674 
0675         /// \relates split_fn
0676         /// \ingroup group-views
0677         RANGES_INLINE_VARIABLE(split_fn, split)
0678     } // namespace views
0679 
0680     namespace cpp20
0681     {
0682         namespace views
0683         {
0684             using ranges::views::split;
0685         }
0686         template(typename Rng, typename Pattern)(
0687             requires input_range<Rng> AND forward_range<Pattern> AND view_<Rng> AND
0688                 view_<Pattern> AND
0689                 indirectly_comparable<
0690                     iterator_t<Rng>,
0691                     iterator_t<Pattern>,
0692                     ranges::equal_to> AND
0693                 (forward_range<Rng> || ranges::detail::tiny_range<Pattern>)) //
0694         using split_view =
0695             ranges::split_view<Rng, Pattern>;
0696     } // namespace cpp20
0697 
0698     /// @}
0699 } // namespace ranges
0700 
0701 #include <range/v3/detail/epilogue.hpp>
0702 
0703 #include <range/v3/detail/satisfy_boost_range.hpp>
0704 RANGES_SATISFY_BOOST_RANGE(::ranges::split_view)
0705 
0706 #endif