comparison DEPENDENCIES/generic/include/boost/spirit/home/support/container.hpp @ 16:2665513ce2d3

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