Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:40:35

0001 #ifndef BOOST_PARSER_REPLACE_HPP
0002 #define BOOST_PARSER_REPLACE_HPP
0003 
0004 #include <boost/parser/search.hpp>
0005 
0006 #if !defined(_MSC_VER) || BOOST_PARSER_USE_CONCEPTS
0007 
0008 
0009 namespace boost::parser {
0010 
0011     namespace detail {
0012         template<typename T, bool = std::is_pointer_v<remove_cv_ref_t<T>>>
0013         constexpr auto range_value_type =
0014             wrapper<remove_cv_ref_t<range_value_t<T>>>{};
0015         template<typename T>
0016         constexpr auto range_value_type<T, true> = wrapper<
0017             remove_cv_ref_t<std::remove_pointer_t<remove_cv_ref_t<T>>>>{};
0018 
0019         template<typename T>
0020         constexpr text::format range_utf_format()
0021         {
0022 #if !BOOST_PARSER_USE_CONCEPTS
0023             // Special case: the metafunctions above will not detect char8_t
0024             // in C++17 mode, since it does not exit yet!  So, we need to
0025             // detect utf8_view in particular, and know that its use implies
0026             // format::utf8.
0027             if constexpr (is_utf8_view<T>{}) {
0028                 return format::utf8;
0029             } else {
0030 #endif
0031                 using value_t = typename decltype(range_value_type<T>)::type;
0032                 if constexpr (std::is_same_v<value_t, char>) {
0033                     return no_format;
0034 #if defined(__cpp_char8_t)
0035                 } else if constexpr (std::is_same_v<value_t, char8_t>) {
0036                     return format::utf8;
0037 #endif
0038                 } else if constexpr (
0039                     std::is_same_v<value_t, char16_t>
0040 #ifdef _MSC_VER
0041                     || std::is_same_v<T, wchar_t>
0042 #endif
0043                 ) {
0044                     return format::utf16;
0045                 } else if constexpr (
0046                     std::is_same_v<value_t, char32_t>
0047 #ifndef _MSC_VER
0048                     || std::is_same_v<T, wchar_t>
0049 #endif
0050                 ) {
0051                     return format::utf32;
0052                 } else {
0053                     static_assert(
0054                         sizeof(T) && false,
0055                         "Looks like you're trying to pass a range to replace "
0056                         "or transform_replace that has a non-character type "
0057                         "for its value type.  This is not supported.");
0058                 }
0059 #if !BOOST_PARSER_USE_CONCEPTS
0060             }
0061 #endif
0062         }
0063 
0064         template<typename T>
0065         constexpr text::format
0066             range_utf_format_v = detail::range_utf_format<remove_cv_ref_t<T>>();
0067 
0068         template<typename V1, typename V2>
0069         using concat_reference_t =
0070             std::common_type_t<range_reference_t<V1>, range_reference_t<V2>>;
0071         template<typename V1, typename V2>
0072         using concat_value_t =
0073             std::common_type_t<range_value_t<V1>, range_value_t<V2>>;
0074         template<typename V1, typename V2>
0075         using concat_rvalue_reference_t = std::common_type_t<
0076             range_rvalue_reference_t<V1>,
0077             range_rvalue_reference_t<V2>>;
0078 
0079 #if BOOST_PARSER_USE_CONCEPTS
0080         template<typename ReplacementV, typename V>
0081         concept concatable = requires {
0082             typename detail::concat_reference_t<ReplacementV, V>;
0083             typename detail::concat_value_t<ReplacementV, V>;
0084             typename detail::concat_rvalue_reference_t<ReplacementV, V>;
0085         };
0086 #else
0087         template<typename ReplacementV, typename V>
0088         using concatable_expr =
0089             decltype(std::declval<concat_reference_t<ReplacementV, V>>(), std::declval<concat_value_t<ReplacementV, V>>(), std::declval<concat_rvalue_reference_t<ReplacementV, V>>());
0090         template<typename ReplacementV, typename V>
0091         constexpr bool concatable =
0092             is_detected_v<concatable_expr, ReplacementV, V>;
0093 #endif
0094 
0095         template<
0096             typename V1,
0097             typename V2
0098 #if !BOOST_PARSER_USE_CONCEPTS
0099             ,
0100             typename Enable = std::enable_if_t<concatable<V1, V2>>
0101 #endif
0102             >
0103 #if BOOST_PARSER_USE_CONCEPTS
0104             requires concatable<V1, V2>
0105 #endif
0106         struct either_iterator_impl
0107             : detail::stl_interfaces::iterator_interface<
0108                   either_iterator_impl<V1, V2>,
0109                   std::forward_iterator_tag,
0110                   concat_value_t<V1, V2>,
0111                   concat_reference_t<V1, V2>>
0112         {
0113             constexpr either_iterator_impl() = default;
0114             constexpr either_iterator_impl(iterator_t<V1> it) : it_(it) {}
0115             template<typename V = V2>
0116             constexpr either_iterator_impl(iterator_t<V> it) : it_(it)
0117             {}
0118 
0119             constexpr concat_reference_t<V1, V2> operator*() const
0120             {
0121                 if (it_.index() == 0) {
0122                     return *std::get<0>(it_);
0123                 } else {
0124                     return *std::get<1>(it_);
0125                 }
0126             }
0127 
0128             constexpr either_iterator_impl & operator++()
0129             {
0130                 if (it_.index() == 0)
0131                     ++std::get<0>(it_);
0132                 else
0133                     ++std::get<1>(it_);
0134                 return *this;
0135             }
0136 
0137             friend constexpr bool
0138             operator==(either_iterator_impl lhs, either_iterator_impl rhs)
0139             {
0140                 if (lhs.it_.index() != rhs.it_.index())
0141                     return false;
0142                 if (lhs.it_.index() == 0)
0143                     return std::get<0>(lhs.it_) == std::get<0>(rhs.it_);
0144                 else
0145                     return std::get<1>(lhs.it_) == std::get<1>(rhs.it_);
0146             }
0147 
0148             using base_type = detail::stl_interfaces::iterator_interface<
0149                 either_iterator_impl<V1, V2>,
0150                 std::forward_iterator_tag,
0151                 concat_value_t<V1, V2>,
0152                 concat_reference_t<V1, V2>>;
0153             using base_type::operator++;
0154 
0155         private:
0156             std::variant<iterator_t<V1>, iterator_t<V2>> it_;
0157         };
0158 
0159         template<typename V1, typename V2>
0160         using either_iterator = std::conditional_t<
0161             std::is_same_v<iterator_t<V1>, iterator_t<V2>>,
0162             iterator_t<V1>,
0163             either_iterator_impl<V1, V2>>;
0164 
0165 #if BOOST_PARSER_USE_CONCEPTS
0166         template<typename ReplacementV, typename V>
0167         concept replacement_for = requires(ReplacementV replacement, V base) {
0168             { either_iterator<V, ReplacementV>(replacement.begin()) };
0169             { either_iterator<V, ReplacementV>(replacement.end()) };
0170             { either_iterator<V, ReplacementV>(base.begin()) };
0171         };
0172 #else
0173         template<typename ReplacementV, typename V>
0174         using replacement_for_expr = decltype(
0175             either_iterator<V, ReplacementV>(
0176                 std::declval<ReplacementV&>().begin()),
0177             either_iterator<V, ReplacementV>(
0178                 std::declval<ReplacementV&>().end()),
0179             either_iterator<V, ReplacementV>(std::declval<V&>().begin()));
0180         template<typename ReplacementV, typename V>
0181         constexpr bool replacement_for =
0182             is_detected_v<replacement_for_expr, ReplacementV, V>;
0183 #endif
0184     }
0185 
0186     /** Produces a range of subranges of a given range `base`.  Each subrange
0187         is either a subrange of `base` that does not match the given parser
0188         `parser`, or is the given replacement for a match, `replacement`.
0189 
0190         In addition to the template parameter constraints, `V` and
0191         `ReplacementV` must be ranges of `char`, or must have the same UTF
0192         format, and `V` and `ReplacementV` must meet the same compatibility
0193         requirements as described in `std::ranges::join_view`. */
0194     template<
0195 #if BOOST_PARSER_USE_CONCEPTS
0196         std::ranges::viewable_range V,
0197         std::ranges::viewable_range ReplacementV,
0198 #else
0199         typename V,
0200         typename ReplacementV,
0201 #endif
0202         typename Parser,
0203         typename GlobalState,
0204         typename ErrorHandler,
0205         typename SkipParser
0206 #if !BOOST_PARSER_USE_CONCEPTS
0207         ,
0208         typename Enable = std::enable_if_t<
0209             detail::replacement_for<ReplacementV, V> &&
0210             (detail::range_utf_format_v<V> ==
0211              detail::range_utf_format_v<ReplacementV>)>
0212 #endif
0213         >
0214 #if BOOST_PARSER_USE_CONCEPTS
0215     requires detail::replacement_for<ReplacementV, V> &&
0216         (detail::range_utf_format_v<V> ==
0217          detail::range_utf_format_v<ReplacementV>)
0218 #endif
0219             struct replace_view
0220         : detail::stl_interfaces::view_interface<replace_view<
0221               V,
0222               ReplacementV,
0223               Parser,
0224               GlobalState,
0225               ErrorHandler,
0226               SkipParser>>
0227     {
0228         constexpr replace_view() = default;
0229         constexpr replace_view(
0230             V base,
0231             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0232             parser_interface<SkipParser> const & skip,
0233             ReplacementV replacement,
0234             trace trace_mode = trace::off) :
0235             base_(std::move(base)),
0236             replacement_(std::move(replacement)),
0237             parser_(parser),
0238             skip_(skip),
0239             trace_mode_(trace_mode)
0240         {}
0241         constexpr replace_view(
0242             V base,
0243             parser_interface<Parser, GlobalState, ErrorHandler> const & parser,
0244             ReplacementV replacement,
0245             trace trace_mode = trace::off) :
0246             base_(std::move(base)),
0247             replacement_(std::move(replacement)),
0248             parser_(parser),
0249             skip_(),
0250             trace_mode_(trace_mode)
0251         {}
0252 
0253         constexpr V base() const &
0254 #if BOOST_PARSER_USE_CONCEPTS
0255             requires std::copy_constructible<V>
0256 #endif
0257         {
0258             return base_;
0259         }
0260         constexpr V base() && { return std::move(base_); }
0261 
0262         constexpr V replacement() const &
0263 #if BOOST_PARSER_USE_CONCEPTS
0264             requires std::copy_constructible<V>
0265 #endif
0266         {
0267             return replacement_;
0268         }
0269         constexpr V replacement() && { return std::move(replacement_); }
0270 
0271         constexpr auto begin() { return iterator<false>{this}; }
0272         constexpr auto end() { return sentinel<false>{}; }
0273 
0274         constexpr auto begin() const
0275 #if BOOST_PARSER_USE_CONCEPTS
0276             requires std::ranges::range<const V>
0277 #endif
0278         {
0279             return iterator<true>{this};
0280         }
0281         constexpr auto end() const
0282 #if BOOST_PARSER_USE_CONCEPTS
0283             requires std::ranges::range<const V>
0284 #endif
0285         {
0286             return sentinel<true>{};
0287         }
0288 
0289         template<bool Const>
0290         struct sentinel
0291         {};
0292 
0293         template<bool Const>
0294         struct iterator : detail::stl_interfaces::proxy_iterator_interface<
0295                               iterator<Const>,
0296                               std::forward_iterator_tag,
0297                               BOOST_PARSER_SUBRANGE<detail::either_iterator<
0298                                   detail::maybe_const<Const, V>,
0299                                   detail::maybe_const<Const, ReplacementV>>>>
0300         {
0301             using I = detail::iterator_t<detail::maybe_const<Const, V>>;
0302             using S = detail::sentinel_t<detail::maybe_const<Const, V>>;
0303 
0304             using ref_t_iter = detail::either_iterator<
0305                 detail::maybe_const<Const, V>,
0306                 detail::maybe_const<Const, ReplacementV>>;
0307             using reference_type = BOOST_PARSER_SUBRANGE<ref_t_iter>;
0308 
0309             constexpr iterator() = default;
0310             constexpr iterator(
0311                 detail::maybe_const<Const, replace_view> * parent) :
0312                 parent_(parent),
0313                 r_(parent_->base_.begin(), parent_->base_.end()),
0314                 curr_(r_.begin(), r_.begin()),
0315                 next_it_(r_.begin()),
0316                 in_match_(true)
0317             {
0318                 ++*this;
0319             }
0320 
0321             constexpr iterator & operator++()
0322             {
0323                 if (in_match_) {
0324                     r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
0325                     auto const new_match = parser::search(
0326                         r_,
0327                         parent_->parser_,
0328                         parent_->skip_,
0329                         parent_->trace_mode_);
0330                     if (new_match.begin() == curr_.end()) {
0331                         curr_ = new_match;
0332                     } else {
0333                         curr_ =
0334                             BOOST_PARSER_SUBRANGE(next_it_, new_match.begin());
0335                         in_match_ = false;
0336                     }
0337                     next_it_ = new_match.end();
0338                 } else {
0339                     if (!curr_.empty()) {
0340                         curr_ = BOOST_PARSER_SUBRANGE(curr_.end(), next_it_);
0341                         in_match_ = true;
0342                     }
0343                     if (curr_.empty())
0344                         r_ = BOOST_PARSER_SUBRANGE<I, S>(next_it_, r_.end());
0345                 }
0346                 return *this;
0347             }
0348 
0349             constexpr reference_type operator*() const
0350             {
0351                 if (in_match_) {
0352                     return reference_type(
0353                         ref_t_iter(parent_->replacement_.begin()),
0354                         ref_t_iter(parent_->replacement_.end()));
0355                 } else {
0356                     return reference_type(
0357                         ref_t_iter(curr_.begin()), ref_t_iter(curr_.end()));
0358                 }
0359             }
0360 
0361             friend constexpr bool operator==(iterator lhs, iterator rhs)
0362             {
0363                 return lhs.r_.begin() == rhs.r_.begin();
0364             }
0365             friend constexpr bool operator==(iterator it, sentinel<Const>)
0366             {
0367                 return it.r_.begin() == it.r_.end();
0368             }
0369 
0370             using base_type = detail::stl_interfaces::proxy_iterator_interface<
0371                 iterator,
0372                 std::forward_iterator_tag,
0373                 reference_type>;
0374             using base_type::operator++;
0375 
0376         private:
0377             detail::maybe_const<Const, replace_view> * parent_;
0378             BOOST_PARSER_SUBRANGE<I, S> r_;
0379             BOOST_PARSER_SUBRANGE<I> curr_;
0380             I next_it_;
0381             bool in_match_;
0382         };
0383 
0384         template<bool Const>
0385         friend struct iterator;
0386 
0387     private:
0388         V base_;
0389         ReplacementV replacement_;
0390         parser_interface<Parser, GlobalState, ErrorHandler> parser_;
0391         parser_interface<SkipParser> skip_;
0392         trace trace_mode_;
0393     };
0394 
0395     // deduction guides
0396     template<
0397         typename V,
0398         typename ReplacementV,
0399         typename Parser,
0400         typename GlobalState,
0401         typename ErrorHandler,
0402         typename SkipParser>
0403     replace_view(
0404         V &&,
0405         parser_interface<Parser, GlobalState, ErrorHandler>,
0406         parser_interface<SkipParser>,
0407         ReplacementV &&,
0408         trace)
0409         -> replace_view<
0410             detail::text::detail::all_t<V>,
0411             detail::text::detail::all_t<ReplacementV>,
0412             Parser,
0413             GlobalState,
0414             ErrorHandler,
0415             SkipParser>;
0416 
0417     template<
0418         typename V,
0419         typename ReplacementV,
0420         typename Parser,
0421         typename GlobalState,
0422         typename ErrorHandler,
0423         typename SkipParser>
0424     replace_view(
0425         V &&,
0426         parser_interface<Parser, GlobalState, ErrorHandler>,
0427         parser_interface<SkipParser>,
0428         ReplacementV &&)
0429         -> replace_view<
0430             detail::text::detail::all_t<V>,
0431             detail::text::detail::all_t<ReplacementV>,
0432             Parser,
0433             GlobalState,
0434             ErrorHandler,
0435             SkipParser>;
0436 
0437     template<
0438         typename V,
0439         typename ReplacementV,
0440         typename Parser,
0441         typename GlobalState,
0442         typename ErrorHandler>
0443     replace_view(
0444         V &&,
0445         parser_interface<Parser, GlobalState, ErrorHandler>,
0446         ReplacementV &&,
0447         trace)
0448         -> replace_view<
0449             detail::text::detail::all_t<V>,
0450             detail::text::detail::all_t<ReplacementV>,
0451             Parser,
0452             GlobalState,
0453             ErrorHandler,
0454             parser_interface<eps_parser<detail::phony>>>;
0455 
0456     template<
0457         typename V,
0458         typename ReplacementV,
0459         typename Parser,
0460         typename GlobalState,
0461         typename ErrorHandler>
0462     replace_view(
0463         V &&,
0464         parser_interface<Parser, GlobalState, ErrorHandler>,
0465         ReplacementV &&)
0466         -> replace_view<
0467             detail::text::detail::all_t<V>,
0468             detail::text::detail::all_t<ReplacementV>,
0469             Parser,
0470             GlobalState,
0471             ErrorHandler,
0472             parser_interface<eps_parser<detail::phony>>>;
0473 
0474     namespace detail {
0475         template<
0476             typename V,
0477             typename ReplacementV,
0478             typename Parser,
0479             typename GlobalState,
0480             typename ErrorHandler,
0481             typename SkipParser>
0482         using replace_view_expr = decltype(replace_view<
0483                                            V,
0484                                            ReplacementV,
0485                                            Parser,
0486                                            GlobalState,
0487                                            ErrorHandler,
0488                                            SkipParser>(
0489             std::declval<V>(),
0490             std::declval<
0491                 parser_interface<Parser, GlobalState, ErrorHandler> const &>(),
0492             std::declval<parser_interface<SkipParser> const &>(),
0493             std::declval<ReplacementV>(),
0494             trace::on));
0495 
0496         template<
0497             typename V,
0498             typename ReplacementV,
0499             typename Parser,
0500             typename GlobalState,
0501             typename ErrorHandler,
0502             typename SkipParser>
0503         constexpr bool can_replace_view = is_detected_v<
0504             replace_view_expr,
0505             V,
0506             ReplacementV,
0507             Parser,
0508             GlobalState,
0509             ErrorHandler,
0510             SkipParser>;
0511 
0512         struct replace_impl
0513         {
0514 #if BOOST_PARSER_USE_CONCEPTS
0515 
0516             template<
0517                 parsable_range R,
0518                 std::ranges::range ReplacementR,
0519                 typename Parser,
0520                 typename GlobalState,
0521                 typename ErrorHandler,
0522                 typename SkipParser>
0523                 requires std::ranges::viewable_range<R> &&
0524                          std::ranges::viewable_range<ReplacementR> &&
0525                          can_replace_view<
0526                              to_range_t<R>,
0527                              decltype(to_range<
0528                                       ReplacementR,
0529                                       true,
0530                                       detail::range_utf_format_v<R>>::
0531                                           call(std::declval<ReplacementR>())),
0532                              Parser,
0533                              GlobalState,
0534                              ErrorHandler,
0535                              SkipParser>
0536             [[nodiscard]] constexpr auto operator()(
0537                 R && r,
0538                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0539                     parser,
0540                 parser_interface<SkipParser> const & skip,
0541                 ReplacementR && replacement,
0542                 trace trace_mode = trace::off) const
0543             {
0544                 return replace_view(
0545                     to_range<R>::call((R &&)r),
0546                     parser,
0547                     skip,
0548                     to_range<
0549                         ReplacementR,
0550                         true,
0551                         detail::range_utf_format_v<R>>::call((ReplacementR &&)
0552                                                                  replacement),
0553                     trace_mode);
0554             }
0555 
0556             template<
0557                 parsable_range R,
0558                 std::ranges::range ReplacementR,
0559                 typename Parser,
0560                 typename GlobalState,
0561                 typename ErrorHandler>
0562                 requires std::ranges::viewable_range<R> &&
0563                          std::ranges::viewable_range<ReplacementR> &&
0564                          can_replace_view<
0565                              to_range_t<R>,
0566                              decltype(to_range<
0567                                       ReplacementR,
0568                                       true,
0569                                       detail::range_utf_format_v<R>>::
0570                                           call(std::declval<ReplacementR>())),
0571                              Parser,
0572                              GlobalState,
0573                              ErrorHandler,
0574                              parser_interface<eps_parser<detail::phony>>>
0575             [[nodiscard]] constexpr auto operator()(
0576                 R && r,
0577                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0578                     parser,
0579                 ReplacementR && replacement,
0580                 trace trace_mode = trace::off) const
0581             {
0582                 return (*this)(
0583                     (R &&)r,
0584                     parser,
0585                     parser_interface<eps_parser<detail::phony>>{},
0586                     (ReplacementR &&)replacement,
0587                     trace_mode);
0588             }
0589 
0590 #else
0591 
0592             template<
0593                 typename R,
0594                 typename Parser,
0595                 typename GlobalState,
0596                 typename ErrorHandler,
0597                 typename SkipParser,
0598                 typename ReplacementR = trace,
0599                 typename Trace = trace,
0600                 typename Enable = std::enable_if_t<is_parsable_range_v<R>>>
0601             [[nodiscard]] constexpr auto operator()(
0602                 R && r,
0603                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0604                     parser,
0605                 SkipParser && skip,
0606                 ReplacementR && replacement = ReplacementR{},
0607                 Trace trace_mode = Trace{}) const
0608             {
0609                 if constexpr (
0610                     is_parser_iface<remove_cv_ref_t<SkipParser>> &&
0611                     is_range<remove_cv_ref_t<ReplacementR>> &&
0612                     std::is_same_v<Trace, trace>) {
0613                     // (r, parser, skip, replacement, trace) case
0614                     return impl(
0615                         (R &&) r,
0616                         parser,
0617                         skip,
0618                         (ReplacementR &&) replacement,
0619                         trace_mode);
0620                 } else if constexpr (
0621                     is_range<remove_cv_ref_t<SkipParser>> &&
0622                     std::is_same_v<remove_cv_ref_t<ReplacementR>, trace> &&
0623                     std::is_same_v<Trace, trace>) {
0624                     // (r, parser, replacement, trace) case
0625                     return impl(
0626                         (R &&) r,
0627                         parser,
0628                         parser_interface<eps_parser<detail::phony>>{},
0629                         (SkipParser &&) skip,
0630                         replacement);
0631                 } else {
0632                     static_assert(
0633                         sizeof(R) == 1 && false,
0634                         "Only the signatures replace(R, parser, skip, "
0635                         "replcement trace = trace::off) and replace(R, parser, "
0636                         "replacement, trace = trace::off) are supported.");
0637                 }
0638             }
0639 
0640         private:
0641             template<
0642                 typename R,
0643                 typename ReplacementR,
0644                 typename Parser,
0645                 typename GlobalState,
0646                 typename ErrorHandler,
0647                 typename SkipParser>
0648             [[nodiscard]] constexpr auto impl(
0649                 R && r,
0650                 parser_interface<Parser, GlobalState, ErrorHandler> const &
0651                     parser,
0652                 parser_interface<SkipParser> const & skip,
0653                 ReplacementR && replacement,
0654                 trace trace_mode = trace::off) const
0655             {
0656                 return replace_view(
0657                     to_range<R>::call((R &&) r),
0658                     parser,
0659                     skip,
0660                     to_range<
0661                         ReplacementR,
0662                         true,
0663                         detail::range_utf_format_v<R>>::call((ReplacementR &&)
0664                                                                  replacement),
0665                     trace_mode);
0666             }
0667 
0668 #endif
0669         };
0670     }
0671 
0672     /** A range adaptor object ([range.adaptor.object]).  Given subexpressions
0673         `E` and `P`, `Q`, `R`, and 'S', each of the expressions `replace(E,
0674         P)`, `replace(E, P, Q)`. `replace(E, P, Q, R)`, and `replace(E, P, Q,
0675         R, S)` are expression-equivalent to `replace_view(E, P)`,
0676         `replace_view(E, P, Q)`, `replace_view(E, P, Q, R)`, `replace_view(E,
0677         P, Q, R, S)`, respectively. */
0678     inline constexpr detail::stl_interfaces::adaptor<detail::replace_impl>
0679         replace = detail::replace_impl{};
0680 
0681 }
0682 
0683 #if BOOST_PARSER_USE_CONCEPTS
0684 template<
0685     typename V,
0686     typename ReplacementV,
0687     typename Parser,
0688     typename GlobalState,
0689     typename ErrorHandler,
0690     typename SkipParser>
0691 constexpr bool std::ranges::enable_borrowed_range<boost::parser::replace_view<
0692     V,
0693     ReplacementV,
0694     Parser,
0695     GlobalState,
0696     ErrorHandler,
0697     SkipParser>> = std::ranges::enable_borrowed_range<V> &&
0698     std::ranges::enable_borrowed_range<ReplacementV>;
0699 #endif
0700 
0701 #endif
0702 
0703 #endif