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>
19 #include <boost/iterator.hpp>
21 #include <boost/spirit/home/classic/namespace.hpp>
22 #include <boost/spirit/home/classic/core/assert.hpp> // for BOOST_SPIRIT_ASSERT
23 #include <boost/spirit/home/classic/iterator/fixed_size_queue.hpp>
24 #include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
26 #include <boost/spirit/home/classic/iterator/multi_pass_fwd.hpp>
28 namespace boost { namespace spirit {
30 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
34 inline void mp_swap(T& t1, T& t2);
37 namespace multi_pass_policies
40 ///////////////////////////////////////////////////////////////////////////////
42 // Implementation of an OwnershipPolicy used by multi_pass.
44 // Implementation modified from RefCounted class from the Loki library by
45 // Andrei Alexandrescu
46 ///////////////////////////////////////////////////////////////////////////////
51 : count(new std::size_t(1))
54 ref_counted(ref_counted const& x)
58 // clone is called when a copy of the iterator is made, so increment
65 // called when a copy is deleted. Decrement the ref-count. Return
66 // value of true indicates that the last copy has been released.
78 void swap(ref_counted& x)
80 impl::mp_swap(count, x.count);
84 // returns true if there is only one iterator in existence.
85 // std_deque StoragePolicy will free it's buffered data if this
96 ///////////////////////////////////////////////////////////////////////////////
98 // Implementation of an OwnershipPolicy used by multi_pass
99 // This ownership policy dictates that the first iterator created will
100 // determine the lifespan of the shared components. This works well for
101 // spirit, since no dynamic allocation of iterators is done, and all copies
102 // are make on the stack.
104 // There is a caveat about using this policy together with the std_deque
105 // StoragePolicy. Since first_owner always returns false from unique(),
106 // std_deque will only release the queued data if clear_queue() is called.
107 ///////////////////////////////////////////////////////////////////////////////
115 first_owner(first_owner const&)
123 // return true to indicate deletion of resources
129 void swap(first_owner&)
131 // if we're the first, we still remain the first, even if assigned
132 // to, so don't swap first_. swap is only called from operator=
138 return false; // no way to know, so always return false
145 ///////////////////////////////////////////////////////////////////////////////
146 // class illegal_backtracking
147 // thrown by buf_id_check CheckingPolicy if an instance of an iterator is
148 // used after another one has invalidated the queue
149 ///////////////////////////////////////////////////////////////////////////////
150 class illegal_backtracking : public std::exception
154 illegal_backtracking() throw() {}
155 ~illegal_backtracking() throw() {}
159 { return "BOOST_SPIRIT_CLASSIC_NS::illegal_backtracking"; }
162 ///////////////////////////////////////////////////////////////////////////////
163 // class buf_id_check
164 // Implementation of the CheckingPolicy used by multi_pass
165 // This policy is most effective when used together with the std_deque
167 // If used with the fixed_size_queue StoragePolicy, it will not detect
168 // iterator derefereces that are out of the range of the queue.
169 ///////////////////////////////////////////////////////////////////////////////
174 : shared_buf_id(new unsigned long(0))
178 buf_id_check(buf_id_check const& x)
179 : shared_buf_id(x.shared_buf_id)
183 // will be called from the destructor of the last iterator.
186 delete shared_buf_id;
190 void swap(buf_id_check& x)
192 impl::mp_swap(shared_buf_id, x.shared_buf_id);
193 impl::mp_swap(buf_id, x.buf_id);
196 // called to verify that everything is okay.
197 void check_if_valid() const
199 if (buf_id != *shared_buf_id)
201 boost::throw_exception(illegal_backtracking());
205 // called from multi_pass::clear_queue, so we can increment the count
213 unsigned long* shared_buf_id;
214 unsigned long buf_id;
217 ///////////////////////////////////////////////////////////////////////////////
219 // Implementation of the CheckingPolicy used by multi_pass
220 // It does not do anything :-)
221 ///////////////////////////////////////////////////////////////////////////////
226 no_check(no_check const&) {}
228 void swap(no_check&) {}
229 void check_if_valid() const {}
230 void clear_queue() {}
233 ///////////////////////////////////////////////////////////////////////////////
235 // Implementation of the StoragePolicy used by multi_pass
236 // This stores all data in a std::deque, and keeps an offset to the current
237 // position. It stores all the data unless there is only one
238 // iterator using the queue.
239 // Note: a position is used instead of an iterator, because a push_back on
240 // a deque can invalidate any iterators.
241 ///////////////////////////////////////////////////////////////////////////////
246 template <typename ValueT>
251 typedef std::deque<ValueT> queue_type;
252 queue_type* queuedElements;
253 mutable typename queue_type::size_type queuePosition;
257 : queuedElements(new queue_type)
261 inner(inner const& x)
262 : queuedElements(x.queuedElements)
263 , queuePosition(x.queuePosition)
266 // will be called from the destructor of the last iterator.
269 BOOST_SPIRIT_ASSERT(NULL != queuedElements);
270 delete queuedElements;
276 impl::mp_swap(queuedElements, x.queuedElements);
277 impl::mp_swap(queuePosition, x.queuePosition);
280 // This is called when the iterator is dereferenced. It's a template
281 // method so we can recover the type of the multi_pass iterator
282 // and call unique and access the m_input data member.
283 template <typename MultiPassT>
284 static typename MultiPassT::reference dereference(MultiPassT const& mp)
286 if (mp.queuePosition == mp.queuedElements->size())
288 // check if this is the only iterator
291 // free up the memory used by the queue.
292 if (mp.queuedElements->size() > 0)
294 mp.queuedElements->clear();
295 mp.queuePosition = 0;
298 return mp.get_input();
302 return (*mp.queuedElements)[mp.queuePosition];
306 // This is called when the iterator is incremented. It's a template
307 // method so we can recover the type of the multi_pass iterator
308 // and call unique and access the m_input data member.
309 template <typename MultiPassT>
310 static void increment(MultiPassT& mp)
312 if (mp.queuePosition == mp.queuedElements->size())
314 // check if this is the only iterator
317 // free up the memory used by the queue.
318 if (mp.queuedElements->size() > 0)
320 mp.queuedElements->clear();
321 mp.queuePosition = 0;
326 mp.queuedElements->push_back(mp.get_input());
338 // called to forcibly clear the queue
341 queuedElements->clear();
345 // called to determine whether the iterator is an eof iterator
346 template <typename MultiPassT>
347 static bool is_eof(MultiPassT const& mp)
349 return mp.queuePosition == mp.queuedElements->size() &&
353 // called by operator==
354 bool equal_to(inner const& x) const
356 return queuePosition == x.queuePosition;
359 // called by operator<
360 bool less_than(inner const& x) const
362 return queuePosition < x.queuePosition;
366 }; // class std_deque
369 ///////////////////////////////////////////////////////////////////////////////
370 // class fixed_size_queue
371 // Implementation of the StoragePolicy used by multi_pass
372 // fixed_size_queue keeps a circular buffer (implemented by
373 // BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue class) that is size N+1 and stores N elements.
374 // It is up to the user to ensure that there is enough look ahead for their
375 // grammar. Currently there is no way to tell if an iterator is pointing
376 // to forgotten data. The leading iterator will put an item in the queue
377 // and remove one when it is incremented. No dynamic allocation is done,
378 // except on creation of the queue (fixed_size_queue constructor).
379 ///////////////////////////////////////////////////////////////////////////////
380 template < std::size_t N>
381 class fixed_size_queue
385 template <typename ValueT>
390 typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<ValueT, N> queue_type;
391 queue_type * queuedElements;
392 mutable typename queue_type::iterator queuePosition;
396 : queuedElements(new queue_type)
397 , queuePosition(queuedElements->begin())
400 inner(inner const& x)
401 : queuedElements(x.queuedElements)
402 , queuePosition(x.queuePosition)
405 // will be called from the destructor of the last iterator.
408 BOOST_SPIRIT_ASSERT(NULL != queuedElements);
409 delete queuedElements;
415 impl::mp_swap(queuedElements, x.queuedElements);
416 impl::mp_swap(queuePosition, x.queuePosition);
419 // This is called when the iterator is dereferenced. It's a template
420 // method so we can recover the type of the multi_pass iterator
421 // and access the m_input data member.
422 template <typename MultiPassT>
423 static typename MultiPassT::reference dereference(MultiPassT const& mp)
425 if (mp.queuePosition == mp.queuedElements->end())
427 return mp.get_input();
431 return *mp.queuePosition;
435 // This is called when the iterator is incremented. It's a template
436 // method so we can recover the type of the multi_pass iterator
437 // and access the m_input data member.
438 template <typename MultiPassT>
439 static void increment(MultiPassT& mp)
441 if (mp.queuePosition == mp.queuedElements->end())
443 // don't let the queue get larger than N
444 if (mp.queuedElements->size() >= N)
445 mp.queuedElements->pop_front();
447 mp.queuedElements->push_back(mp.get_input());
457 // called to determine whether the iterator is an eof iterator
458 template <typename MultiPassT>
459 static bool is_eof(MultiPassT const& mp)
461 return mp.queuePosition == mp.queuedElements->end() &&
465 // called by operator==
466 bool equal_to(inner const& x) const
468 return queuePosition == x.queuePosition;
471 // called by operator<
472 bool less_than(inner const& x) const
474 return queuePosition < x.queuePosition;
478 }; // class fixed_size_queue
481 ///////////////////////////////////////////////////////////////////////////////
482 // class input_iterator
483 // Implementation of the InputPolicy used by multi_pass
484 // input_iterator encapsulates an input iterator of type InputT
485 ///////////////////////////////////////////////////////////////////////////////
490 template <typename InputT>
495 typename boost::detail::iterator_traits<InputT>::value_type
499 typedef result_type value_type;
503 Data(InputT const &input_)
504 : input(input_), was_initialized(false)
509 bool was_initialized;
512 // Needed by compilers not implementing the resolution to DR45. For
514 // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
520 typename boost::detail::iterator_traits<InputT>::difference_type
523 typename boost::detail::iterator_traits<InputT>::pointer
526 typename boost::detail::iterator_traits<InputT>::reference
538 inner(inner const& x)
548 bool same_input(inner const& x) const
550 return data == x.data;
554 typename boost::detail::iterator_traits<InputT>::value_type
558 impl::mp_swap(data, x.data);
561 void ensure_initialized() const
563 if (data && !data->was_initialized) {
564 data->curtok = *data->input; // get the first token
565 data->was_initialized = true;
570 reference get_input() const
572 BOOST_SPIRIT_ASSERT(NULL != data);
573 ensure_initialized();
579 BOOST_SPIRIT_ASSERT(NULL != data);
580 data->was_initialized = false; // should get the next token
584 bool input_at_eof() const
586 return !data || data->input == InputT();
595 ///////////////////////////////////////////////////////////////////////////////
597 // Implementation of the InputPolicy used by multi_pass
598 // lex_input gets tokens (ints) from yylex()
599 ///////////////////////////////////////////////////////////////////////////////
604 template <typename InputT>
608 typedef int value_type;
609 typedef std::ptrdiff_t difference_type;
610 typedef int* pointer;
611 typedef int& reference;
622 inner(inner const& x)
632 bool same_input(inner const& x) const
634 return curtok == x.curtok;
639 impl::mp_swap(curtok, x.curtok);
643 reference get_input() const
654 bool input_at_eof() const
666 ///////////////////////////////////////////////////////////////////////////////
667 // class functor_input
668 // Implementation of the InputPolicy used by multi_pass
669 // functor_input gets tokens from a functor
670 // Note: the functor must have a typedef for result_type
671 // It also must have a static variable of type result_type defined to
672 // represent eof that is called eof.
673 ///////////////////////////////////////////////////////////////////////////////
678 template <typename FunctorT>
681 typedef typename FunctorT::result_type result_type;
683 typedef result_type value_type;
684 typedef std::ptrdiff_t difference_type;
685 typedef result_type* pointer;
686 typedef result_type& reference;
694 inner(FunctorT const& x)
695 : ftor(new FunctorT(x))
696 , curtok(new result_type((*ftor)()))
699 inner(inner const& x)
712 bool same_input(inner const& x) const
714 return ftor == x.ftor;
719 impl::mp_swap(curtok, x.curtok);
720 impl::mp_swap(ftor, x.ftor);
724 reference get_input() const
736 bool input_at_eof() const
738 return !curtok || *curtok == ftor->eof;
741 FunctorT& get_functor() const
755 } // namespace multi_pass_policies
757 ///////////////////////////////////////////////////////////////////////////////
758 // iterator_base_creator
759 ///////////////////////////////////////////////////////////////////////////////
761 namespace iterator_ { namespace impl {
763 // Meta-function to generate a std::iterator<> base class for multi_pass. This
764 // is used mainly to improve conformance of compilers not supporting PTS
765 // and thus relying on inheritance to recognize an iterator.
766 // We are using boost::iterator<> because it offers an automatic workaround
767 // for broken std::iterator<> implementations.
768 template <typename InputPolicyT, typename InputT>
769 struct iterator_base_creator
771 typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t;
773 typedef boost::iterator
775 std::forward_iterator_tag,
776 typename input_t::value_type,
777 typename input_t::difference_type,
778 typename input_t::pointer,
779 typename input_t::reference
785 ///////////////////////////////////////////////////////////////////////////////
786 // class template multi_pass
787 ///////////////////////////////////////////////////////////////////////////////
789 // The default multi_pass instantiation uses a ref-counted std_deque scheme.
793 typename InputPolicy,
794 typename OwnershipPolicy,
795 typename CheckingPolicy,
796 typename StoragePolicy
799 : public OwnershipPolicy
800 , public CheckingPolicy
801 , public StoragePolicy::template inner<
802 typename InputPolicy::template inner<InputT>::value_type>
803 , public InputPolicy::template inner<InputT>
804 , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
806 typedef OwnershipPolicy OP;
807 typedef CheckingPolicy CHP;
808 typedef typename StoragePolicy::template inner<
809 typename InputPolicy::template inner<InputT>::value_type> SP;
810 typedef typename InputPolicy::template inner<InputT> IP;
812 iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
816 typedef typename IB::value_type value_type;
817 typedef typename IB::difference_type difference_type;
818 typedef typename IB::reference reference;
819 typedef typename IB::pointer pointer;
820 typedef InputT iterator_type;
823 explicit multi_pass(InputT input);
825 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
827 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
831 multi_pass(multi_pass const&);
832 multi_pass& operator=(multi_pass const&);
834 void swap(multi_pass& x);
836 reference operator*() const;
837 pointer operator->() const;
838 multi_pass& operator++();
839 multi_pass operator++(int);
843 bool operator==(const multi_pass& y) const;
844 bool operator<(const multi_pass& y) const;
846 private: // helper functions
853 typename InputPolicy,
854 typename OwnershipPolicy,
855 typename CheckingPolicy,
856 typename StoragePolicy
859 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
871 typename InputPolicy,
872 typename OwnershipPolicy,
873 typename CheckingPolicy,
874 typename StoragePolicy
877 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
878 multi_pass(InputT input)
886 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
887 // The standard library shipped with gcc-3.1 has a bug in
888 // bits/basic_string.tcc. It tries to use iter::iter(0) to
889 // construct an iterator. Ironically, this happens in sanity
890 // checking code that isn't required by the standard.
891 // The workaround is to provide an additional constructor that
892 // ignores its int argument and behaves like the default constructor.
896 typename InputPolicy,
897 typename OwnershipPolicy,
898 typename CheckingPolicy,
899 typename StoragePolicy
902 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
910 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
915 typename InputPolicy,
916 typename OwnershipPolicy,
917 typename CheckingPolicy,
918 typename StoragePolicy
921 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
935 typename InputPolicy,
936 typename OwnershipPolicy,
937 typename CheckingPolicy,
938 typename StoragePolicy
941 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
955 typename InputPolicy,
956 typename OwnershipPolicy,
957 typename CheckingPolicy,
958 typename StoragePolicy
961 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
962 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
974 typename InputPolicy,
975 typename OwnershipPolicy,
976 typename CheckingPolicy,
977 typename StoragePolicy
980 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
992 typename InputPolicy,
993 typename OwnershipPolicy,
994 typename CheckingPolicy,
995 typename StoragePolicy
998 typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1000 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1003 CHP::check_if_valid();
1004 return SP::dereference(*this);
1010 typename InputPolicy,
1011 typename OwnershipPolicy,
1012 typename CheckingPolicy,
1013 typename StoragePolicy
1016 typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1018 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1021 return &(operator*());
1027 typename InputPolicy,
1028 typename OwnershipPolicy,
1029 typename CheckingPolicy,
1030 typename StoragePolicy
1033 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
1034 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1037 CHP::check_if_valid();
1038 SP::increment(*this);
1045 typename InputPolicy,
1046 typename OwnershipPolicy,
1047 typename CheckingPolicy,
1048 typename StoragePolicy
1051 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
1052 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1072 typename InputPolicy,
1073 typename OwnershipPolicy,
1074 typename CheckingPolicy,
1075 typename StoragePolicy
1078 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1088 typename InputPolicy,
1089 typename OwnershipPolicy,
1090 typename CheckingPolicy,
1091 typename StoragePolicy
1094 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1097 return SP::is_eof(*this);
1104 typename InputPolicy,
1105 typename OwnershipPolicy,
1106 typename CheckingPolicy,
1107 typename StoragePolicy
1110 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1111 operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1112 StoragePolicy>& y) const
1114 bool is_eof_ = SP::is_eof(*this);
1115 bool y_is_eof_ = SP::is_eof(y);
1117 if (is_eof_ && y_is_eof_)
1119 return true; // both are EOF
1121 else if (is_eof_ ^ y_is_eof_)
1123 return false; // one is EOF, one isn't
1125 else if (!IP::same_input(y))
1131 return SP::equal_to(y);
1138 typename InputPolicy,
1139 typename OwnershipPolicy,
1140 typename CheckingPolicy,
1141 typename StoragePolicy
1144 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1145 operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1146 StoragePolicy>& y) const
1148 return SP::less_than(y);
1154 typename InputPolicy,
1155 typename OwnershipPolicy,
1156 typename CheckingPolicy,
1157 typename StoragePolicy
1161 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1163 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1172 typename InputPolicy,
1173 typename OwnershipPolicy,
1174 typename CheckingPolicy,
1175 typename StoragePolicy
1179 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1181 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1190 typename InputPolicy,
1191 typename OwnershipPolicy,
1192 typename CheckingPolicy,
1193 typename StoragePolicy
1197 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1199 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1208 typename InputPolicy,
1209 typename OwnershipPolicy,
1210 typename CheckingPolicy,
1211 typename StoragePolicy
1215 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1217 const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1223 ///// Generator function
1224 template <typename InputT>
1225 inline multi_pass<InputT,
1226 multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
1227 multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>
1228 make_multi_pass(InputT i)
1230 return multi_pass<InputT,
1231 multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
1232 multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>(i);
1235 // this could be a template typedef, since such a thing doesn't
1236 // exist in C++, we'll use inheritance to accomplish the same thing.
1238 template <typename InputT, std::size_t 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> >
1249 multi_pass_policies::input_iterator,
1250 multi_pass_policies::first_owner,
1251 multi_pass_policies::no_check,
1252 multi_pass_policies::fixed_size_queue<N> > base_t;
1257 explicit look_ahead(InputT x)
1260 look_ahead(look_ahead const& x)
1263 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1264 look_ahead(int) // workaround for a bug in the library
1265 : base_t() {} // shipped with gcc 3.1
1266 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1268 // default generated operators destructor and assignment operator are okay.
1274 typename InputPolicy,
1275 typename OwnershipPolicy,
1276 typename CheckingPolicy,
1277 typename StoragePolicy
1281 InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1284 InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1292 template <typename T>
1293 inline void mp_swap(T& t1, T& t2)
1296 using BOOST_SPIRIT_CLASSIC_NS::swap;
1301 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
1303 }} // namespace BOOST_SPIRIT_CLASSIC_NS
1305 #endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP