1 // Copyright (c) 2001-2010 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);
44 void swap(multi_pass_unique& x)
46 this->Ownership::swap(x);
47 this->Checking::swap(x);
49 this->Storage::swap(x);
53 ///////////////////////////////////////////////////////////////////////////
54 // select the correct derived classes based on if a policy is empty
56 , typename Ownership, typename Checking, typename Input, typename Storage
57 , bool OwnershipIsEmpty = boost::is_empty<Ownership>::value
58 , bool CheckingIsEmpty = boost::is_empty<Checking>::value
59 , bool InputIsEmpty = boost::is_empty<Input>::value>
60 struct multi_pass_unique;
62 ///////////////////////////////////////////////////////////////////////////
63 template <typename T, typename Ownership, typename Checking
64 , typename Input, typename Storage>
65 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
66 , false, false, false>
67 : Ownership, Checking, Input, Storage
69 multi_pass_unique() {}
70 multi_pass_unique(T& x) : Input(x) {}
71 multi_pass_unique(T const& x) : Input(x) {}
73 template <typename MultiPass>
74 static void destroy(MultiPass& mp)
76 Ownership::destroy(mp);
77 Checking::destroy(mp);
81 void swap(multi_pass_unique& x)
83 this->Ownership::swap(x);
84 this->Checking::swap(x);
86 this->Storage::swap(x);
90 ///////////////////////////////////////////////////////////////////////////
91 template <typename T, typename Ownership, typename Checking
92 , typename Input, typename Storage>
93 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
95 : Ownership, Checking, Storage
97 multi_pass_unique() {}
98 multi_pass_unique(T const& x) {}
100 template <typename MultiPass>
101 static void destroy(MultiPass& mp)
103 Ownership::destroy(mp);
104 Checking::destroy(mp);
106 Storage::destroy(mp);
108 void swap(multi_pass_unique& x)
110 this->Ownership::swap(x);
111 this->Checking::swap(x);
112 this->Storage::swap(x);
115 // implement input policy functions by forwarding to the Input type
116 template <typename MultiPass>
117 inline static void advance_input(MultiPass& mp)
118 { Input::advance_input(mp); }
120 template <typename MultiPass>
121 inline static typename MultiPass::reference get_input(MultiPass& mp)
122 { return Input::get_input(mp); }
124 template <typename MultiPass>
125 inline static bool input_at_eof(MultiPass const& mp)
126 { return Input::input_at_eof(mp); }
128 template <typename MultiPass, typename TokenType>
129 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
130 { return Input::input_is_valid(mp, curtok); }
133 ///////////////////////////////////////////////////////////////////////////
134 template <typename T, typename Ownership, typename Checking
135 , typename Input, typename Storage>
136 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
137 , false, true, false>
138 : Ownership, Input, Storage
140 multi_pass_unique() {}
141 multi_pass_unique(T& x) : Input(x) {}
142 multi_pass_unique(T const& x) : Input(x) {}
144 template <typename MultiPass>
145 static void destroy(MultiPass& mp)
147 Ownership::destroy(mp);
149 Storage::destroy(mp);
151 void swap(multi_pass_unique& x)
153 this->Ownership::swap(x);
154 this->Input::swap(x);
155 this->Storage::swap(x);
158 // checking policy functions are forwarded to the Checking type
159 template <typename MultiPass>
160 inline static void docheck(MultiPass const& mp)
161 { Checking::docheck(mp); }
163 template <typename MultiPass>
164 inline static void clear_queue(MultiPass& mp)
165 { Checking::clear_queue(mp); }
168 ///////////////////////////////////////////////////////////////////////////
169 template <typename T, typename Ownership, typename Checking
170 , typename Input, typename Storage>
171 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
175 multi_pass_unique() {}
176 multi_pass_unique(T const& x) {}
178 template <typename MultiPass>
179 static void destroy(MultiPass& mp)
181 Ownership::destroy(mp);
183 Storage::destroy(mp);
185 void swap(multi_pass_unique& x)
187 this->Ownership::swap(x);
188 this->Storage::swap(x);
191 // implement input policy functions by forwarding to the Input type
192 template <typename MultiPass>
193 inline static void advance_input(MultiPass& mp)
194 { Input::advance_input(mp); }
196 template <typename MultiPass>
197 inline static typename MultiPass::reference get_input(MultiPass& mp)
198 { return Input::get_input(mp); }
200 template <typename MultiPass>
201 inline static bool input_at_eof(MultiPass const& mp)
202 { return Input::input_at_eof(mp); }
204 template <typename MultiPass, typename TokenType>
205 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
206 { return Input::input_is_valid(mp, curtok); }
208 // checking policy functions are forwarded to the Checking type
209 template <typename MultiPass>
210 inline static void docheck(MultiPass const& mp)
211 { Checking::docheck(mp); }
213 template <typename MultiPass>
214 inline static void clear_queue(MultiPass& mp)
215 { Checking::clear_queue(mp); }
218 ///////////////////////////////////////////////////////////////////////////
219 template <typename T, typename Ownership, typename Checking
220 , typename Input, typename Storage>
221 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
222 , true, false, false>
223 : Checking, Input, Storage
225 multi_pass_unique() {}
226 multi_pass_unique(T& x) : Input(x) {}
227 multi_pass_unique(T const& x) : Input(x) {}
229 template <typename MultiPass>
230 static void destroy(MultiPass& mp)
232 Checking::destroy(mp);
234 Storage::destroy(mp);
236 void swap(multi_pass_unique& x)
238 this->Checking::swap(x);
239 this->Input::swap(x);
240 this->Storage::swap(x);
243 // ownership policy functions are forwarded to the Ownership type
244 template <typename MultiPass>
245 inline static void clone(MultiPass& mp)
246 { Ownership::clone(mp); }
248 template <typename MultiPass>
249 inline static bool release(MultiPass& mp)
250 { return Ownership::release(mp); }
252 template <typename MultiPass>
253 inline static bool is_unique(MultiPass const& mp)
254 { return Ownership::is_unique(mp); }
257 ///////////////////////////////////////////////////////////////////////////
258 template <typename T, typename Ownership, typename Checking
259 , typename Input, typename Storage>
260 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
264 multi_pass_unique() {}
265 multi_pass_unique(T const& x) {}
267 template <typename MultiPass>
268 static void destroy(MultiPass& mp)
270 Checking::destroy(mp);
272 Storage::destroy(mp);
274 void swap(multi_pass_unique& x)
276 this->Checking::swap(x);
277 this->Storage::swap(x);
280 // implement input policy functions by forwarding to the Input type
281 template <typename MultiPass>
282 inline static void advance_input(MultiPass& mp)
283 { Input::advance_input(mp); }
285 template <typename MultiPass>
286 inline static typename MultiPass::reference get_input(MultiPass& mp)
287 { return Input::get_input(mp); }
289 template <typename MultiPass>
290 inline static bool input_at_eof(MultiPass const& mp)
291 { return Input::input_at_eof(mp); }
293 template <typename MultiPass, typename TokenType>
294 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
295 { return Input::input_is_valid(mp, curtok); }
297 // ownership policy functions are forwarded to the Ownership type
298 template <typename MultiPass>
299 inline static void clone(MultiPass& mp)
300 { Ownership::clone(mp); }
302 template <typename MultiPass>
303 inline static bool release(MultiPass& mp)
304 { return Ownership::release(mp); }
306 template <typename MultiPass>
307 inline static bool is_unique(MultiPass const& mp)
308 { return Ownership::is_unique(mp); }
311 ///////////////////////////////////////////////////////////////////////////
312 template <typename T, typename Ownership, typename Checking
313 , typename Input, typename Storage>
314 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
318 multi_pass_unique() {}
319 multi_pass_unique(T& x) : Input(x) {}
320 multi_pass_unique(T const& x) : Input(x) {}
322 template <typename MultiPass>
323 static void destroy(MultiPass& mp)
326 Storage::destroy(mp);
328 void swap(multi_pass_unique& x)
330 this->Input::swap(x);
331 this->Storage::swap(x);
334 // checking policy functions are forwarded to the Checking type
335 template <typename MultiPass>
336 inline static void docheck(MultiPass const& mp)
337 { Checking::docheck(mp); }
339 template <typename MultiPass>
340 inline static void clear_queue(MultiPass& mp)
341 { Checking::clear_queue(mp); }
343 // ownership policy functions are forwarded to the Ownership type
344 template <typename MultiPass>
345 inline static void clone(MultiPass& mp)
346 { Ownership::clone(mp); }
348 template <typename MultiPass>
349 inline static bool release(MultiPass& mp)
350 { return Ownership::release(mp); }
352 template <typename MultiPass>
353 inline static bool is_unique(MultiPass const& mp)
354 { return Ownership::is_unique(mp); }
357 ///////////////////////////////////////////////////////////////////////////
358 template <typename T, typename Ownership, typename Checking
359 , typename Input, typename Storage>
360 struct multi_pass_unique<T, Ownership, Checking, Input, Storage
364 multi_pass_unique() {}
365 multi_pass_unique(T const&) {}
367 template <typename MultiPass>
368 static void destroy(MultiPass& mp)
371 Storage::destroy(mp);
373 void swap(multi_pass_unique& x)
375 this->Storage::swap(x);
378 // implement input policy functions by forwarding to the Input type
379 template <typename MultiPass>
380 inline static void advance_input(MultiPass& mp)
381 { Input::advance_input(mp); }
383 template <typename MultiPass>
384 inline static typename MultiPass::reference get_input(MultiPass& mp)
385 { return Input::get_input(mp); }
387 template <typename MultiPass>
388 inline static bool input_at_eof(MultiPass const& mp)
389 { return Input::input_at_eof(mp); }
391 template <typename MultiPass, typename TokenType>
392 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
393 { return Input::input_is_valid(mp, curtok); }
395 // checking policy functions are forwarded to the Checking type
396 template <typename MultiPass>
397 inline static void docheck(MultiPass const& mp)
398 { Checking::docheck(mp); }
400 template <typename MultiPass>
401 inline static void clear_queue(MultiPass& mp)
402 { Checking::clear_queue(mp); }
404 // ownership policy functions are forwarded to the Ownership type
405 template <typename MultiPass>
406 inline static void clone(MultiPass& mp)
407 { Ownership::clone(mp); }
409 template <typename MultiPass>
410 inline static bool release(MultiPass& mp)
411 { return Ownership::release(mp); }
413 template <typename MultiPass>
414 inline static bool is_unique(MultiPass const& mp)
415 { return Ownership::is_unique(mp); }
419 ///////////////////////////////////////////////////////////////////////////
420 // the multi_pass_shared structure is used to combine the shared data items
421 // of all policies into one single structure
422 ///////////////////////////////////////////////////////////////////////////
423 template<typename T, typename Ownership, typename Checking, typename Input
425 struct multi_pass_shared : Ownership, Checking, Input, Storage
427 explicit multi_pass_shared(T& input) : Input(input) {}
428 explicit multi_pass_shared(T const& input) : Input(input) {}
431 ///////////////////////////////////////////////////////////////////////////
432 // This is a default implementation of a policy class as required by the
433 // multi_pass template, combining 4 separate policies into one. Any other
434 // multi_pass policy class needs to follow the scheme as shown below.
435 template<typename Ownership, typename Checking, typename Input
437 struct default_policy
439 typedef Ownership ownership_policy;
440 typedef Checking checking_policy;
441 typedef Input input_policy;
442 typedef Storage storage_policy;
444 ///////////////////////////////////////////////////////////////////////
445 template <typename T>
446 struct unique : multi_pass_unique<T
447 , typename Ownership::unique, typename Checking::unique
448 , typename Input::BOOST_NESTED_TEMPLATE unique<T>
449 , typename Storage::BOOST_NESTED_TEMPLATE unique<
450 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
452 typedef typename Ownership::unique ownership_policy;
453 typedef typename Checking::unique checking_policy;
454 typedef typename Input::BOOST_NESTED_TEMPLATE unique<T>
456 typedef typename Storage::BOOST_NESTED_TEMPLATE unique<
457 typename input_policy::value_type> storage_policy;
459 typedef multi_pass_unique<T, ownership_policy, checking_policy
460 , input_policy, storage_policy> unique_base_type;
463 explicit unique(T& input) : unique_base_type(input) {}
464 explicit unique(T const& input) : unique_base_type(input) {}
467 ///////////////////////////////////////////////////////////////////////
468 template <typename T>
469 struct shared : multi_pass_shared<T
470 , typename Ownership::shared, typename Checking::shared
471 , typename Input::BOOST_NESTED_TEMPLATE shared<T>
472 , typename Storage::BOOST_NESTED_TEMPLATE shared<
473 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
475 typedef typename Ownership::shared ownership_policy;
476 typedef typename Checking::shared checking_policy;
477 typedef typename Input::BOOST_NESTED_TEMPLATE shared<T>
479 typedef typename Storage::BOOST_NESTED_TEMPLATE shared<
480 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
483 typedef multi_pass_shared<T, ownership_policy, checking_policy
484 , input_policy, storage_policy> shared_base_type;
486 explicit shared(T& input)
487 : shared_base_type(input), inhibit_clear_queue_(false) {}
488 explicit shared(T const& input)
489 : shared_base_type(input), inhibit_clear_queue_(false) {}
491 // This is needed for the correct implementation of expectation
492 // points. Normally expectation points flush any multi_pass
493 // iterator they may act on, but if the corresponding error handler
494 // is of type 'retry' no flushing of the internal buffers should be
495 // executed (even if explicitly requested).
496 bool inhibit_clear_queue_;