1
/*=============================================================================
3
Copyright (c) 2001, Daniel C. Nuffer
4
http://spirit.sourceforge.net/
6
Permission to copy, use, modify, sell and distribute this software is
7
granted provided this copyright notice appears in all copies. This
8
software is provided "as is" without express or implied warranty, and
9
with no claim as to its suitability for any purpose.
10
=============================================================================*/
11
#ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
12
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
14
#include <boost/config.hpp>
15
#include <boost/throw_exception.hpp>
16
#include <boost/detail/workaround.hpp>
18
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
19
# error multi_pass iterator supported only on MSVC 7.0 and above.
21
// the newer version of multi_pass
26
#include <algorithm> // for std::swap
27
#include <exception> // for std::exception
29
#include <boost/limits.hpp>
30
#include <boost/iterator.hpp>
32
#include "fixed_size_queue.hpp"
33
#include "boost/spirit/core/assert.hpp" // for BOOST_SPIRIT_ASSERT
35
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
36
# include "boost/spirit/core/impl/msvc.hpp" // for more compatible iterator_traits
37
#define BOOST_SPIRIT_IT_NS impl
39
#define BOOST_SPIRIT_IT_NS std
42
#if (defined(BOOST_INTEL_CXX_VERSION) && !defined(_STLPORT_VERSION))
43
# include "boost/spirit/core/impl/msvc.hpp" // for more compatible iterator_traits
44
#undef BOOST_SPIRIT_IT_NS
45
#define BOOST_SPIRIT_IT_NS impl
48
///////////////////////////////////////////////////////////////////////////////
49
namespace boost { namespace spirit {
53
inline void mp_swap(T& t1, T& t2);
56
namespace multi_pass_policies
59
///////////////////////////////////////////////////////////////////////////////
61
// Implementation of an OwnershipPolicy used by multi_pass.
63
// Implementation modified from RefCounted class from the Loki library by
64
// Andrei Alexandrescu
65
///////////////////////////////////////////////////////////////////////////////
70
: count(new unsigned int(1))
73
ref_counted(ref_counted const& x)
77
// clone is called when a copy of the iterator is made, so increment
84
// called when a copy is deleted. Decrement the ref-count. Return
85
// value of true indicates that the last copy has been released.
97
void swap(ref_counted& x)
99
impl::mp_swap(count, x.count);
103
// returns true if there is only one iterator in existence.
104
// std_deque StoragePolicy will free it's buffered data if this
115
///////////////////////////////////////////////////////////////////////////////
117
// Implementation of an OwnershipPolicy used by multi_pass
118
// This ownership policy dictates that the first iterator created will
119
// determine the lifespan of the shared components. This works well for
120
// spirit, since no dynamic allocation of iterators is done, and all copies
121
// are make on the stack.
123
// There is a caveat about using this policy together with the std_deque
124
// StoragePolicy. Since first_owner always returns false from unique(),
125
// std_deque will only release the queued data if clear_queue() is called.
126
///////////////////////////////////////////////////////////////////////////////
134
first_owner(first_owner const&)
142
// return true to indicate deletion of resources
148
void swap(first_owner&)
150
// if we're the first, we still remain the first, even if assigned
151
// to, so don't swap first_. swap is only called from operator=
157
return false; // no way to know, so always return false
164
///////////////////////////////////////////////////////////////////////////////
165
// class illegal_backtracking
166
// thrown by buf_id_check CheckingPolicy if an instance of an iterator is
167
// used after another one has invalidated the queue
168
///////////////////////////////////////////////////////////////////////////////
169
class illegal_backtracking : public std::exception
173
illegal_backtracking() throw() {}
174
~illegal_backtracking() throw() {}
178
{ return "boost::spirit::illegal_backtracking"; }
181
///////////////////////////////////////////////////////////////////////////////
182
// class buf_id_check
183
// Implementation of the CheckingPolicy used by multi_pass
184
// This policy is most effective when used together with the std_deque
186
// If used with the fixed_size_queue StoragePolicy, it will not detect
187
// iterator derefereces that are out of the range of the queue.
188
///////////////////////////////////////////////////////////////////////////////
193
: shared_buf_id(new unsigned long(0))
197
buf_id_check(buf_id_check const& x)
198
: shared_buf_id(x.shared_buf_id)
202
// will be called from the destructor of the last iterator.
205
delete shared_buf_id;
209
void swap(buf_id_check& x)
211
impl::mp_swap(shared_buf_id, x.shared_buf_id);
212
impl::mp_swap(buf_id, x.buf_id);
215
// called to verify that everything is okay.
218
if (buf_id != *shared_buf_id)
220
boost::throw_exception(illegal_backtracking());
224
// called from multi_pass::clear_queue, so we can increment the count
232
unsigned long* shared_buf_id;
233
unsigned long buf_id;
236
///////////////////////////////////////////////////////////////////////////////
238
// Implementation of the CheckingPolicy used by multi_pass
239
// It does not do anything :-)
240
///////////////////////////////////////////////////////////////////////////////
245
no_check(no_check const&) {}
247
void swap(no_check&) {}
248
void check() const {}
249
void clear_queue() {}
252
///////////////////////////////////////////////////////////////////////////////
254
// Implementation of the StoragePolicy used by multi_pass
255
// This stores all data in a std::deque, and keeps an offset to the current
256
// position. It stores all the data unless there is only one
257
// iterator using the queue.
258
// Note: a position is used instead of an iterator, because a push_back on
259
// a deque can invalidate any iterators.
260
///////////////////////////////////////////////////////////////////////////////
265
template <typename ValueT>
268
#if defined(__BORLANDC__) || BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
273
typedef std::deque<ValueT> queue_type;
274
queue_type* queuedElements;
275
mutable typename queue_type::size_type queuePosition;
279
: queuedElements(new queue_type)
283
inner(inner const& x)
284
: queuedElements(x.queuedElements)
285
, queuePosition(x.queuePosition)
288
// will be called from the destructor of the last iterator.
291
BOOST_SPIRIT_ASSERT(queuedElements);
292
delete queuedElements;
298
impl::mp_swap(queuedElements, x.queuedElements);
299
impl::mp_swap(queuePosition, x.queuePosition);
302
// This is called when the iterator is dereferenced. It's a template
303
// method so we can recover the type of the multi_pass iterator
304
// and call unique and access the m_input data member.
305
template <typename MultiPassT>
306
static typename MultiPassT::reference dereference(MultiPassT const& mp)
308
if (mp.queuePosition == mp.queuedElements->size())
310
// check if this is the only iterator
313
// free up the memory used by the queue.
314
if (mp.queuedElements->size() > 0)
316
mp.queuedElements->clear();
317
mp.queuePosition = 0;
320
return mp.get_input();
324
return (*mp.queuedElements)[mp.queuePosition];
328
// This is called when the iterator is incremented. It's a template
329
// method so we can recover the type of the multi_pass iterator
330
// and call unique and access the m_input data member.
331
template <typename MultiPassT>
332
static void increment(MultiPassT& mp)
334
if (mp.queuePosition == mp.queuedElements->size())
336
// check if this is the only iterator
339
// free up the memory used by the queue.
340
if (mp.queuedElements->size() > 0)
342
mp.queuedElements->clear();
343
mp.queuePosition = 0;
348
mp.queuedElements->push_back(mp.get_input());
360
// called to forcibly clear the queue
363
queuedElements->clear();
367
// called to determine whether the iterator is an eof iterator
368
template <typename MultiPassT>
369
static bool is_eof(MultiPassT const& mp)
371
return mp.queuePosition == mp.queuedElements->size() &&
375
// called by operator==
376
bool equal_to(inner const& x) const
378
return queuePosition == x.queuePosition;
381
// called by operator<
382
bool less_than(inner const& x) const
384
return queuePosition < x.queuePosition;
388
}; // class std_deque
391
///////////////////////////////////////////////////////////////////////////////
392
// class fixed_size_queue
393
// Implementation of the StoragePolicy used by multi_pass
394
// fixed_size_queue keeps a circular buffer (implemented by
395
// boost::spirit::fixed_size_queue class) that is size N+1 and stores N elements.
396
// It is up to the user to ensure that there is enough look ahead for their
397
// grammar. Currently there is no way to tell if an iterator is pointing
398
// to forgotten data. The leading iterator will put an item in the queue
399
// and remove one when it is incremented. No dynamic allocation is done,
400
// except on creation of the queue (fixed_size_queue constructor).
401
///////////////////////////////////////////////////////////////////////////////
402
template < std::size_t N>
403
class fixed_size_queue
407
template <typename ValueT>
410
#if defined(__BORLANDC__) || BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
415
typedef boost::spirit::fixed_size_queue<ValueT, N> queue_type;
416
queue_type * queuedElements;
417
mutable typename queue_type::iterator queuePosition;
421
: queuedElements(new queue_type)
422
, queuePosition(queuedElements->begin())
425
inner(inner const& x)
426
: queuedElements(x.queuedElements)
427
, queuePosition(x.queuePosition)
430
// will be called from the destructor of the last iterator.
433
BOOST_SPIRIT_ASSERT(queuedElements);
434
delete queuedElements;
440
impl::mp_swap(queuedElements, x.queuedElements);
441
impl::mp_swap(queuePosition, x.queuePosition);
444
// This is called when the iterator is dereferenced. It's a template
445
// method so we can recover the type of the multi_pass iterator
446
// and access the m_input data member.
447
template <typename MultiPassT>
448
static typename MultiPassT::reference dereference(MultiPassT const& mp)
450
if (mp.queuePosition == mp.queuedElements->end())
452
return mp.get_input();
456
return *mp.queuePosition;
460
// This is called when the iterator is incremented. It's a template
461
// method so we can recover the type of the multi_pass iterator
462
// and access the m_input data member.
463
template <typename MultiPassT>
464
static void increment(MultiPassT& mp)
466
if (mp.queuePosition == mp.queuedElements->end())
468
// don't let the queue get larger than N
469
if (mp.queuedElements->size() >= N)
470
mp.queuedElements->pop_front();
472
mp.queuedElements->push_back(mp.get_input());
482
// called to determine whether the iterator is an eof iterator
483
template <typename MultiPassT>
484
static bool is_eof(MultiPassT const& mp)
486
return mp.queuePosition == mp.queuedElements->end() &&
490
// called by operator==
491
bool equal_to(inner const& x) const
493
return queuePosition == x.queuePosition;
496
// called by operator<
497
bool less_than(inner const& x) const
499
return queuePosition < x.queuePosition;
503
}; // class fixed_size_queue
506
///////////////////////////////////////////////////////////////////////////////
507
// class input_iterator
508
// Implementation of the InputPolicy used by multi_pass
509
// input_iterator encapsulates an input iterator of type InputT
510
///////////////////////////////////////////////////////////////////////////////
515
template <typename InputT>
520
typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::value_type
523
typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::difference_type
526
typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::pointer
529
typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::reference
534
: input(new InputT())
535
, val(new value_type)
539
: input(new InputT(x))
540
, val(new value_type(**input))
543
inner(inner const& x)
556
bool same_input(inner const& x) const
558
return input == x.input;
562
typename BOOST_SPIRIT_IT_NS::iterator_traits<InputT>::value_type
566
impl::mp_swap(input, x.input);
567
impl::mp_swap(val, x.val);
571
reference get_input() const
582
bool input_at_eof() const
584
return *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
787
///////////////////////////////////////////////////////////////////////////////
788
// class template multi_pass (declaration)
789
///////////////////////////////////////////////////////////////////////////////
793
typename InputPolicy = multi_pass_policies::input_iterator,
794
typename OwnershipPolicy = multi_pass_policies::ref_counted,
795
typename CheckingPolicy = multi_pass_policies::buf_id_check,
796
typename StoragePolicy = multi_pass_policies::std_deque
800
// The default multi_pass instantiation uses a ref-counted std_deque scheme.
802
///////////////////////////////////////////////////////////////////////////////
803
// class template multi_pass (definition)
804
///////////////////////////////////////////////////////////////////////////////
808
typename InputPolicy,
809
typename OwnershipPolicy,
810
typename CheckingPolicy,
811
typename StoragePolicy
814
: public OwnershipPolicy
815
, public CheckingPolicy
816
, public StoragePolicy::template inner<
817
typename InputPolicy::template inner<InputT>::value_type>
818
, public InputPolicy::template inner<InputT>
819
, public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
821
typedef OwnershipPolicy OP;
822
typedef CheckingPolicy CHP;
823
typedef typename StoragePolicy::template inner<
824
typename InputPolicy::template inner<InputT>::value_type> SP;
825
typedef typename InputPolicy::template inner<InputT> IP;
827
iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
831
typedef typename IB::value_type value_type;
832
typedef typename IB::difference_type difference_type;
833
typedef typename IB::reference reference;
834
typedef typename IB::pointer pointer;
835
typedef InputT iterator_type;
838
explicit multi_pass(InputT input);
840
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
842
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
846
multi_pass(multi_pass const&);
847
multi_pass& operator=(multi_pass const&);
849
void swap(multi_pass& x);
851
reference operator*() const;
852
pointer operator->() const;
853
multi_pass& operator++();
854
multi_pass operator++(int);
858
bool operator==(const multi_pass& y) const;
859
bool operator<(const multi_pass& y) const;
861
private: // helper functions
868
typename InputPolicy,
869
typename OwnershipPolicy,
870
typename CheckingPolicy,
871
typename StoragePolicy
874
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
886
typename InputPolicy,
887
typename OwnershipPolicy,
888
typename CheckingPolicy,
889
typename StoragePolicy
892
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
893
multi_pass(InputT input)
901
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
902
// The standard library shipped with gcc-3.1 has a bug in
903
// bits/basic_string.tcc. It tries to use iter::iter(0) to
904
// construct an iterator. Ironically, this happens in sanity
905
// checking code that isn't required by the standard.
906
// The workaround is to provide an additional constructor that
907
// ignores its int argument and behaves like the default constructor.
911
typename InputPolicy,
912
typename OwnershipPolicy,
913
typename CheckingPolicy,
914
typename StoragePolicy
917
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
925
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
930
typename InputPolicy,
931
typename OwnershipPolicy,
932
typename CheckingPolicy,
933
typename StoragePolicy
936
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
950
typename InputPolicy,
951
typename OwnershipPolicy,
952
typename CheckingPolicy,
953
typename StoragePolicy
956
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
970
typename InputPolicy,
971
typename OwnershipPolicy,
972
typename CheckingPolicy,
973
typename StoragePolicy
976
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
977
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
989
typename InputPolicy,
990
typename OwnershipPolicy,
991
typename CheckingPolicy,
992
typename StoragePolicy
995
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1007
typename InputPolicy,
1008
typename OwnershipPolicy,
1009
typename CheckingPolicy,
1010
typename StoragePolicy
1013
typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1015
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1019
return SP::dereference(*this);
1025
typename InputPolicy,
1026
typename OwnershipPolicy,
1027
typename CheckingPolicy,
1028
typename StoragePolicy
1031
typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1033
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1036
return &(operator*());
1042
typename InputPolicy,
1043
typename OwnershipPolicy,
1044
typename CheckingPolicy,
1045
typename StoragePolicy
1048
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
1049
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1053
SP::increment(*this);
1060
typename InputPolicy,
1061
typename OwnershipPolicy,
1062
typename CheckingPolicy,
1063
typename StoragePolicy
1066
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
1067
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1087
typename InputPolicy,
1088
typename OwnershipPolicy,
1089
typename CheckingPolicy,
1090
typename StoragePolicy
1093
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1103
typename InputPolicy,
1104
typename OwnershipPolicy,
1105
typename CheckingPolicy,
1106
typename StoragePolicy
1109
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1112
return SP::is_eof(*this);
1119
typename InputPolicy,
1120
typename OwnershipPolicy,
1121
typename CheckingPolicy,
1122
typename StoragePolicy
1125
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1126
operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1127
StoragePolicy>& y) const
1129
if (is_eof() && y.is_eof())
1131
return true; // both are EOF
1133
else if (is_eof() ^ y.is_eof())
1135
return false; // one is EOF, one isn't
1137
else if (!IP::same_input(y))
1143
return SP::equal_to(y);
1150
typename InputPolicy,
1151
typename OwnershipPolicy,
1152
typename CheckingPolicy,
1153
typename StoragePolicy
1156
multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1157
operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1158
StoragePolicy>& y) const
1160
return SP::less_than(y);
1166
typename InputPolicy,
1167
typename OwnershipPolicy,
1168
typename CheckingPolicy,
1169
typename StoragePolicy
1173
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1175
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1184
typename InputPolicy,
1185
typename OwnershipPolicy,
1186
typename CheckingPolicy,
1187
typename StoragePolicy
1191
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1193
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1202
typename InputPolicy,
1203
typename OwnershipPolicy,
1204
typename CheckingPolicy,
1205
typename StoragePolicy
1209
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1211
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1220
typename InputPolicy,
1221
typename OwnershipPolicy,
1222
typename CheckingPolicy,
1223
typename StoragePolicy
1227
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1229
const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1235
///// Generator function
1236
template <typename InputT>
1237
inline multi_pass<InputT>
1238
make_multi_pass(InputT i)
1240
return multi_pass<InputT>(i);
1243
// this could be a template typedef, since such a thing doesn't
1244
// exist in C++, we'll use inheritance to accomplish the same thing.
1246
template <typename InputT, std::size_t N>
1250
multi_pass_policies::input_iterator,
1251
multi_pass_policies::first_owner,
1252
multi_pass_policies::no_check,
1253
multi_pass_policies::fixed_size_queue<N> >
1257
multi_pass_policies::input_iterator,
1258
multi_pass_policies::first_owner,
1259
multi_pass_policies::no_check,
1260
multi_pass_policies::fixed_size_queue<N> > base_t;
1265
explicit look_ahead(InputT x)
1268
look_ahead(look_ahead const& x)
1271
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1272
look_ahead(int) // workaround for a bug in the library
1273
: base_t() {} // shipped with gcc 3.1
1274
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1276
// default generated operators destructor and assignment operator are okay.
1282
typename InputPolicy,
1283
typename OwnershipPolicy,
1284
typename CheckingPolicy,
1285
typename StoragePolicy
1289
InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1292
InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1302
template <typename T>
1303
inline void mp_swap(T& t1, T& t2)
1306
using boost::spirit::swap;
1311
///////////////////////////////////////////////////////////////////////////////
1312
}} // namespace boost::spirit
1314
#undef BOOST_SPIRIT_IT_NS
1315
#endif // defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
1316
#endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP