Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:53

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file match_results.hpp
0003 /// Contains the definition of the match_results type and associated helpers.
0004 /// The match_results type holds the results of a regex_match() or
0005 /// regex_search() operation.
0006 //
0007 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0008 //  Software License, Version 1.0. (See accompanying file
0009 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Acknowledgements: Thanks to Markus Schoepflin for helping to track down
0012 // a tricky formatting bug on HP Tru64, and to Steven Watanabe for suggesting
0013 // the fix.
0014 
0015 #ifndef BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
0016 #define BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
0017 
0018 // MS compatible compilers support #pragma once
0019 #if defined(_MSC_VER)
0020 # pragma once
0021 #endif
0022 
0023 #include <map>
0024 #include <string>
0025 #include <vector>
0026 #include <utility>
0027 #include <iterator>
0028 #include <typeinfo>
0029 #include <algorithm>
0030 #include <boost/config.hpp>
0031 #include <boost/assert.hpp>
0032 #include <boost/integer.hpp>
0033 #include <boost/mpl/if.hpp>
0034 #include <boost/mpl/not.hpp>
0035 #include <boost/mpl/size_t.hpp>
0036 #include <boost/mpl/assert.hpp>
0037 #include <boost/intrusive_ptr.hpp>
0038 #include <boost/throw_exception.hpp>
0039 #include <boost/iterator_adaptors.hpp>
0040 #include <boost/utility/enable_if.hpp>
0041 #include <boost/detail/workaround.hpp>
0042 #include <boost/numeric/conversion/converter.hpp>
0043 #include <boost/optional.hpp>
0044 #include <boost/range/end.hpp>
0045 #include <boost/range/begin.hpp>
0046 #include <boost/range/as_literal.hpp>
0047 #include <boost/range/const_iterator.hpp>
0048 #include <boost/type_traits/is_function.hpp>
0049 #if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
0050 # include <boost/iterator/filter_iterator.hpp>
0051 #endif
0052 #include <boost/xpressive/regex_constants.hpp>
0053 #include <boost/xpressive/detail/detail_fwd.hpp>
0054 #include <boost/xpressive/detail/core/regex_impl.hpp>
0055 #include <boost/xpressive/detail/core/sub_match_vector.hpp>
0056 #include <boost/xpressive/detail/utility/sequence_stack.hpp>
0057 #include <boost/xpressive/detail/core/results_cache.hpp>
0058 #include <boost/xpressive/detail/utility/literals.hpp>
0059 #include <boost/xpressive/detail/utility/algorithm.hpp>
0060 #include <boost/xpressive/detail/utility/counted_base.hpp>
0061 // Doxygen can't handle proto :-(
0062 #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
0063 # include <boost/proto/proto_fwd.hpp>
0064 # include <boost/proto/traits.hpp>
0065 #endif
0066 
0067 namespace boost { namespace xpressive { namespace detail
0068 {
0069 
0070 ///////////////////////////////////////////////////////////////////////////////
0071 // type_info_less
0072 //
0073 struct type_info_less
0074 {
0075     bool operator()(std::type_info const *left, std::type_info const *right) const
0076     {
0077         return 0 != left->before(*right);
0078     }
0079 };
0080 
0081 ///////////////////////////////////////////////////////////////////////////////
0082 // ActionArgBinding
0083 //
0084 struct ActionArgBinding
0085   : proto::assign<proto::terminal<action_arg<proto::_, proto::_> >, proto::terminal<proto::_> >
0086 {
0087 };
0088 
0089 ///////////////////////////////////////////////////////////////////////////////
0090 // results_extras
0091 //
0092 template<typename BidiIter>
0093 struct results_extras
0094   : counted_base<results_extras<BidiIter> >
0095 {
0096     sequence_stack<sub_match_impl<BidiIter> > sub_match_stack_;
0097     results_cache<BidiIter> results_cache_;
0098 };
0099 
0100 ///////////////////////////////////////////////////////////////////////////////
0101 // char_overflow_handler_
0102 //
0103 struct char_overflow_handler_
0104 {
0105     void operator ()(numeric::range_check_result result) const // throw(regex_error)
0106     {
0107         if(numeric::cInRange != result)
0108         {
0109             BOOST_THROW_EXCEPTION(
0110                 regex_error(
0111                     regex_constants::error_escape
0112                   , "character escape too large to fit in target character type"
0113                 )
0114             );
0115         }
0116     }
0117 };
0118 
0119 ///////////////////////////////////////////////////////////////////////////////
0120 // transform_op enum
0121 //
0122 enum transform_op { op_none = 0, op_upper = 1, op_lower = 2 };
0123 enum transform_scope { scope_next = 0, scope_rest = 1 };
0124 
0125 ///////////////////////////////////////////////////////////////////////////////
0126 // case_converting_iterator
0127 //
0128 template<typename OutputIterator, typename Char>
0129 struct case_converting_iterator
0130 {
0131     typedef std::output_iterator_tag iterator_category;
0132     typedef Char value_type;
0133     typedef void difference_type;
0134     typedef void pointer;
0135     typedef case_converting_iterator<OutputIterator, Char> reference;
0136 
0137     case_converting_iterator(OutputIterator const &out, traits<Char> const *tr)
0138       : out_(out)
0139       , traits_(tr)
0140       , next_(op_none)
0141       , rest_(op_none)
0142     {}
0143 
0144     OutputIterator base() const
0145     {
0146         return this->out_;
0147     }
0148 
0149     case_converting_iterator &operator ++()
0150     {
0151         ++this->out_;
0152         this->next_ = op_none;
0153         return *this;
0154     }
0155 
0156     case_converting_iterator operator ++(int)
0157     {
0158         case_converting_iterator tmp(*this);
0159         ++*this;
0160         return tmp;
0161     }
0162 
0163     case_converting_iterator &operator *()
0164     {
0165         return *this;
0166     }
0167 
0168     friend bool set_transform(case_converting_iterator &iter, transform_op trans, transform_scope scope)
0169     {
0170         BOOST_ASSERT(scope == scope_next || scope == scope_rest);
0171         if(scope == scope_next)
0172             iter.next_ = trans;
0173         else
0174             iter.rest_ = trans;
0175         return true;
0176     }
0177 
0178     case_converting_iterator &operator =(Char ch)
0179     {
0180         switch(this->next_ ? this->next_ : this->rest_)
0181         {
0182         case op_lower:
0183             ch = this->traits_->tolower(ch);
0184             break;
0185 
0186         case op_upper:
0187             ch = this->traits_->toupper(ch);
0188             break;
0189 
0190         default:;
0191         }
0192 
0193         *this->out_ = ch;
0194         return *this;
0195     }
0196 
0197 private:
0198     OutputIterator out_;
0199     traits<Char> const *traits_;
0200     transform_op next_, rest_;
0201 };
0202 
0203 template<typename Iterator>
0204 inline bool set_transform(Iterator &, transform_op, transform_scope)
0205 {
0206     return false;
0207 }
0208 
0209 ///////////////////////////////////////////////////////////////////////////////
0210 // noop_output_iterator
0211 //
0212 template<typename Char>
0213 struct noop_output_iterator
0214 {
0215     typedef std::output_iterator_tag iterator_category;
0216     typedef Char value_type;
0217     typedef void difference_type;
0218     typedef void pointer;
0219     typedef noop_output_iterator<Char> reference;
0220 
0221     noop_output_iterator &operator ++()
0222     {
0223         return *this;
0224     }
0225 
0226     noop_output_iterator &operator ++(int)
0227     {
0228         return *this;
0229     }
0230 
0231     noop_output_iterator &operator *()
0232     {
0233         return *this;
0234     }
0235 
0236     noop_output_iterator &operator =(Char const &)
0237     {
0238         return *this;
0239     }
0240 };
0241 
0242 struct any_type { any_type(...); };
0243 typedef char no_type;
0244 typedef char (&unary_type)[2];
0245 typedef char (&binary_type)[3];
0246 typedef char (&ternary_type)[4];
0247 
0248 no_type check_is_formatter(unary_type, binary_type, ternary_type);
0249 
0250 template<typename T>
0251 unary_type check_is_formatter(T const &, binary_type, ternary_type);
0252 
0253 template<typename T>
0254 binary_type check_is_formatter(unary_type, T const &, ternary_type);
0255 
0256 template<typename T, typename U>
0257 binary_type check_is_formatter(T const &, U const &, ternary_type);
0258 
0259 template<typename T>
0260 ternary_type check_is_formatter(unary_type, binary_type, T const &);
0261 
0262 template<typename T, typename U>
0263 ternary_type check_is_formatter(T const &, binary_type, U const &);
0264 
0265 template<typename T, typename U>
0266 ternary_type check_is_formatter(unary_type, T const &, U const &);
0267 
0268 template<typename T, typename U, typename V>
0269 ternary_type check_is_formatter(T const &, U const &, V const &);
0270 
0271 struct unary_binary_ternary
0272 {
0273     typedef unary_type (*unary_fun)(any_type);
0274     typedef binary_type (*binary_fun)(any_type, any_type);
0275     typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
0276     operator unary_fun();
0277     operator binary_fun();
0278     operator ternary_fun();
0279 };
0280 
0281 template<typename Formatter, bool IsFunction = is_function<Formatter>::value>
0282 struct formatter_wrapper
0283   : Formatter
0284   , unary_binary_ternary
0285 {
0286     formatter_wrapper();
0287 };
0288 
0289 template<typename Formatter>
0290 struct formatter_wrapper<Formatter, true>
0291   : unary_binary_ternary
0292 {
0293     operator Formatter *();
0294 };
0295 
0296 template<typename Formatter>
0297 struct formatter_wrapper<Formatter *, false>
0298   : unary_binary_ternary
0299 {
0300     operator Formatter *();
0301 };
0302 
0303 template<typename Formatter, typename What, typename Out, typename Void = void>
0304 struct formatter_arity
0305 {
0306     static formatter_wrapper<Formatter> &formatter;
0307     static What &what;
0308     static Out &out;
0309     BOOST_STATIC_CONSTANT(
0310         std::size_t
0311       , value = sizeof(
0312             check_is_formatter(
0313                 formatter(what)
0314               , formatter(what, out)
0315               , formatter(what, out, regex_constants::format_default)
0316             )
0317         ) - 1
0318     );
0319     typedef mpl::size_t<value> type;
0320 };
0321 
0322 template<typename Formatter, typename What, typename Out>
0323 struct formatter_arity<Formatter, What, Out, typename Formatter::proto_is_expr_>
0324   : mpl::size_t<4>
0325 {};
0326 
0327 template<typename T>
0328 struct is_char_ptr
0329   : mpl::false_
0330 {};
0331 
0332 template<typename T>
0333 struct is_char_ptr<T *>
0334   : mpl::not_<is_function<T> >
0335 {};
0336 
0337 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0338 // work around gcc-4.0.1 compiler bug wrt function references
0339 template<typename T>
0340 typename mpl::if_<is_function<T>, T *, T const &>::type
0341 as_callable(T const &t)
0342 {
0343     return t;
0344 }
0345 #endif
0346 
0347 } // detail
0348 
0349 ///////////////////////////////////////////////////////////////////////////////
0350 // match_results
0351 /// \brief Class template match_results\<\> holds the results of a regex_match() or a
0352 /// regex_search() as a collection of sub_match objects.
0353 ///
0354 /// Class template match_results\<\> denotes a collection of sequences representing the result of
0355 /// a regular expression match. Storage for the collection is allocated and freed as necessary by
0356 /// the member functions of class match_results\<\>.
0357 ///
0358 /// The class template match_results\<\> conforms to the requirements of a Sequence, as specified
0359 /// in (lib.sequence.reqmts), except that only operations defined for const-qualified Sequences are
0360 /// supported.
0361 template<typename BidiIter>
0362 struct match_results
0363 {
0364 private:
0365     /// INTERNAL ONLY
0366     ///
0367     struct dummy { int i_; };
0368     typedef int dummy::*bool_type;
0369 
0370 public:
0371     typedef typename iterator_value<BidiIter>::type char_type;
0372     typedef typename detail::string_type<char_type>::type string_type;
0373     typedef std::size_t size_type;
0374     typedef sub_match<BidiIter> value_type;
0375     typedef typename iterator_difference<BidiIter>::type difference_type;
0376     typedef value_type const &reference;
0377     typedef value_type const &const_reference;
0378 
0379     typedef typename detail::sub_match_vector<BidiIter>::iterator iterator;
0380     typedef typename detail::sub_match_vector<BidiIter>::const_iterator const_iterator;
0381     typedef typename detail::nested_results<BidiIter> nested_results_type;
0382 
0383     /// \post regex_id() == 0
0384     /// \post size()     == 0
0385     /// \post empty()    == true
0386     /// \post str()      == string_type()
0387     match_results()
0388       : regex_id_(0)
0389       , sub_matches_()
0390       , base_()
0391       , prefix_()
0392       , suffix_()
0393       , nested_results_()
0394       , extras_ptr_()
0395       , traits_()
0396       , args_()
0397       , named_marks_()
0398     {
0399     }
0400 
0401     /// \param that The match_results object to copy
0402     /// \post regex_id()  == that.regex_id().
0403     /// \post size()      == that.size().
0404     /// \post empty()     == that.empty().
0405     /// \post str(n)      == that.str(n) for all positive integers n \< that.size().
0406     /// \post prefix()    == that.prefix().
0407     /// \post suffix()    == that.suffix().
0408     /// \post (*this)[n]  == that[n] for all positive integers n \< that.size().
0409     /// \post length(n)   == that.length(n) for all positive integers n \< that.size().
0410     /// \post position(n) == that.position(n) for all positive integers n \< that.size().
0411     match_results(match_results<BidiIter> const &that)
0412       : regex_id_(that.regex_id_)
0413       , sub_matches_()
0414       , base_()
0415       , prefix_()
0416       , suffix_()
0417       , nested_results_()
0418       , extras_ptr_()
0419       , traits_()
0420       , args_(that.args_)
0421       , named_marks_(that.named_marks_)
0422     {
0423         if(that)
0424         {
0425             extras_type &extras = this->get_extras_();
0426             std::size_t size = that.sub_matches_.size();
0427             detail::sub_match_impl<BidiIter> *sub_matches = extras.sub_match_stack_.push_sequence(size, detail::sub_match_impl<BidiIter>(*that.base_), detail::fill);
0428             detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size, that.sub_matches_);
0429 
0430             this->base_ = that.base_;
0431             this->prefix_ = that.prefix_;
0432             this->suffix_ = that.suffix_;
0433             // BUGBUG this doesn't share the extras::sequence_stack
0434             this->nested_results_ = that.nested_results_;
0435             this->traits_ = that.traits_;
0436         }
0437     }
0438 
0439     ~match_results()
0440     {
0441     }
0442 
0443     /// \param that The match_results object to copy.
0444     /// \post regex_id()  == that.regex_id().
0445     /// \post size()      == that.size().
0446     /// \post empty()     == that.empty().
0447     /// \post str(n)      == that.str(n) for all positive integers n \< that.size().
0448     /// \post prefix()    == that.prefix().
0449     /// \post suffix()    == that.suffix().
0450     /// \post (*this)[n]  == that[n] for all positive integers n \< that.size().
0451     /// \post length(n)   == that.length(n) for all positive integers n \< that.size().
0452     /// \post position(n) == that.position(n) for all positive integers n \< that.size().
0453     match_results<BidiIter> &operator =(match_results<BidiIter> const &that)
0454     {
0455         match_results<BidiIter>(that).swap(*this);
0456         return *this;
0457     }
0458 
0459     /// Returns one plus the number of marked sub-expressions in the regular
0460     /// expression that was matched if *this represents the result of a
0461     /// successful match. Otherwise returns 0.
0462     size_type size() const
0463     {
0464         return this->sub_matches_.size();
0465     }
0466 
0467     /// Returns size() == 0.
0468     ///
0469     bool empty() const
0470     {
0471         return 0 == this->size();
0472     }
0473 
0474     /// Returns (*this)[sub].length().
0475     ///
0476     difference_type length(size_type sub = 0) const
0477     {
0478         return this->sub_matches_[ sub ].length();
0479     }
0480 
0481     /// If !(*this)[sub].matched then returns -1. Otherwise returns std::distance(base, (*this)[sub].first),
0482     /// where base is the start iterator of the sequence that was searched. [Note - unless this is part
0483     /// of a repeated search with a regex_iterator then base is the same as prefix().first - end note]
0484     difference_type position(size_type sub = 0) const
0485     {
0486         return this->sub_matches_[ sub ].matched ? std::distance(*this->base_, this->sub_matches_[ sub ].first) : -1;
0487     }
0488 
0489     /// Returns (*this)[sub].str().
0490     ///
0491     string_type str(size_type sub = 0) const
0492     {
0493         return this->sub_matches_[ sub ].str();
0494     }
0495 
0496     /// Returns a reference to the sub_match object representing the sequence that
0497     /// matched marked sub-expression sub. If sub == 0 then returns a reference to
0498     /// a sub_match object representing the sequence that matched the whole regular
0499     /// expression. If sub >= size() then returns a sub_match object representing an
0500     /// unmatched sub-expression.
0501     template<typename Sub>
0502     const_reference operator [](Sub const &sub) const
0503     {
0504         return this->at_(sub);
0505     }
0506 
0507     /// Returns a reference to the sub_match object representing the character sequence from
0508     /// the start of the string being matched/searched, to the start of the match found.
0509     ///
0510     /// \pre (*this)[0].matched is true
0511     const_reference prefix() const
0512     {
0513         return this->prefix_ ? *this->prefix_ : this->sub_matches_[this->sub_matches_.size()];
0514     }
0515 
0516     /// Returns a reference to the sub_match object representing the character sequence from
0517     /// the end of the match found to the end of the string being matched/searched.
0518     ///
0519     /// \pre (*this)[0].matched is true
0520     const_reference suffix() const
0521     {
0522         return this->suffix_ ? *this->suffix_ : this->sub_matches_[this->sub_matches_.size()];
0523     }
0524 
0525     /// Returns a starting iterator that enumerates over all the marked sub-expression matches
0526     /// stored in *this.
0527     ///
0528     const_iterator begin() const
0529     {
0530         return this->sub_matches_.begin();
0531     }
0532 
0533     /// Returns a terminating iterator that enumerates over all the marked sub-expression
0534     /// matches stored in *this.
0535     ///
0536     const_iterator end() const
0537     {
0538         return this->sub_matches_.end();
0539     }
0540 
0541     /// Returns a true value if (*this)[0].matched, else returns a false value.
0542     ///
0543     operator bool_type() const
0544     {
0545         return (!this->empty() && this->sub_matches_[ 0 ].matched) ? &dummy::i_ : 0;
0546     }
0547 
0548     /// Returns true if empty() || !(*this)[0].matched, else returns false.
0549     ///
0550     bool operator !() const
0551     {
0552         return this->empty() || !this->sub_matches_[ 0 ].matched;
0553     }
0554 
0555     /// Returns the id of the basic_regex object most recently used with this match_results object.
0556     ///
0557     regex_id_type regex_id() const
0558     {
0559         return this->regex_id_;
0560     }
0561 
0562     /// Returns a Sequence of nested match_results elements.
0563     ///
0564     nested_results_type const &nested_results() const
0565     {
0566         return this->nested_results_;
0567     }
0568 
0569     /// If \c Format models \c ForwardRange or is a null-terminated string, this function
0570     /// copies the character sequence in \c fmt to \c OutputIterator \c out. For each format
0571     /// specifier or escape sequence in \c fmt, replace that sequence with either the character(s) it
0572     /// represents, or the sequence within <tt>*this</tt> to which it refers. The bitmasks specified in flags
0573     /// determines what format specifiers or escape sequences are recognized. By default, this is the
0574     /// format used by ECMA-262, ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
0575     ///
0576     /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
0577     /// this function returns <tt>fmt(*this, out, flags)</tt>.
0578     ///
0579     /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
0580     /// returns <tt>fmt(*this, out)</tt>.
0581     ///
0582     /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
0583     /// returns <tt>std::copy(x.begin(), x.end(), out)</tt>, where \c x is the result of
0584     /// calling <tt>fmt(*this)</tt>.
0585     template<typename Format, typename OutputIterator>
0586     OutputIterator format
0587     (
0588         OutputIterator out
0589       , Format const &fmt
0590       , regex_constants::match_flag_type flags = regex_constants::format_default
0591       , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
0592     ) const
0593     {
0594         // Is this a formatter object, or a format string?
0595         typedef
0596             typename detail::formatter_arity<
0597                 Format
0598               , match_results<BidiIter>
0599               , OutputIterator
0600             >::type
0601         arity;
0602 
0603         return this->format_(out, fmt, flags, arity());
0604     }
0605 
0606     /// \overload
0607     ///
0608     template<typename OutputIterator>
0609     OutputIterator format
0610     (
0611         OutputIterator out
0612       , char_type const *fmt
0613       , regex_constants::match_flag_type flags = regex_constants::format_default
0614     ) const
0615     {
0616         return this->format_(out, boost::as_literal(fmt), flags, mpl::size_t<0>());
0617     }
0618 
0619     /// If \c Format models \c ForwardRange or is a null-terminated string, this function
0620     /// returns a copy of the character sequence \c fmt. For each format specifier or escape sequence in \c fmt,
0621     /// replace that sequence with either the character(s) it represents, or the sequence within
0622     /// <tt>*this</tt> to which it refers. The bitmasks specified in \c flags determines what format specifiers
0623     /// or escape sequences are recognized. By default this is the format used by ECMA-262,
0624     /// ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
0625     ///
0626     /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
0627     /// this function returns a \c string_type object \c x populated by calling <tt>fmt(*this, out, flags)</tt>,
0628     /// where \c out is a \c back_insert_iterator into \c x.
0629     ///
0630     /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
0631     /// returns a \c string_type object \c x populated by calling <tt>fmt(*this, out)</tt>,
0632     /// where \c out is a \c back_insert_iterator into \c x.
0633     ///
0634     /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
0635     /// returns <tt>fmt(*this)</tt>.
0636     template<typename Format, typename OutputIterator>
0637     string_type format
0638     (
0639         Format const &fmt
0640       , regex_constants::match_flag_type flags = regex_constants::format_default
0641       , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
0642     ) const
0643     {
0644         string_type result;
0645         this->format(std::back_inserter(result), fmt, flags);
0646         return result;
0647     }
0648 
0649     /// \overload
0650     ///
0651     string_type format
0652     (
0653         char_type const *fmt
0654       , regex_constants::match_flag_type flags = regex_constants::format_default
0655     ) const
0656     {
0657         string_type result;
0658         this->format(std::back_inserter(result), fmt, flags);
0659         return result;
0660     }
0661 
0662     /// Swaps the contents of two match_results objects. Guaranteed not to throw.
0663     /// \param that The match_results object to swap with.
0664     /// \post *this contains the sequence of matched sub-expressions that were in that,
0665     /// that contains the sequence of matched sub-expressions that were in *this.
0666     /// \throw nothrow
0667     void swap(match_results<BidiIter> &that) // throw()
0668     {
0669         using std::swap;
0670         swap(this->regex_id_, that.regex_id_);
0671         this->sub_matches_.swap(that.sub_matches_);
0672         this->base_.swap(that.base_);
0673         this->prefix_.swap(that.prefix_);
0674         this->suffix_.swap(that.suffix_);
0675         this->nested_results_.swap(that.nested_results_);
0676         this->extras_ptr_.swap(that.extras_ptr_);
0677         this->traits_.swap(that.traits_);
0678         this->args_.swap(that.args_);
0679     }
0680 
0681     /// TODO document me
0682     ///
0683     template<typename Arg>
0684     match_results<BidiIter> &let(Arg const &arg)
0685     {
0686         typedef typename proto::result_of::left<Arg>::type left_type;
0687         typedef typename proto::result_of::right<Arg>::type right_type;
0688         typedef typename proto::result_of::value<left_type>::type arg_left_type;
0689         typedef typename proto::result_of::value<right_type>::type arg_right_type;
0690         BOOST_MPL_ASSERT((proto::matches<Arg, detail::ActionArgBinding>));
0691         BOOST_MPL_ASSERT((is_same<typename arg_left_type::type, arg_right_type>));
0692         this->args_[&typeid(proto::value(proto::left(arg)))] = &proto::value(proto::right(arg));
0693         return *this;
0694     }
0695 
0696     /// INTERNAL ONLY
0697     ///
0698     match_results<BidiIter> const &operator ()(regex_id_type regex_id, size_type index = 0) const
0699     {
0700         // BUGBUG this is linear, make it O(1)
0701         static match_results<BidiIter> const s_null;
0702 
0703         regex_id_filter_predicate<BidiIter> pred(regex_id);
0704         typename nested_results_type::const_iterator
0705             begin = this->nested_results_.begin()
0706           , end = this->nested_results_.end()
0707           , cur = detail::find_nth_if(begin, end, index, pred);
0708 
0709         return (cur == end) ? s_null : *cur;
0710     }
0711 
0712     /// INTERNAL ONLY
0713     ///
0714     match_results<BidiIter> const &operator ()(basic_regex<BidiIter> const &rex, std::size_t index = 0) const
0715     {
0716         return (*this)(rex.regex_id(), index);
0717     }
0718 
0719 private:
0720 
0721     friend struct detail::core_access<BidiIter>;
0722     typedef detail::results_extras<BidiIter> extras_type;
0723 
0724     /// INTERNAL ONLY
0725     ///
0726     void init_
0727     (
0728         regex_id_type regex_id
0729       , intrusive_ptr<detail::traits<char_type> const> const &tr
0730       , detail::sub_match_impl<BidiIter> *sub_matches
0731       , size_type size
0732       , std::vector<detail::named_mark<char_type> > const &named_marks
0733     )
0734     {
0735         this->traits_ = tr;
0736         this->regex_id_ = regex_id;
0737         this->named_marks_ = named_marks;
0738         detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size);
0739     }
0740 
0741     /// INTERNAL ONLY
0742     ///
0743     extras_type &get_extras_()
0744     {
0745         if(!this->extras_ptr_)
0746         {
0747             this->extras_ptr_ = new extras_type;
0748         }
0749 
0750         return *this->extras_ptr_;
0751     }
0752 
0753     /// INTERNAL ONLY
0754     ///
0755     void set_prefix_suffix_(BidiIter begin, BidiIter end)
0756     {
0757         this->base_ = begin;
0758         this->prefix_ = sub_match<BidiIter>(begin, this->sub_matches_[ 0 ].first, begin != this->sub_matches_[ 0 ].first);
0759         this->suffix_ = sub_match<BidiIter>(this->sub_matches_[ 0 ].second, end, this->sub_matches_[ 0 ].second != end);
0760 
0761         typename nested_results_type::iterator ibegin = this->nested_results_.begin();
0762         typename nested_results_type::iterator iend = this->nested_results_.end();
0763         for( ; ibegin != iend; ++ibegin )
0764         {
0765             ibegin->set_prefix_suffix_(begin, end);
0766         }
0767     }
0768 
0769     /// INTERNAL ONLY
0770     ///
0771     void reset_()
0772     {
0773         detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, 0, 0);
0774     }
0775 
0776     /// INTERNAL ONLY
0777     ///
0778     void set_base_(BidiIter base)
0779     {
0780         this->base_ = base;
0781 
0782         typename nested_results_type::iterator ibegin = this->nested_results_.begin();
0783         typename nested_results_type::iterator iend = this->nested_results_.end();
0784         for( ; ibegin != iend; ++ibegin )
0785         {
0786             ibegin->set_base_(base);
0787         }
0788     }
0789 
0790     /// INTERNAL ONLY
0791     ///
0792     const_reference at_(size_type sub) const
0793     {
0794         return this->sub_matches_[ sub ];
0795     }
0796 
0797     /// INTERNAL ONLY
0798     ///
0799     const_reference at_(detail::basic_mark_tag const &mark) const
0800     {
0801         return this->sub_matches_[ detail::get_mark_number(mark) ];
0802     }
0803 
0804     /// INTERNAL ONLY
0805     ///
0806     const_reference at_(char_type const *name) const
0807     {
0808         for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
0809         {
0810             if(this->named_marks_[i].name_ == name)
0811             {
0812                 return this->sub_matches_[ this->named_marks_[i].mark_nbr_ ];
0813             }
0814         }
0815         BOOST_THROW_EXCEPTION(
0816             regex_error(regex_constants::error_badmark, "invalid named back-reference")
0817         );
0818         // Should never execute, but if it does, this returns
0819         // a "null" sub_match.
0820         return this->sub_matches_[this->sub_matches_.size()];
0821     }
0822 
0823     /// INTERNAL ONLY
0824     ///
0825     const_reference at_(string_type const &name) const
0826     {
0827         return (*this)[name.c_str()];
0828     }
0829 
0830     /// INTERNAL ONLY
0831     ///
0832     template<typename OutputIterator, typename ForwardRange>
0833     OutputIterator format2_(OutputIterator out, ForwardRange const &result) const
0834     {
0835         return std::copy(boost::begin(result), boost::end(result), out);
0836     }
0837 
0838     /// INTERNAL ONLY
0839     ///
0840     template<typename OutputIterator, typename Char>
0841     OutputIterator format2_(OutputIterator out, Char const *const &result) const
0842     {
0843         Char const *tmp = result;
0844         BOOST_ASSERT(0 != tmp);
0845         for(; 0 != *tmp; ++tmp, ++out)
0846         {
0847             *out = *tmp;
0848         }
0849         return out;
0850     }
0851 
0852     /// INTERNAL ONLY
0853     ///
0854     template<typename OutputIterator, typename ForwardRange>
0855     OutputIterator format_
0856     (
0857         OutputIterator out
0858       , ForwardRange const &format
0859       , regex_constants::match_flag_type flags
0860       , mpl::size_t<0>
0861     ) const
0862     {
0863         typedef typename range_const_iterator<ForwardRange>::type iterator;
0864         iterator cur = boost::begin(format), end = boost::end(format);
0865 
0866         if(0 != (regex_constants::format_literal & flags))
0867         {
0868             return std::copy(cur, end, out);
0869         }
0870         else if(0 != (regex_constants::format_perl & flags))
0871         {
0872             return this->format_perl_(cur, end, out);
0873         }
0874         else if(0 != (regex_constants::format_sed & flags))
0875         {
0876             return this->format_sed_(cur, end, out);
0877         }
0878         else if(0 != (regex_constants::format_all & flags))
0879         {
0880             return this->format_all_(cur, end, out);
0881         }
0882 
0883         return this->format_ecma_262_(cur, end, out);
0884     }
0885 
0886     /// INTERNAL ONLY
0887     ///
0888     template<typename OutputIterator, typename Callable1>
0889     OutputIterator format_
0890     (
0891         OutputIterator out
0892       , Callable1 const &format
0893       , regex_constants::match_flag_type
0894       , mpl::size_t<1>
0895     ) const
0896     {
0897         #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0898         return this->format2_(out, detail::as_callable(format)(*this));
0899         #else
0900         return this->format2_(out, format(*this));
0901         #endif
0902     }
0903 
0904     /// INTERNAL ONLY
0905     ///
0906     template<typename OutputIterator, typename Callable2>
0907     OutputIterator format_
0908     (
0909         OutputIterator out
0910       , Callable2 const &format
0911       , regex_constants::match_flag_type
0912       , mpl::size_t<2>
0913     ) const
0914     {
0915         #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0916         return detail::as_callable(format)(*this, out);
0917         #else
0918         return format(*this, out);
0919         #endif
0920     }
0921 
0922     /// INTERNAL ONLY
0923     ///
0924     template<typename OutputIterator, typename Callable3>
0925     OutputIterator format_
0926     (
0927         OutputIterator out
0928       , Callable3 const &format
0929       , regex_constants::match_flag_type flags
0930       , mpl::size_t<3>
0931     ) const
0932     {
0933         #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0934         return detail::as_callable(format)(*this, out, flags);
0935         #else
0936         return format(*this, out, flags);
0937         #endif
0938     }
0939 
0940     /// INTERNAL ONLY
0941     ///
0942     template<typename OutputIterator, typename Expr>
0943     OutputIterator format_
0944     (
0945         OutputIterator out
0946       , Expr const &format
0947       , regex_constants::match_flag_type
0948       , mpl::size_t<4>
0949     ) const
0950     {
0951         // detail::ReplaceAlgo may be an incomplete type at this point, so
0952         // we can't construct it directly.
0953         typedef typename mpl::if_c<true, detail::ReplaceAlgo, OutputIterator>::type ReplaceAlgo;
0954         return this->format2_(out, ReplaceAlgo()(format, 0, *this));
0955     }
0956 
0957     /// INTERNAL ONLY
0958     ///
0959     template<typename ForwardIterator, typename OutputIterator>
0960     OutputIterator format_ecma_262_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
0961     {
0962         while(cur != end)
0963         {
0964             switch(*cur)
0965             {
0966             case BOOST_XPR_CHAR_(char_type, '$'):
0967                 out = this->format_backref_(++cur, end, out);
0968                 break;
0969 
0970             default:
0971                 *out++ = *cur++;
0972                 break;
0973             }
0974         }
0975 
0976         return out;
0977     }
0978 
0979     /// INTERNAL ONLY
0980     ///
0981     template<typename ForwardIterator, typename OutputIterator>
0982     OutputIterator format_sed_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
0983     {
0984         while(cur != end)
0985         {
0986             switch(*cur)
0987             {
0988             case BOOST_XPR_CHAR_(char_type, '&'):
0989                 ++cur;
0990                 out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
0991                 break;
0992 
0993             case BOOST_XPR_CHAR_(char_type, '\\'):
0994                 out = this->format_escape_(++cur, end, out);
0995                 break;
0996 
0997             default:
0998                 *out++ = *cur++;
0999                 break;
1000             }
1001         }
1002 
1003         return out;
1004     }
1005 
1006     /// INTERNAL ONLY
1007     ///
1008     template<typename ForwardIterator, typename OutputIterator>
1009     OutputIterator format_perl_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
1010     {
1011         detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
1012 
1013         while(cur != end)
1014         {
1015             switch(*cur)
1016             {
1017             case BOOST_XPR_CHAR_(char_type, '$'):
1018                 iout = this->format_backref_(++cur, end, iout);
1019                 break;
1020 
1021             case BOOST_XPR_CHAR_(char_type, '\\'):
1022                 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
1023                 {
1024                     iout = this->format_named_backref_(++cur, end, iout);
1025                 }
1026                 else
1027                 {
1028                     iout = this->format_escape_(cur, end, iout);
1029                 }
1030                 break;
1031 
1032             default:
1033                 *iout++ = *cur++;
1034                 break;
1035             }
1036         }
1037 
1038         return iout.base();
1039     }
1040 
1041     /// INTERNAL ONLY
1042     ///
1043     template<typename ForwardIterator, typename OutputIterator>
1044     OutputIterator format_all_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
1045     {
1046         detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
1047         iout = this->format_all_impl_(cur, end, iout);
1048         BOOST_XPR_ENSURE_(cur == end
1049           , regex_constants::error_paren, "unbalanced parentheses in format string");
1050         return iout.base();
1051     }
1052 
1053     /// INTERNAL ONLY
1054     ///
1055     template<typename ForwardIterator, typename OutputIterator>
1056     OutputIterator format_all_impl_(ForwardIterator &cur, ForwardIterator end, OutputIterator out, bool metacolon = false) const
1057     {
1058         int max = 0, sub = 0;
1059         detail::noop_output_iterator<char_type> noop;
1060 
1061         while(cur != end)
1062         {
1063             switch(*cur)
1064             {
1065             case BOOST_XPR_CHAR_(char_type, '$'):
1066                 out = this->format_backref_(++cur, end, out);
1067                 break;
1068 
1069             case BOOST_XPR_CHAR_(char_type, '\\'):
1070                 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
1071                 {
1072                     out = this->format_named_backref_(++cur, end, out);
1073                 }
1074                 else
1075                 {
1076                     out = this->format_escape_(cur, end, out);
1077                 }
1078                 break;
1079 
1080             case BOOST_XPR_CHAR_(char_type, '('):
1081                 out = this->format_all_impl_(++cur, end, out);
1082                 BOOST_XPR_ENSURE_(BOOST_XPR_CHAR_(char_type, ')') == *(cur-1)
1083                   , regex_constants::error_paren, "unbalanced parentheses in format string");
1084                 break;
1085 
1086             case BOOST_XPR_CHAR_(char_type, '?'):
1087                 BOOST_XPR_ENSURE_(++cur != end
1088                   , regex_constants::error_subreg, "malformed conditional in format string");
1089                 max = static_cast<int>(this->size() - 1);
1090                 sub = detail::toi(cur, end, *this->traits_, 10, max);
1091                 BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
1092                 if(this->sub_matches_[ sub ].matched)
1093                 {
1094                     out = this->format_all_impl_(cur, end, out, true);
1095                     if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
1096                         this->format_all_impl_(cur, end, noop);
1097                 }
1098                 else
1099                 {
1100                     this->format_all_impl_(cur, end, noop, true);
1101                     if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
1102                         out = this->format_all_impl_(cur, end, out);
1103                 }
1104                 return out;
1105 
1106             case BOOST_XPR_CHAR_(char_type, ':'):
1107                 if(metacolon)
1108                 {
1109                     BOOST_FALLTHROUGH;
1110             case BOOST_XPR_CHAR_(char_type, ')'):
1111                     ++cur;
1112                     return out;
1113                 }
1114                 BOOST_FALLTHROUGH;
1115 
1116             default:
1117                 *out++ = *cur++;
1118                 break;
1119             }
1120         }
1121 
1122         return out;
1123     }
1124 
1125     /// INTERNAL ONLY
1126     ///
1127     template<typename ForwardIterator, typename OutputIterator>
1128     OutputIterator format_backref_
1129     (
1130         ForwardIterator &cur
1131       , ForwardIterator end
1132       , OutputIterator out
1133     ) const
1134     {
1135         if(cur == end)
1136         {
1137             *out++ = BOOST_XPR_CHAR_(char_type, '$');
1138         }
1139         else if(BOOST_XPR_CHAR_(char_type, '$') == *cur)
1140         {
1141             *out++ = *cur++;
1142         }
1143         else if(BOOST_XPR_CHAR_(char_type, '&') == *cur) // whole match
1144         {
1145             ++cur;
1146             out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
1147         }
1148         else if(BOOST_XPR_CHAR_(char_type, '`') == *cur) // prefix
1149         {
1150             ++cur;
1151             out = std::copy(this->prefix().first, this->prefix().second, out);
1152         }
1153         else if(BOOST_XPR_CHAR_(char_type, '\'') == *cur) // suffix
1154         {
1155             ++cur;
1156             out = std::copy(this->suffix().first, this->suffix().second, out);
1157         }
1158         else if(-1 != this->traits_->value(*cur, 10)) // a sub-match
1159         {
1160             int max = static_cast<int>(this->size() - 1);
1161             int sub = detail::toi(cur, end, *this->traits_, 10, max);
1162             BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
1163             if(this->sub_matches_[ sub ].matched)
1164                 out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
1165         }
1166         else
1167         {
1168             *out++ = BOOST_XPR_CHAR_(char_type, '$');
1169             *out++ = *cur++;
1170         }
1171 
1172         return out;
1173     }
1174 
1175     /// INTERNAL ONLY
1176     ///
1177     template<typename ForwardIterator, typename OutputIterator>
1178     OutputIterator format_escape_
1179     (
1180         ForwardIterator &cur
1181       , ForwardIterator end
1182       , OutputIterator out
1183     ) const
1184     {
1185         using namespace regex_constants;
1186         ForwardIterator tmp;
1187         // define an unsigned type the same size as char_type
1188         typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
1189         BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
1190         typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
1191         numeric::converter<int, uchar_t, converstion_traits, detail::char_overflow_handler_> converter;
1192 
1193         if(cur == end)
1194         {
1195             *out++ = BOOST_XPR_CHAR_(char_type, '\\');
1196             return out;
1197         }
1198 
1199         char_type ch = *cur++;
1200         switch(ch)
1201         {
1202         case BOOST_XPR_CHAR_(char_type, 'a'):
1203             *out++ = BOOST_XPR_CHAR_(char_type, '\a');
1204             break;
1205 
1206         case BOOST_XPR_CHAR_(char_type, 'e'):
1207             *out++ = converter(27);
1208             break;
1209 
1210         case BOOST_XPR_CHAR_(char_type, 'f'):
1211             *out++ = BOOST_XPR_CHAR_(char_type, '\f');
1212             break;
1213 
1214         case BOOST_XPR_CHAR_(char_type, 'n'):
1215             *out++ = BOOST_XPR_CHAR_(char_type, '\n');
1216             break;
1217 
1218         case BOOST_XPR_CHAR_(char_type, 'r'):
1219             *out++ = BOOST_XPR_CHAR_(char_type, '\r');
1220             break;
1221 
1222         case BOOST_XPR_CHAR_(char_type, 't'):
1223             *out++ = BOOST_XPR_CHAR_(char_type, '\t');
1224             break;
1225 
1226         case BOOST_XPR_CHAR_(char_type, 'v'):
1227             *out++ = BOOST_XPR_CHAR_(char_type, '\v');
1228             break;
1229 
1230         case BOOST_XPR_CHAR_(char_type, 'x'):
1231             BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
1232             if(BOOST_XPR_CHAR_(char_type, '{') == *cur)
1233             {
1234                 BOOST_XPR_ENSURE_(++cur != end, error_escape, "unexpected end of format found");
1235                 tmp = cur;
1236                 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xffff));
1237                 BOOST_XPR_ENSURE_(4 == std::distance(tmp, cur) && cur != end && BOOST_XPR_CHAR_(char_type, '}') == *cur++
1238                   , error_escape, "invalid hex escape : must be \\x { HexDigit HexDigit HexDigit HexDigit }");
1239             }
1240             else
1241             {
1242                 tmp = cur;
1243                 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xff));
1244                 BOOST_XPR_ENSURE_(2 == std::distance(tmp, cur), error_escape
1245                   , "invalid hex escape : must be \\x HexDigit HexDigit");
1246             }
1247             break;
1248 
1249         case BOOST_XPR_CHAR_(char_type, 'c'):
1250             BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
1251             BOOST_XPR_ENSURE_
1252             (
1253                 this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *cur)
1254              || this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *cur)
1255               , error_escape
1256               , "invalid escape control letter; must be one of a-z or A-Z"
1257             );
1258             // Convert to character according to ECMA-262, section 15.10.2.10:
1259             *out++ = converter(*cur % 32);
1260             ++cur;
1261             break;
1262 
1263         case BOOST_XPR_CHAR_(char_type, 'l'):
1264             if(!set_transform(out, detail::op_lower, detail::scope_next))
1265             {
1266                 *out++ = BOOST_XPR_CHAR_(char_type, 'l');
1267             }
1268             break;
1269 
1270         case BOOST_XPR_CHAR_(char_type, 'L'):
1271             if(!set_transform(out, detail::op_lower, detail::scope_rest))
1272             {
1273                 *out++ = BOOST_XPR_CHAR_(char_type, 'L');
1274             }
1275             break;
1276 
1277         case BOOST_XPR_CHAR_(char_type, 'u'):
1278             if(!set_transform(out, detail::op_upper, detail::scope_next))
1279             {
1280                 *out++ = BOOST_XPR_CHAR_(char_type, 'u');
1281             }
1282             break;
1283 
1284         case BOOST_XPR_CHAR_(char_type, 'U'):
1285             if(!set_transform(out, detail::op_upper, detail::scope_rest))
1286             {
1287                 *out++ = BOOST_XPR_CHAR_(char_type, 'U');
1288             }
1289             break;
1290 
1291         case BOOST_XPR_CHAR_(char_type, 'E'):
1292             if(!set_transform(out, detail::op_none, detail::scope_rest))
1293             {
1294                 *out++ = BOOST_XPR_CHAR_(char_type, 'E');
1295             }
1296             break;
1297 
1298         default:
1299             // BUGBUG what about backreferences like \12 ?
1300             if(0 < this->traits_->value(ch, 10))
1301             {
1302                 int sub = this->traits_->value(ch, 10);
1303                 if(this->sub_matches_[ sub ].matched)
1304                     out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
1305             }
1306             else
1307             {
1308                 *out++ = ch;
1309             }
1310             break;
1311         }
1312 
1313         return out;
1314     }
1315 
1316     /// INTERNAL ONLY
1317     ///
1318     template<typename ForwardIterator, typename OutputIterator>
1319     OutputIterator format_named_backref_
1320     (
1321         ForwardIterator &cur
1322       , ForwardIterator end
1323       , OutputIterator out
1324     ) const
1325     {
1326         using namespace regex_constants;
1327         BOOST_XPR_ENSURE_(cur != end && BOOST_XPR_CHAR_(char_type, '<') == *cur++
1328             , error_badmark, "invalid named back-reference");
1329         ForwardIterator begin = cur;
1330         for(; cur != end && BOOST_XPR_CHAR_(char_type, '>') != *cur; ++cur)
1331         {}
1332         BOOST_XPR_ENSURE_(cur != begin && cur != end && BOOST_XPR_CHAR_(char_type, '>') == *cur
1333             , error_badmark, "invalid named back-reference");
1334 
1335         string_type name(begin, cur++);
1336         for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
1337         {
1338             if(this->named_marks_[i].name_ == name)
1339             {
1340                 std::size_t sub = this->named_marks_[i].mark_nbr_;
1341                 return std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
1342             }
1343         }
1344 
1345         BOOST_THROW_EXCEPTION(regex_error(error_badmark, "invalid named back-reference"));
1346         // Should never get here
1347         return out;
1348     }
1349 
1350     regex_id_type regex_id_;
1351     detail::sub_match_vector<BidiIter> sub_matches_;
1352     boost::optional<BidiIter> base_;
1353     boost::optional<sub_match<BidiIter> > prefix_;
1354     boost::optional<sub_match<BidiIter> > suffix_;
1355     nested_results_type nested_results_;
1356     intrusive_ptr<extras_type> extras_ptr_;
1357     intrusive_ptr<detail::traits<char_type> const> traits_;
1358     detail::action_args_type args_;
1359     std::vector<detail::named_mark<char_type> > named_marks_;
1360 };
1361 
1362 ///////////////////////////////////////////////////////////////////////////////
1363 // regex_id_filter_predicate
1364 //
1365 template<typename BidiIter>
1366 struct regex_id_filter_predicate
1367 {
1368     typedef match_results<BidiIter> argument_type;
1369     typedef bool result_type;
1370 
1371     regex_id_filter_predicate(regex_id_type regex_id)
1372       : regex_id_(regex_id)
1373     {
1374     }
1375 
1376     bool operator ()(match_results<BidiIter> const &res) const
1377     {
1378         return this->regex_id_ == res.regex_id();
1379     }
1380 
1381 private:
1382 
1383     regex_id_type regex_id_;
1384 };
1385 
1386 }} // namespace boost::xpressive
1387 
1388 #ifdef BOOST_HAS_CONCEPTS
1389 // Better living through concepts. :-P
1390 namespace std
1391 {
1392     template<typename Iter_, typename Char_>
1393     concept_map OutputIterator<
1394         boost::xpressive::detail::case_converting_iterator<Iter_, Char_>
1395       , Char_
1396     >
1397     {};
1398 
1399     template<typename Char_>
1400     concept_map OutputIterator<
1401         boost::xpressive::detail::noop_output_iterator<Char_>
1402       , Char_
1403     >
1404     {};
1405 }
1406 #endif
1407 
1408 #endif