1 // Copyright (c) 2001-2012 Hartmut Kaiser
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #if !defined(BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM)
7 #define BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM
9 #include <boost/config.hpp>
10 #include <boost/type_traits/is_empty.hpp>
12 namespace boost { namespace spirit { namespace iterator_policies
14 ///////////////////////////////////////////////////////////////////////////
15 // The purpose of the multi_pass_unique template is to eliminate
16 // empty policy classes (policies not containing any data items) from the
17 // multiple inheritance chain. This is necessary since some compilers
18 // fail to apply the empty base optimization if multiple inheritance is
20 // Additionally this can be used to combine separate policies into one
21 // single multi_pass_policy as required by the multi_pass template
22 ///////////////////////////////////////////////////////////////////////////
24 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
25 // without partial template specialization there is nothing much to do in
26 // terms of empty base optimization anyways...
27 template <typename T, typename Ownership, typename Checking,
28 typename Input, typename Storage>
29 struct multi_pass_unique
30 : Ownership, Checking, Input, Storage
32 multi_pass_unique() {}
33 multi_pass_unique(T& x) : Input(x) {}
34 multi_pass_unique(T const& x) : Input(x) {}
36 template <typename MultiPass>
37 static void destroy(MultiPass& mp)
39 Ownership::destroy(mp);
40 Checking::destroy(mp);
45 void swap(multi_pass_unique& x)
47 this->Ownership::swap(x);
48 this->Checking::swap(x);
50 this->Storage::swap(x);
53 template <typename MultiPass>
54 inline static void clear_queue(MultiPass& mp)
56 Checking::clear_queue(mp);
57 Storage::clear_queue(mp);
61 ///////////////////////////////////////////////////////////////////////////
62 // select the correct derived classes based on if a policy is empty
64 , typename Ownership, typename Checking, typename Input, typename Storage
65 , bool OwnershipIsEmpty = boost::is_empty<Ownership>::value
66 , bool CheckingIsEmpty = boost::is_empty<Checking>::value
67 , bool InputIsEmpty = boost::is_empty<Input>::value>
68 struct multi_pass_unique;
70 ///////////////////////////////////////////////////////////////////////////
71 template <typename T, typename Ownership, typename Checking
72 , typename Input, typename Storage>
73 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
74 , false, false, false>
75 : Ownership, Checking, Input, Storage
77 multi_pass_unique() {}
78 multi_pass_unique(T& x) : Input(x) {}
79 multi_pass_unique(T const& x) : Input(x) {}
81 template <typename MultiPass>
82 static void destroy(MultiPass& mp)
84 Ownership::destroy(mp);
85 Checking::destroy(mp);
90 void swap(multi_pass_unique& x)
92 this->Ownership::swap(x);
93 this->Checking::swap(x);
95 this->Storage::swap(x);
98 template <typename MultiPass>
99 inline static void clear_queue(MultiPass& mp)
101 Checking::clear_queue(mp);
102 Storage::clear_queue(mp);
106 ///////////////////////////////////////////////////////////////////////////
107 template <typename T, typename Ownership, typename Checking
108 , typename Input, typename Storage>
109 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
110 , false, false, true>
111 : Ownership, Checking, Storage
113 multi_pass_unique() {}
114 multi_pass_unique(T const&) {}
116 template <typename MultiPass>
117 static void destroy(MultiPass& mp)
119 Ownership::destroy(mp);
120 Checking::destroy(mp);
122 Storage::destroy(mp);
125 void swap(multi_pass_unique& x)
127 this->Ownership::swap(x);
128 this->Checking::swap(x);
129 this->Storage::swap(x);
132 template <typename MultiPass>
133 inline static void clear_queue(MultiPass& mp)
135 Checking::clear_queue(mp);
136 Storage::clear_queue(mp);
139 // implement input policy functions by forwarding to the Input type
140 template <typename MultiPass>
141 inline static void advance_input(MultiPass& mp)
142 { Input::advance_input(mp); }
144 template <typename MultiPass>
145 inline static typename MultiPass::reference get_input(MultiPass& mp)
146 { return Input::get_input(mp); }
148 template <typename MultiPass>
149 inline static bool input_at_eof(MultiPass const& mp)
150 { return Input::input_at_eof(mp); }
152 template <typename MultiPass, typename TokenType>
153 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
154 { return Input::input_is_valid(mp, curtok); }
157 ///////////////////////////////////////////////////////////////////////////
158 template <typename T, typename Ownership, typename Checking
159 , typename Input, typename Storage>
160 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
161 , false, true, false>
162 : Ownership, Input, Storage
164 multi_pass_unique() {}
165 multi_pass_unique(T& x) : Input(x) {}
166 multi_pass_unique(T const& x) : Input(x) {}
168 template <typename MultiPass>
169 static void destroy(MultiPass& mp)
171 Ownership::destroy(mp);
173 Storage::destroy(mp);
176 void swap(multi_pass_unique& x)
178 this->Ownership::swap(x);
179 this->Input::swap(x);
180 this->Storage::swap(x);
183 template <typename MultiPass>
184 inline static void clear_queue(MultiPass& mp)
186 Checking::clear_queue(mp);
187 Storage::clear_queue(mp);
190 // checking policy functions are forwarded to the Checking type
191 template <typename MultiPass>
192 inline static void docheck(MultiPass const& mp)
193 { Checking::docheck(mp); }
196 ///////////////////////////////////////////////////////////////////////////
197 template <typename T, typename Ownership, typename Checking
198 , typename Input, typename Storage>
199 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
203 multi_pass_unique() {}
204 multi_pass_unique(T const&) {}
206 template <typename MultiPass>
207 static void destroy(MultiPass& mp)
209 Ownership::destroy(mp);
211 Storage::destroy(mp);
214 void swap(multi_pass_unique& x)
216 this->Ownership::swap(x);
217 this->Storage::swap(x);
220 template <typename MultiPass>
221 inline static void clear_queue(MultiPass& mp)
223 Checking::clear_queue(mp);
224 Storage::clear_queue(mp);
227 // implement input policy functions by forwarding to the Input type
228 template <typename MultiPass>
229 inline static void advance_input(MultiPass& mp)
230 { Input::advance_input(mp); }
232 template <typename MultiPass>
233 inline static typename MultiPass::reference get_input(MultiPass& mp)
234 { return Input::get_input(mp); }
236 template <typename MultiPass>
237 inline static bool input_at_eof(MultiPass const& mp)
238 { return Input::input_at_eof(mp); }
240 template <typename MultiPass, typename TokenType>
241 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
242 { return Input::input_is_valid(mp, curtok); }
244 // checking policy functions are forwarded to the Checking type
245 template <typename MultiPass>
246 inline static void docheck(MultiPass const& mp)
247 { Checking::docheck(mp); }
250 ///////////////////////////////////////////////////////////////////////////
251 template <typename T, typename Ownership, typename Checking
252 , typename Input, typename Storage>
253 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
254 , true, false, false>
255 : Checking, Input, Storage
257 multi_pass_unique() {}
258 multi_pass_unique(T& x) : Input(x) {}
259 multi_pass_unique(T const& x) : Input(x) {}
261 template <typename MultiPass>
262 static void destroy(MultiPass& mp)
264 Checking::destroy(mp);
266 Storage::destroy(mp);
269 void swap(multi_pass_unique& x)
271 this->Checking::swap(x);
272 this->Input::swap(x);
273 this->Storage::swap(x);
276 template <typename MultiPass>
277 inline static void clear_queue(MultiPass& mp)
279 Checking::clear_queue(mp);
280 Storage::clear_queue(mp);
283 // ownership policy functions are forwarded to the Ownership type
284 template <typename MultiPass>
285 inline static void clone(MultiPass& mp)
286 { Ownership::clone(mp); }
288 template <typename MultiPass>
289 inline static bool release(MultiPass& mp)
290 { return Ownership::release(mp); }
292 template <typename MultiPass>
293 inline static bool is_unique(MultiPass const& mp)
294 { return Ownership::is_unique(mp); }
297 ///////////////////////////////////////////////////////////////////////////
298 template <typename T, typename Ownership, typename Checking
299 , typename Input, typename Storage>
300 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
304 multi_pass_unique() {}
305 multi_pass_unique(T const&) {}
307 template <typename MultiPass>
308 static void destroy(MultiPass& mp)
310 Checking::destroy(mp);
312 Storage::destroy(mp);
315 void swap(multi_pass_unique& x)
317 this->Checking::swap(x);
318 this->Storage::swap(x);
321 template <typename MultiPass>
322 inline static void clear_queue(MultiPass& mp)
324 Checking::clear_queue(mp);
325 Storage::clear_queue(mp);
328 // implement input policy functions by forwarding to the Input type
329 template <typename MultiPass>
330 inline static void advance_input(MultiPass& mp)
331 { Input::advance_input(mp); }
333 template <typename MultiPass>
334 inline static typename MultiPass::reference get_input(MultiPass& mp)
335 { return Input::get_input(mp); }
337 template <typename MultiPass>
338 inline static bool input_at_eof(MultiPass const& mp)
339 { return Input::input_at_eof(mp); }
341 template <typename MultiPass, typename TokenType>
342 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
343 { return Input::input_is_valid(mp, curtok); }
345 // ownership policy functions are forwarded to the Ownership type
346 template <typename MultiPass>
347 inline static void clone(MultiPass& mp)
348 { Ownership::clone(mp); }
350 template <typename MultiPass>
351 inline static bool release(MultiPass& mp)
352 { return Ownership::release(mp); }
354 template <typename MultiPass>
355 inline static bool is_unique(MultiPass const& mp)
356 { return Ownership::is_unique(mp); }
359 ///////////////////////////////////////////////////////////////////////////
360 template <typename T, typename Ownership, typename Checking
361 , typename Input, typename Storage>
362 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
366 multi_pass_unique() {}
367 multi_pass_unique(T& x) : Input(x) {}
368 multi_pass_unique(T const& x) : Input(x) {}
370 template <typename MultiPass>
371 static void destroy(MultiPass& mp)
374 Storage::destroy(mp);
377 void swap(multi_pass_unique& x)
379 this->Input::swap(x);
380 this->Storage::swap(x);
383 template <typename MultiPass>
384 inline static void clear_queue(MultiPass& mp)
386 Checking::clear_queue(mp);
387 Storage::clear_queue(mp);
390 // checking policy functions are forwarded to the Checking type
391 template <typename MultiPass>
392 inline static void docheck(MultiPass const& mp)
393 { Checking::docheck(mp); }
395 // ownership policy functions are forwarded to the Ownership type
396 template <typename MultiPass>
397 inline static void clone(MultiPass& mp)
398 { Ownership::clone(mp); }
400 template <typename MultiPass>
401 inline static bool release(MultiPass& mp)
402 { return Ownership::release(mp); }
404 template <typename MultiPass>
405 inline static bool is_unique(MultiPass const& mp)
406 { return Ownership::is_unique(mp); }
409 ///////////////////////////////////////////////////////////////////////////
410 template <typename T, typename Ownership, typename Checking
411 , typename Input, typename Storage>
412 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
416 multi_pass_unique() {}
417 multi_pass_unique(T const&) {}
419 template <typename MultiPass>
420 static void destroy(MultiPass& mp)
423 Storage::destroy(mp);
426 void swap(multi_pass_unique& x)
428 this->Storage::swap(x);
431 template <typename MultiPass>
432 inline static void clear_queue(MultiPass& mp)
434 Checking::clear_queue(mp);
435 Storage::clear_queue(mp);
438 // implement input policy functions by forwarding to the Input type
439 template <typename MultiPass>
440 inline static void advance_input(MultiPass& mp)
441 { Input::advance_input(mp); }
443 template <typename MultiPass>
444 inline static typename MultiPass::reference get_input(MultiPass& mp)
445 { return Input::get_input(mp); }
447 template <typename MultiPass>
448 inline static bool input_at_eof(MultiPass const& mp)
449 { return Input::input_at_eof(mp); }
451 template <typename MultiPass, typename TokenType>
452 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
453 { return Input::input_is_valid(mp, curtok); }
455 // checking policy functions are forwarded to the Checking type
456 template <typename MultiPass>
457 inline static void docheck(MultiPass const& mp)
458 { Checking::docheck(mp); }
460 // ownership policy functions are forwarded to the Ownership type
461 template <typename MultiPass>
462 inline static void clone(MultiPass& mp)
463 { Ownership::clone(mp); }
465 template <typename MultiPass>
466 inline static bool release(MultiPass& mp)
467 { return Ownership::release(mp); }
469 template <typename MultiPass>
470 inline static bool is_unique(MultiPass const& mp)
471 { return Ownership::is_unique(mp); }
475 ///////////////////////////////////////////////////////////////////////////
476 // the multi_pass_shared structure is used to combine the shared data items
477 // of all policies into one single structure
478 ///////////////////////////////////////////////////////////////////////////
479 template<typename T, typename Ownership, typename Checking, typename Input
481 struct multi_pass_shared : Ownership, Checking, Input, Storage
483 explicit multi_pass_shared(T& input) : Input(input) {}
484 explicit multi_pass_shared(T const& input) : Input(input) {}
487 ///////////////////////////////////////////////////////////////////////////
488 // This is a default implementation of a policy class as required by the
489 // multi_pass template, combining 4 separate policies into one. Any other
490 // multi_pass policy class needs to follow the scheme as shown below.
491 template<typename Ownership, typename Checking, typename Input
493 struct default_policy
495 typedef Ownership ownership_policy;
496 typedef Checking checking_policy;
497 typedef Input input_policy;
498 typedef Storage storage_policy;
500 ///////////////////////////////////////////////////////////////////////
501 template <typename T>
502 struct unique : multi_pass_unique<T
503 , typename Ownership::unique, typename Checking::unique
504 , typename Input::BOOST_NESTED_TEMPLATE unique<T>
505 , typename Storage::BOOST_NESTED_TEMPLATE unique<
506 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
508 typedef typename Ownership::unique ownership_policy;
509 typedef typename Checking::unique checking_policy;
510 typedef typename Input::BOOST_NESTED_TEMPLATE unique<T>
512 typedef typename Storage::BOOST_NESTED_TEMPLATE unique<
513 typename input_policy::value_type> storage_policy;
515 typedef multi_pass_unique<T, ownership_policy, checking_policy
516 , input_policy, storage_policy> unique_base_type;
519 explicit unique(T& input) : unique_base_type(input) {}
520 explicit unique(T const& input) : unique_base_type(input) {}
523 ///////////////////////////////////////////////////////////////////////
524 template <typename T>
525 struct shared : multi_pass_shared<T
526 , typename Ownership::shared, typename Checking::shared
527 , typename Input::BOOST_NESTED_TEMPLATE shared<T>
528 , typename Storage::BOOST_NESTED_TEMPLATE shared<
529 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
531 typedef typename Ownership::shared ownership_policy;
532 typedef typename Checking::shared checking_policy;
533 typedef typename Input::BOOST_NESTED_TEMPLATE shared<T>
535 typedef typename Storage::BOOST_NESTED_TEMPLATE shared<
536 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
539 typedef multi_pass_shared<T, ownership_policy, checking_policy
540 , input_policy, storage_policy> shared_base_type;
542 explicit shared(T& input)
543 : shared_base_type(input), inhibit_clear_queue_(false) {}
544 explicit shared(T const& input)
545 : shared_base_type(input), inhibit_clear_queue_(false) {}
547 // This is needed for the correct implementation of expectation
548 // points. Normally expectation points flush any multi_pass
549 // iterator they may act on, but if the corresponding error handler
550 // is of type 'retry' no flushing of the internal buffers should be
551 // executed (even if explicitly requested).
552 bool inhibit_clear_queue_;