1 /*=============================================================================
2 Copyright (c) 2001, Daniel C. Nuffer
3 http://spirit.sourceforge.net/
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
9 #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
11 #include <boost/config.hpp>
12 #include <boost/throw_exception.hpp>
16 #include <algorithm> // for std::swap
17 #include <exception> // for std::exception
18 #include <boost/limits.hpp>
20 #include <boost/spirit/home/classic/namespace.hpp>
21 #include <boost/spirit/home/classic/core/assert.hpp> // for BOOST_SPIRIT_ASSERT
22 #include <boost/spirit/home/classic/iterator/fixed_size_queue.hpp>
24 #include <boost/spirit/home/classic/iterator/multi_pass_fwd.hpp>
26 namespace boost { namespace spirit {
28 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
32 inline void mp_swap(T& t1, T& t2);
35 namespace multi_pass_policies
38 ///////////////////////////////////////////////////////////////////////////////
40 // Implementation of an OwnershipPolicy used by multi_pass.
42 // Implementation modified from RefCounted class from the Loki library by
43 // Andrei Alexandrescu
44 ///////////////////////////////////////////////////////////////////////////////
49 : count(new std::size_t(1))
52 ref_counted(ref_counted const& x)
56 // clone is called when a copy of the iterator is made, so increment
63 // called when a copy is deleted. Decrement the ref-count. Return
64 // value of true indicates that the last copy has been released.
76 void swap(ref_counted& x)
78 impl::mp_swap(count, x.count);
82 // returns true if there is only one iterator in existence.
83 // std_deque StoragePolicy will free it's buffered data if this
94 ///////////////////////////////////////////////////////////////////////////////
96 // Implementation of an OwnershipPolicy used by multi_pass
97 // This ownership policy dictates that the first iterator created will
98 // determine the lifespan of the shared components. This works well for
99 // spirit, since no dynamic allocation of iterators is done, and all copies
100 // are make on the stack.
102 // There is a caveat about using this policy together with the std_deque
103 // StoragePolicy. Since first_owner always returns false from unique(),
104 // std_deque will only release the queued data if clear_queue() is called.
105 ///////////////////////////////////////////////////////////////////////////////
113 first_owner(first_owner const&)
121 // return true to indicate deletion of resources
127 void swap(first_owner&)
129 // if we're the first, we still remain the first, even if assigned
130 // to, so don't swap first_. swap is only called from operator=
136 return false; // no way to know, so always return false
143 ///////////////////////////////////////////////////////////////////////////////
144 // class illegal_backtracking
145 // thrown by buf_id_check CheckingPolicy if an instance of an iterator is
146 // used after another one has invalidated the queue
147 ///////////////////////////////////////////////////////////////////////////////
148 class BOOST_SYMBOL_VISIBLE illegal_backtracking : public std::exception
152 illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW {}
153 ~illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW {}
156 what() const BOOST_NOEXCEPT_OR_NOTHROW
157 { return "BOOST_SPIRIT_CLASSIC_NS::illegal_backtracking"; }
160 ///////////////////////////////////////////////////////////////////////////////
161 // class buf_id_check
162 // Implementation of the CheckingPolicy used by multi_pass
163 // This policy is most effective when used together with the std_deque
165 // If used with the fixed_size_queue StoragePolicy, it will not detect
166 // iterator derefereces that are out of the range of the queue.
167 ///////////////////////////////////////////////////////////////////////////////
172 : shared_buf_id(new unsigned long(0))
176 buf_id_check(buf_id_check const& x)
177 : shared_buf_id(x.shared_buf_id)
181 // will be called from the destructor of the last iterator.
184 delete shared_buf_id;
188 void swap(buf_id_check& x)
190 impl::mp_swap(shared_buf_id, x.shared_buf_id);
191 impl::mp_swap(buf_id, x.buf_id);
194 // called to verify that everything is okay.
195 void check_if_valid() const
197 if (buf_id != *shared_buf_id)
199 boost::throw_exception(illegal_backtracking());
203 // called from multi_pass::clear_queue, so we can increment the count
211 unsigned long* shared_buf_id;
212 unsigned long buf_id;
215 ///////////////////////////////////////////////////////////////////////////////
217 // Implementation of the CheckingPolicy used by multi_pass
218 // It does not do anything :-)
219 ///////////////////////////////////////////////////////////////////////////////
224 no_check(no_check const&) {}
226 void swap(no_check&) {}
227 void check_if_valid() const {}
228 void clear_queue() {}
231 ///////////////////////////////////////////////////////////////////////////////
233 // Implementation of the StoragePolicy used by multi_pass
234 // This stores all data in a std::deque, and keeps an offset to the current
235 // position. It stores all the data unless there is only one
236 // iterator using the queue.
237 // Note: a position is used instead of an iterator, because a push_back on
238 // a deque can invalidate any iterators.
239 ///////////////////////////////////////////////////////////////////////////////
244 template <typename ValueT>
249 typedef std::deque<ValueT> queue_type;
250 queue_type* queuedElements;
251 mutable typename queue_type::size_type queuePosition;
255 : queuedElements(new queue_type)
259 inner(inner const& x)
260 : queuedElements(x.queuedElements)
261 , queuePosition(x.queuePosition)
264 // will be called from the destructor of the last iterator.
267 BOOST_SPIRIT_ASSERT(NULL != queuedElements);
268 delete queuedElements;
274 impl::mp_swap(queuedElements, x.queuedElements);
275 impl::mp_swap(queuePosition, x.queuePosition);
278 // This is called when the iterator is dereferenced. It's a template
279 // method so we can recover the type of the multi_pass iterator
280 // and call unique and access the m_input data member.
281 template <typename MultiPassT>
282 static typename MultiPassT::reference dereference(MultiPassT const& mp)
284 if (mp.queuePosition == mp.queuedElements->size())
286 // check if this is the only iterator
289 // free up the memory used by the queue.
290 if (mp.queuedElements->size() > 0)
292 mp.queuedElements->clear();
293 mp.queuePosition = 0;
296 return mp.get_input();
300 return (*mp.queuedElements)[mp.queuePosition];
304 // This is called when the iterator is incremented. It's a template
305 // method so we can recover the type of the multi_pass iterator
306 // and call unique and access the m_input data member.
307 template <typename MultiPassT>
308 static void increment(MultiPassT& mp)
310 if (mp.queuePosition == mp.queuedElements->size())
312 // check if this is the only iterator
315 // free up the memory used by the queue.
316 if (mp.queuedElements->size() > 0)
318 mp.queuedElements->clear();
319 mp.queuePosition = 0;
324 mp.queuedElements->push_back(mp.get_input());
336 // called to forcibly clear the queue
339 queuedElements->clear();
343 // called to determine whether the iterator is an eof iterator
344 template <typename MultiPassT>
345 static bool is_eof(MultiPassT const& mp)
347 return mp.queuePosition == mp.queuedElements->size() &&
351 // called by operator==
352 bool equal_to(inner const& x) const
354 return queuePosition == x.queuePosition;
357 // called by operator<
358 bool less_than(inner const& x) const
360 return queuePosition < x.queuePosition;
364 }; // class std_deque
367 ///////////////////////////////////////////////////////////////////////////////
368 // class fixed_size_queue
369 // Implementation of the StoragePolicy used by multi_pass
370 // fixed_size_queue keeps a circular buffer (implemented by
371 // BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue class) that is size N+1 and stores N elements.
372 // It is up to the user to ensure that there is enough look ahead for their
373 // grammar. Currently there is no way to tell if an iterator is pointing
374 // to forgotten data. The leading iterator will put an item in the queue
375 // and remove one when it is incremented. No dynamic allocation is done,
376 // except on creation of the queue (fixed_size_queue constructor).
377 ///////////////////////////////////////////////////////////////////////////////
378 template < std::size_t N>
379 class fixed_size_queue
383 template <typename ValueT>
388 typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<ValueT, N> queue_type;
389 queue_type * queuedElements;
390 mutable typename queue_type::iterator queuePosition;
394 : queuedElements(new queue_type)
395 , queuePosition(queuedElements->begin())
398 inner(inner const& x)
399 : queuedElements(x.queuedElements)
400 , queuePosition(x.queuePosition)
403 // will be called from the destructor of the last iterator.
406 BOOST_SPIRIT_ASSERT(NULL != queuedElements);
407 delete queuedElements;
413 impl::mp_swap(queuedElements, x.queuedElements);
414 impl::mp_swap(queuePosition, x.queuePosition);
417 // This is called when the iterator is dereferenced. It's a template
418 // method so we can recover the type of the multi_pass iterator
419 // and access the m_input data member.
420 template <typename MultiPassT>
421 static typename MultiPassT::reference dereference(MultiPassT const& mp)
423 if (mp.queuePosition == mp.queuedElements->end())
425 return mp.get_input();
429 return *mp.queuePosition;
433 // This is called when the iterator is incremented. It's a template
434 // method so we can recover the type of the multi_pass iterator
435 // and access the m_input data member.
436 template <typename MultiPassT>
437 static void increment(MultiPassT& mp)
439 if (mp.queuePosition == mp.queuedElements->end())
441 // don't let the queue get larger than N
442 if (mp.queuedElements->size() >= N)
443 mp.queuedElements->pop_front();
445 mp.queuedElements->push_back(mp.get_input());
455 // called to determine whether the iterator is an eof iterator
456 template <typename MultiPassT>
457 static bool is_eof(MultiPassT const& mp)
459 return mp.queuePosition == mp.queuedElements->end() &&
463 // called by operator==
464 bool equal_to(inner const& x) const
466 return queuePosition == x.queuePosition;
469 // called by operator<
470 bool less_than(inner const& x) const
472 return queuePosition < x.queuePosition;
476 }; // class fixed_size_queue
479 ///////////////////////////////////////////////////////////////////////////////
480 // class input_iterator
481 // Implementation of the InputPolicy used by multi_pass
482 // input_iterator encapsulates an input iterator of type InputT
483 ///////////////////////////////////////////////////////////////////////////////
488 template <typename InputT>
493 typename std::iterator_traits<InputT>::value_type
497 typedef result_type value_type;
501 Data(InputT const &input_)
502 : input(input_), was_initialized(false)
507 bool was_initialized;
510 // Needed by compilers not implementing the resolution to DR45. For
512 // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
518 typename std::iterator_traits<InputT>::difference_type
521 typename std::iterator_traits<InputT>::pointer
524 typename std::iterator_traits<InputT>::reference
536 inner(inner const& x)
546 bool same_input(inner const& x) const
548 return data == x.data;
552 typename std::iterator_traits<InputT>::value_type
556 impl::mp_swap(data, x.data);
559 void ensure_initialized() const
561 if (data && !data->was_initialized) {
562 data->curtok = *data->input; // get the first token
563 data->was_initialized = true;
568 reference get_input() const
570 BOOST_SPIRIT_ASSERT(NULL != data);
571 ensure_initialized();
577 BOOST_SPIRIT_ASSERT(NULL != data);
578 data->was_initialized = false; // should get the next token
582 bool input_at_eof() const
584 return !data || data->input == InputT();
593 ///////////////////////////////////////////////////////////////////////////////
595 // Implementation of the InputPolicy used by multi_pass
596 // lex_input gets tokens (ints) from yylex()
597 ///////////////////////////////////////////////////////////////////////////////
602 template <typename InputT>
606 typedef int value_type;
607 typedef std::ptrdiff_t difference_type;
608 typedef int* pointer;
609 typedef int& reference;
620 inner(inner const& x)
630 bool same_input(inner const& x) const
632 return curtok == x.curtok;
637 impl::mp_swap(curtok, x.curtok);
641 reference get_input() const
652 bool input_at_eof() const
664 ///////////////////////////////////////////////////////////////////////////////
665 // class functor_input
666 // Implementation of the InputPolicy used by multi_pass
667 // functor_input gets tokens from a functor
668 // Note: the functor must have a typedef for result_type
669 // It also must have a static variable of type result_type defined to
670 // represent eof that is called eof.
671 ///////////////////////////////////////////////////////////////////////////////
676 template <typename FunctorT>
679 typedef typename FunctorT::result_type result_type;
681 typedef result_type value_type;
682 typedef std::ptrdiff_t difference_type;
683 typedef result_type* pointer;
684 typedef result_type& reference;
692 inner(FunctorT const& x)
693 : ftor(new FunctorT(x))
694 , curtok(new result_type((*ftor)()))
697 inner(inner const& x)
710 bool same_input(inner const& x) const
712 return ftor == x.ftor;
717 impl::mp_swap(curtok, x.curtok);
718 impl::mp_swap(ftor, x.ftor);
722 reference get_input() const
734 bool input_at_eof() const
736 return !curtok || *curtok == ftor->eof;
739 FunctorT& get_functor() const
753 } // namespace multi_pass_policies
755 ///////////////////////////////////////////////////////////////////////////////
756 // iterator_base_creator
757 ///////////////////////////////////////////////////////////////////////////////
759 namespace iterator_ { namespace impl {
761 // Meta-function to generate a std::iterator<>-like base class for multi_pass.
762 template <typename InputPolicyT, typename InputT>
763 struct iterator_base_creator
765 typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t;
768 typedef std::forward_iterator_tag iterator_category;
769 typedef typename input_t::value_type value_type;
770 typedef typename input_t::difference_type difference_type;
771 typedef typename input_t::pointer pointer;
772 typedef typename input_t::reference reference;
778 ///////////////////////////////////////////////////////////////////////////////
779 // class template multi_pass
780 ///////////////////////////////////////////////////////////////////////////////
782 // The default multi_pass instantiation uses a ref-counted std_deque scheme.
786 typename InputPolicy,
787 typename OwnershipPolicy,
788 typename CheckingPolicy,
789 typename StoragePolicy
792 : public OwnershipPolicy
793 , public CheckingPolicy
794 , public StoragePolicy::template inner<
795 typename InputPolicy::template inner<InputT>::value_type>
796 , public InputPolicy::template inner<InputT>
797 , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
799 typedef OwnershipPolicy OP;
800 typedef CheckingPolicy CHP;
801 typedef typename StoragePolicy::template inner<
802 typename InputPolicy::template inner<InputT>::value_type> SP;
803 typedef typename InputPolicy::template inner<InputT> IP;
805 iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
809 typedef typename IB::value_type value_type;
810 typedef typename IB::difference_type difference_type;
811 typedef typename IB::reference reference;
812 typedef typename IB::pointer pointer;
813 typedef InputT iterator_type;
816 explicit multi_pass(InputT input);
818 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
820 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
824 multi_pass(multi_pass const&);
825 multi_pass& operator=(multi_pass const&);
827 void swap(multi_pass& x);
829 reference operator*() const;
830 pointer operator->() const;
831 multi_pass& operator++();
832 multi_pass operator++(int);
836 bool operator==(const multi_pass& y) const;
837 bool operator<(const multi_pass& y) const;
839 private: // helper functions
846 typename InputPolicy,
847 typename OwnershipPolicy,
848 typename CheckingPolicy,
849 typename StoragePolicy
852 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
864 typename InputPolicy,
865 typename OwnershipPolicy,
866 typename CheckingPolicy,
867 typename StoragePolicy
870 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
871 multi_pass(InputT input)
879 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
880 // The standard library shipped with gcc-3.1 has a bug in
881 // bits/basic_string.tcc. It tries to use iter::iter(0) to
882 // construct an iterator. Ironically, this happens in sanity
883 // checking code that isn't required by the standard.
884 // The workaround is to provide an additional constructor that
885 // ignores its int argument and behaves like the default constructor.
889 typename InputPolicy,
890 typename OwnershipPolicy,
891 typename CheckingPolicy,
892 typename StoragePolicy
895 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
903 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
908 typename InputPolicy,
909 typename OwnershipPolicy,
910 typename CheckingPolicy,
911 typename StoragePolicy
914 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
928 typename InputPolicy,
929 typename OwnershipPolicy,
930 typename CheckingPolicy,
931 typename StoragePolicy
934 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
948 typename InputPolicy,
949 typename OwnershipPolicy,
950 typename CheckingPolicy,
951 typename StoragePolicy
954 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
955 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
967 typename InputPolicy,
968 typename OwnershipPolicy,
969 typename CheckingPolicy,
970 typename StoragePolicy
973 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
985 typename InputPolicy,
986 typename OwnershipPolicy,
987 typename CheckingPolicy,
988 typename StoragePolicy
991 typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
993 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
996 CHP::check_if_valid();
997 return SP::dereference(*this);
1003 typename InputPolicy,
1004 typename OwnershipPolicy,
1005 typename CheckingPolicy,
1006 typename StoragePolicy
1009 typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1011 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1014 return &(operator*());
1020 typename InputPolicy,
1021 typename OwnershipPolicy,
1022 typename CheckingPolicy,
1023 typename StoragePolicy
1026 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
1027 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1030 CHP::check_if_valid();
1031 SP::increment(*this);
1038 typename InputPolicy,
1039 typename OwnershipPolicy,
1040 typename CheckingPolicy,
1041 typename StoragePolicy
1044 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
1045 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1065 typename InputPolicy,
1066 typename OwnershipPolicy,
1067 typename CheckingPolicy,
1068 typename StoragePolicy
1071 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1081 typename InputPolicy,
1082 typename OwnershipPolicy,
1083 typename CheckingPolicy,
1084 typename StoragePolicy
1087 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1090 return SP::is_eof(*this);
1097 typename InputPolicy,
1098 typename OwnershipPolicy,
1099 typename CheckingPolicy,
1100 typename StoragePolicy
1103 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1104 operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1105 StoragePolicy>& y) const
1107 bool is_eof_ = SP::is_eof(*this);
1108 bool y_is_eof_ = SP::is_eof(y);
1110 if (is_eof_ && y_is_eof_)
1112 return true; // both are EOF
1114 else if (is_eof_ ^ y_is_eof_)
1116 return false; // one is EOF, one isn't
1118 else if (!IP::same_input(y))
1124 return SP::equal_to(y);
1131 typename InputPolicy,
1132 typename OwnershipPolicy,
1133 typename CheckingPolicy,
1134 typename StoragePolicy
1137 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1138 operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1139 StoragePolicy>& y) const
1141 return SP::less_than(y);
1147 typename InputPolicy,
1148 typename OwnershipPolicy,
1149 typename CheckingPolicy,
1150 typename StoragePolicy
1154 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1156 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1165 typename InputPolicy,
1166 typename OwnershipPolicy,
1167 typename CheckingPolicy,
1168 typename StoragePolicy
1172 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1174 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1183 typename InputPolicy,
1184 typename OwnershipPolicy,
1185 typename CheckingPolicy,
1186 typename StoragePolicy
1190 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1192 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1201 typename InputPolicy,
1202 typename OwnershipPolicy,
1203 typename CheckingPolicy,
1204 typename StoragePolicy
1208 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1210 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1216 ///// Generator function
1217 template <typename InputT>
1218 inline multi_pass<InputT,
1219 multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
1220 multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>
1221 make_multi_pass(InputT i)
1223 return multi_pass<InputT,
1224 multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
1225 multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>(i);
1228 // this could be a template typedef, since such a thing doesn't
1229 // exist in C++, we'll use inheritance to accomplish the same thing.
1231 template <typename InputT, std::size_t N>
1235 multi_pass_policies::input_iterator,
1236 multi_pass_policies::first_owner,
1237 multi_pass_policies::no_check,
1238 multi_pass_policies::fixed_size_queue<N> >
1242 multi_pass_policies::input_iterator,
1243 multi_pass_policies::first_owner,
1244 multi_pass_policies::no_check,
1245 multi_pass_policies::fixed_size_queue<N> > base_t;
1250 explicit look_ahead(InputT x)
1253 look_ahead(look_ahead const& x)
1256 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1257 look_ahead(int) // workaround for a bug in the library
1258 : base_t() {} // shipped with gcc 3.1
1259 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1261 // default generated operators destructor and assignment operator are okay.
1267 typename InputPolicy,
1268 typename OwnershipPolicy,
1269 typename CheckingPolicy,
1270 typename StoragePolicy
1274 InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1277 InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1285 template <typename T>
1286 inline void mp_swap(T& t1, T& t2)
1289 using BOOST_SPIRIT_CLASSIC_NS::swap;
1294 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
1296 }} // namespace BOOST_SPIRIT_CLASSIC_NS
1298 #endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP