1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 http://spirit.sourceforge.net/
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#if !defined(BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM)
10#define BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM
11
12#if defined(_MSC_VER)
13#pragma once
14#endif
15
16#include <boost/spirit/home/support/unused.hpp>
17#include <boost/spirit/home/support/attributes_fwd.hpp>
18#include <boost/mpl/has_xxx.hpp>
19#include <boost/mpl/bool.hpp>
20#include <boost/optional.hpp>
21#include <boost/variant.hpp>
22#include <boost/preprocessor/cat.hpp>
23#include <boost/preprocessor/repeat.hpp>
24#include <boost/range/range_fwd.hpp>
25#include <iterator> // for std::iterator_traits
26
27namespace boost { namespace spirit { namespace traits
28{
29 ///////////////////////////////////////////////////////////////////////////
30 // This file contains some container utils for stl containers. The
31 // utilities provided also accept spirit's unused_type; all no-ops.
32 // Compiler optimization will easily strip these away.
33 ///////////////////////////////////////////////////////////////////////////
34
35 namespace detail
36 {
37 BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
38 BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator)
39 BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
40 BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
41 }
42
43 template <typename T, typename Enable/* = void*/>
44 struct is_container
45 : mpl::bool_<
46 detail::has_value_type<T>::value &&
47 detail::has_iterator<T>::value &&
48 detail::has_size_type<T>::value &&
49 detail::has_reference<T>::value>
50 {};
51
52 template <typename T>
53 struct is_container<T&>
54 : is_container<T>
55 {};
56
57 template <typename T>
58 struct is_container<boost::optional<T> >
59 : is_container<T>
60 {};
61
62#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
63 template<typename T>
64 struct is_container<boost::variant<T> >
65 : is_container<T>
66 {};
67
68 template<typename T0, typename T1, typename ...TN>
69 struct is_container<boost::variant<T0, T1, TN...> >
70 : mpl::bool_<is_container<T0>::value ||
71 is_container<boost::variant<T1, TN...> >::value>
72 {};
73
74#else
75#define BOOST_SPIRIT_IS_CONTAINER(z, N, data) \
76 is_container<BOOST_PP_CAT(T, N)>::value || \
77 /***/
78
79 // make sure unused variant parameters do not affect the outcome
80 template <>
81 struct is_container<boost::detail::variant::void_>
82 : mpl::false_
83 {};
84
85 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
86 struct is_container<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
87 : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
88 , BOOST_SPIRIT_IS_CONTAINER, _) false>
89 {};
90
91#undef BOOST_SPIRIT_IS_CONTAINER
92#endif
93
94 template <typename T, typename Enable/* = void*/>
95 struct is_iterator_range
96 : mpl::false_
97 {};
98
99 template <typename T>
100 struct is_iterator_range<iterator_range<T> >
101 : mpl::true_
102 {};
103
104 ///////////////////////////////////////////////////////////////////////////
105 namespace detail
106 {
107 template <typename T>
108 struct remove_value_const
109 {
110 typedef T type;
111 };
112
113 template <typename T>
114 struct remove_value_const<T const>
115 : remove_value_const<T>
116 {};
117
118 template <typename F, typename S>
119 struct remove_value_const<std::pair<F, S> >
120 {
121 typedef typename remove_value_const<F>::type first_type;
122 typedef typename remove_value_const<S>::type second_type;
123 typedef std::pair<first_type, second_type> type;
124 };
125 }
126
127 ///////////////////////////////////////////////////////////////////////
128 //[customization_container_value_default
129 template <typename Container, typename Enable/* = void*/>
130 struct container_value
131 : detail::remove_value_const<typename Container::value_type>
132 {};
133 //]
134
135 template <typename T>
136 struct container_value<T&>
137 : container_value<T>
138 {};
139
140 // this will be instantiated if the optional holds a container
141 template <typename T>
142 struct container_value<boost::optional<T> >
143 : container_value<T>
144 {};
145
146 // this will be instantiated if the variant holds a container
147 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
148 struct container_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
149 {
150 typedef typename
151 variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
152 types;
153 typedef typename
154 mpl::find_if<types, is_container<mpl::_1> >::type
155 iter;
156
157 typedef typename container_value<
158 typename mpl::if_<
159 is_same<iter, typename mpl::end<types>::type>
160 , unused_type, typename mpl::deref<iter>::type
161 >::type
162 >::type type;
163 };
164
165 //[customization_container_value_unused
166 template <>
167 struct container_value<unused_type>
168 {
169 typedef unused_type type;
170 };
171 //]
172
173 template <>
174 struct container_value<unused_type const>
175 {
176 typedef unused_type type;
177 };
178
179 ///////////////////////////////////////////////////////////////////////////
180 template <typename Container, typename Enable/* = void*/>
181 struct container_iterator
182 {
183 typedef typename Container::iterator type;
184 };
185
186 template <typename Container>
187 struct container_iterator<Container&>
188 : container_iterator<Container>
189 {};
190
191 template <typename Container>
192 struct container_iterator<Container const>
193 {
194 typedef typename Container::const_iterator type;
195 };
196
197 template <typename T>
198 struct container_iterator<optional<T> >
199 : container_iterator<T>
200 {};
201
202 template <typename T>
203 struct container_iterator<optional<T> const>
204 : container_iterator<T const>
205 {};
206
207 template <typename Iterator>
208 struct container_iterator<iterator_range<Iterator> >
209 {
210 typedef Iterator type;
211 };
212
213 template <>
214 struct container_iterator<unused_type>
215 {
216 typedef unused_type const* type;
217 };
218
219 template <>
220 struct container_iterator<unused_type const>
221 {
222 typedef unused_type const* type;
223 };
224
225 ///////////////////////////////////////////////////////////////////////////
226 template <typename T, typename Enable/* = void*/>
227 struct optional_attribute
228 {
229 typedef T const& type;
230
231 static type call(T const& val)
232 {
233 return val;
234 }
235
236 static bool is_valid(T const&)
237 {
238 return true;
239 }
240 };
241
242 template <typename T>
243 struct optional_attribute<boost::optional<T> >
244 {
245 typedef T const& type;
246
247 static type call(boost::optional<T> const& val)
248 {
249 return boost::get<T>(val);
250 }
251
252 static bool is_valid(boost::optional<T> const& val)
253 {
254 return !!val;
255 }
256 };
257
258 template <typename T>
259 typename optional_attribute<T>::type
260 optional_value(T const& val)
261 {
262 return optional_attribute<T>::call(val);
263 }
264
265 inline unused_type optional_value(unused_type)
266 {
267 return unused;
268 }
269
270 template <typename T>
271 bool has_optional_value(T const& val)
272 {
273 return optional_attribute<T>::is_valid(val);
274 }
275
276 inline bool has_optional_value(unused_type)
277 {
278 return true;
279 }
280
281 ///////////////////////////////////////////////////////////////////////////
282 template <typename Container, typename T>
283 bool push_back(Container& c, T const& val);
284
285 //[customization_push_back_default
286 template <typename Container, typename T, typename Enable/* = void*/>
287 struct push_back_container
288 {
289 static bool call(Container& c, T const& val)
290 {
291 c.insert(c.end(), val);
292 return true;
293 }
294 };
295 //]
296
297 template <typename Container, typename T>
298 struct push_back_container<optional<Container>, T>
299 {
300 static bool call(boost::optional<Container>& c, T const& val)
301 {
302 if (!c)
303 c = Container();
304 return push_back(boost::get<Container>(c), val);
305 }
306 };
307
308 namespace detail
309 {
310 template <typename T>
311 struct push_back_visitor : public static_visitor<>
312 {
313 typedef bool result_type;
314
315 push_back_visitor(T const& t) : t_(t) {}
316
317 template <typename Container>
318 bool push_back_impl(Container& c, mpl::true_) const
319 {
320 return push_back(c, t_);
321 }
322
323 template <typename T_>
324 bool push_back_impl(T_&, mpl::false_) const
325 {
326 // this variant doesn't hold a container
327 BOOST_ASSERT(false && "This variant doesn't hold a container");
328 return false;
329 }
330
331 template <typename T_>
332 bool operator()(T_& c) const
333 {
334 return push_back_impl(c, typename is_container<T_>::type());
335 }
336
337 T const& t_;
338 };
339 }
340
341 template <BOOST_VARIANT_ENUM_PARAMS(typename T_), typename T>
342 struct push_back_container<variant<BOOST_VARIANT_ENUM_PARAMS(T_)>, T>
343 {
344 static bool call(variant<BOOST_VARIANT_ENUM_PARAMS(T_)>& c, T const& val)
345 {
346 return apply_visitor(detail::push_back_visitor<T>(val), c);
347 }
348 };
349
350 template <typename Container, typename T>
351 bool push_back(Container& c, T const& val)
352 {
353 return push_back_container<Container, T>::call(c, val);
354 }
355
356 //[customization_push_back_unused
357 template <typename Container>
358 bool push_back(Container&, unused_type)
359 {
360 return true;
361 }
362 //]
363
364 template <typename T>
365 bool push_back(unused_type, T const&)
366 {
367 return true;
368 }
369
370 inline bool push_back(unused_type, unused_type)
371 {
372 return true;
373 }
374
375 ///////////////////////////////////////////////////////////////////////////
376 template <typename Container, typename Enable/* = void*/>
377 struct is_empty_container
378 {
379 static bool call(Container const& c)
380 {
381 return c.empty();
382 }
383 };
384
385 template <typename Container>
386 bool is_empty(Container const& c)
387 {
388 return is_empty_container<Container>::call(c);
389 }
390
391 inline bool is_empty(unused_type)
392 {
393 return true;
394 }
395
396 ///////////////////////////////////////////////////////////////////////////
397 // Ensure the attribute is actually a container type
398 template <typename Container, typename Enable/* = void*/>
399 struct make_container_attribute
400 {
401 static void call(Container&)
402 {
403 // for static types this function does nothing
404 }
405 };
406
407 template <typename T>
408 void make_container(T& t)
409 {
410 make_container_attribute<T>::call(t);
411 }
412
413 inline void make_container(unused_type)
414 {
415 }
416
417 ///////////////////////////////////////////////////////////////////////////
418 template <typename Container, typename Enable/* = void*/>
419 struct begin_container
420 {
421 static typename container_iterator<Container>::type call(Container& c)
422 {
423 return c.begin();
424 }
425 };
426
427 template <typename Container>
428 typename spirit::result_of::begin<Container>::type
429 begin(Container& c)
430 {
431 return begin_container<Container>::call(c);
432 }
433
434 inline unused_type const*
435 begin(unused_type)
436 {
437 return &unused;
438 }
439
440 ///////////////////////////////////////////////////////////////////////////
441 template <typename Container, typename Enable/* = void*/>
442 struct end_container
443 {
444 static typename container_iterator<Container>::type call(Container& c)
445 {
446 return c.end();
447 }
448 };
449
450 template <typename Container>
451 inline typename spirit::result_of::end<Container>::type
452 end(Container& c)
453 {
454 return end_container<Container>::call(c);
455 }
456
457 inline unused_type const*
458 end(unused_type)
459 {
460 return &unused;
461 }
462
463 ///////////////////////////////////////////////////////////////////////////
464 template <typename Iterator, typename Enable/* = void*/>
465 struct deref_iterator
466 {
467 typedef typename std::iterator_traits<Iterator>::reference type;
468 static type call(Iterator& it)
469 {
470 return *it;
471 }
472 };
473
474 template <typename Iterator>
475 typename deref_iterator<Iterator>::type
476 deref(Iterator& it)
477 {
478 return deref_iterator<Iterator>::call(it);
479 }
480
481 inline unused_type
482 deref(unused_type const*)
483 {
484 return unused;
485 }
486
487 ///////////////////////////////////////////////////////////////////////////
488 template <typename Iterator, typename Enable/* = void*/>
489 struct next_iterator
490 {
491 static void call(Iterator& it)
492 {
493 ++it;
494 }
495 };
496
497 template <typename Iterator>
498 void next(Iterator& it)
499 {
500 next_iterator<Iterator>::call(it);
501 }
502
503 inline void next(unused_type const*)
504 {
505 // do nothing
506 }
507
508 ///////////////////////////////////////////////////////////////////////////
509 template <typename Iterator, typename Enable/* = void*/>
510 struct compare_iterators
511 {
512 static bool call(Iterator const& it1, Iterator const& it2)
513 {
514 return it1 == it2;
515 }
516 };
517
518 template <typename Iterator>
519 bool compare(Iterator& it1, Iterator& it2)
520 {
521 return compare_iterators<Iterator>::call(it1, it2);
522 }
523
524 inline bool compare(unused_type const*, unused_type const*)
525 {
526 return false;
527 }
528}}}
529
530///////////////////////////////////////////////////////////////////////////////
531namespace boost { namespace spirit { namespace result_of
532{
533 ///////////////////////////////////////////////////////////////////////////
534 template <typename T>
535 struct optional_value
536 {
537 typedef T type;
538 };
539
540 template <typename T>
541 struct optional_value<boost::optional<T> >
542 {
543 typedef T type;
544 };
545
546 template <typename T>
547 struct optional_value<boost::optional<T> const>
548 {
549 typedef T const type;
550 };
551
552 template <>
553 struct optional_value<unused_type>
554 {
555 typedef unused_type type;
556 };
557
558 template <>
559 struct optional_value<unused_type const>
560 {
561 typedef unused_type type;
562 };
563
564 ///////////////////////////////////////////////////////////////////////////
565 template <typename Container>
566 struct begin
567 : traits::container_iterator<Container>
568 {};
569
570 template <typename Container>
571 struct end
572 : traits::container_iterator<Container>
573 {};
574
575 template <typename Iterator>
576 struct deref
577 : traits::deref_iterator<Iterator>
578 {};
579
580 template <>
581 struct deref<unused_type const*>
582 {
583 typedef unused_type type;
584 };
585
586}}}
587
588#endif
589

source code of boost/libs/spirit/include/boost/spirit/home/support/container.hpp