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 #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 typename range_const_iterator< 211 iterator_range<Iterator> >::type type; 212 }; 213 214 template <> 215 struct container_iterator<unused_type> 216 { 217 typedef unused_type const* type; 218 }; 219 220 template <> 221 struct container_iterator<unused_type const> 222 { 223 typedef unused_type const* type; 224 }; 225 226 /////////////////////////////////////////////////////////////////////////// 227 template <typename T, typename Enable/* = void*/> 228 struct optional_attribute 229 { 230 typedef T const& type; 231 callboost::spirit::traits::optional_attribute232 static type call(T const& val) 233 { 234 return val; 235 } 236 is_validboost::spirit::traits::optional_attribute237 static bool is_valid(T const&) 238 { 239 return true; 240 } 241 }; 242 243 template <typename T> 244 struct optional_attribute<boost::optional<T> > 245 { 246 typedef T const& type; 247 callboost::spirit::traits::optional_attribute248 static type call(boost::optional<T> const& val) 249 { 250 return boost::get<T>(val); 251 } 252 is_validboost::spirit::traits::optional_attribute253 static bool is_valid(boost::optional<T> const& val) 254 { 255 return !!val; 256 } 257 }; 258 259 template <typename T> 260 typename optional_attribute<T>::type optional_value(T const & val)261 optional_value(T const& val) 262 { 263 return optional_attribute<T>::call(val); 264 } 265 optional_value(unused_type)266 inline unused_type optional_value(unused_type) 267 { 268 return unused; 269 } 270 271 template <typename T> has_optional_value(T const & val)272 bool has_optional_value(T const& val) 273 { 274 return optional_attribute<T>::is_valid(val); 275 } 276 has_optional_value(unused_type)277 inline bool has_optional_value(unused_type) 278 { 279 return true; 280 } 281 282 /////////////////////////////////////////////////////////////////////////// 283 template <typename Container, typename T> 284 bool push_back(Container& c, T const& val); 285 286 //[customization_push_back_default 287 template <typename Container, typename T, typename Enable/* = void*/> 288 struct push_back_container 289 { callboost::spirit::traits::push_back_container290 static bool call(Container& c, T const& val) 291 { 292 c.insert(c.end(), val); 293 return true; 294 } 295 }; 296 //] 297 298 template <typename Container, typename T> 299 struct push_back_container<optional<Container>, T> 300 { callboost::spirit::traits::push_back_container301 static bool call(boost::optional<Container>& c, T const& val) 302 { 303 if (!c) 304 c = Container(); 305 return push_back(boost::get<Container>(c), val); 306 } 307 }; 308 309 namespace detail 310 { 311 template <typename T> 312 struct push_back_visitor : public static_visitor<> 313 { 314 typedef bool result_type; 315 push_back_visitorboost::spirit::traits::detail::push_back_visitor316 push_back_visitor(T const& t) : t_(t) {} 317 318 template <typename Container> push_back_implboost::spirit::traits::detail::push_back_visitor319 bool push_back_impl(Container& c, mpl::true_) const 320 { 321 return push_back(c, t_); 322 } 323 324 template <typename T_> push_back_implboost::spirit::traits::detail::push_back_visitor325 bool push_back_impl(T_&, mpl::false_) const 326 { 327 // this variant doesn't hold a container 328 BOOST_ASSERT(false && "This variant doesn't hold a container"); 329 return false; 330 } 331 332 template <typename T_> operator ()boost::spirit::traits::detail::push_back_visitor333 bool operator()(T_& c) const 334 { 335 return push_back_impl(c, typename is_container<T_>::type()); 336 } 337 338 T const& t_; 339 }; 340 } 341 342 template <BOOST_VARIANT_ENUM_PARAMS(typename T_), typename T> 343 struct push_back_container<variant<BOOST_VARIANT_ENUM_PARAMS(T_)>, T> 344 { callboost::spirit::traits::push_back_container345 static bool call(variant<BOOST_VARIANT_ENUM_PARAMS(T_)>& c, T const& val) 346 { 347 return apply_visitor(detail::push_back_visitor<T>(val), c); 348 } 349 }; 350 351 template <typename Container, typename T> push_back(Container & c,T const & val)352 bool push_back(Container& c, T const& val) 353 { 354 return push_back_container<Container, T>::call(c, val); 355 } 356 357 //[customization_push_back_unused 358 template <typename Container> push_back(Container &,unused_type)359 bool push_back(Container&, unused_type) 360 { 361 return true; 362 } 363 //] 364 365 template <typename T> push_back(unused_type,T const &)366 bool push_back(unused_type, T const&) 367 { 368 return true; 369 } 370 push_back(unused_type,unused_type)371 inline bool push_back(unused_type, unused_type) 372 { 373 return true; 374 } 375 376 /////////////////////////////////////////////////////////////////////////// 377 template <typename Container, typename Enable/* = void*/> 378 struct is_empty_container 379 { callboost::spirit::traits::is_empty_container380 static bool call(Container const& c) 381 { 382 return c.empty(); 383 } 384 }; 385 386 template <typename Container> is_empty(Container const & c)387 bool is_empty(Container const& c) 388 { 389 return is_empty_container<Container>::call(c); 390 } 391 is_empty(unused_type)392 inline bool is_empty(unused_type) 393 { 394 return true; 395 } 396 397 /////////////////////////////////////////////////////////////////////////// 398 // Ensure the attribute is actually a container type 399 template <typename Container, typename Enable/* = void*/> 400 struct make_container_attribute 401 { callboost::spirit::traits::make_container_attribute402 static void call(Container&) 403 { 404 // for static types this function does nothing 405 } 406 }; 407 408 template <typename T> make_container(T & t)409 void make_container(T& t) 410 { 411 make_container_attribute<T>::call(t); 412 } 413 make_container(unused_type)414 inline void make_container(unused_type) 415 { 416 } 417 418 /////////////////////////////////////////////////////////////////////////// 419 template <typename Container, typename Enable/* = void*/> 420 struct begin_container 421 { callboost::spirit::traits::begin_container422 static typename container_iterator<Container>::type call(Container& c) 423 { 424 return c.begin(); 425 } 426 }; 427 428 template <typename Container> 429 typename spirit::result_of::begin<Container>::type begin(Container & c)430 begin(Container& c) 431 { 432 return begin_container<Container>::call(c); 433 } 434 435 inline unused_type const* begin(unused_type)436 begin(unused_type) 437 { 438 return &unused; 439 } 440 441 /////////////////////////////////////////////////////////////////////////// 442 template <typename Container, typename Enable/* = void*/> 443 struct end_container 444 { callboost::spirit::traits::end_container445 static typename container_iterator<Container>::type call(Container& c) 446 { 447 return c.end(); 448 } 449 }; 450 451 template <typename Container> 452 inline typename spirit::result_of::end<Container>::type end(Container & c)453 end(Container& c) 454 { 455 return end_container<Container>::call(c); 456 } 457 458 inline unused_type const* end(unused_type)459 end(unused_type) 460 { 461 return &unused; 462 } 463 464 /////////////////////////////////////////////////////////////////////////// 465 template <typename Iterator, typename Enable/* = void*/> 466 struct deref_iterator 467 { 468 typedef typename boost::detail::iterator_traits<Iterator>::reference type; callboost::spirit::traits::deref_iterator469 static type call(Iterator& it) 470 { 471 return *it; 472 } 473 }; 474 475 template <typename Iterator> 476 typename deref_iterator<Iterator>::type deref(Iterator & it)477 deref(Iterator& it) 478 { 479 return deref_iterator<Iterator>::call(it); 480 } 481 482 inline unused_type deref(unused_type const *)483 deref(unused_type const*) 484 { 485 return unused; 486 } 487 488 /////////////////////////////////////////////////////////////////////////// 489 template <typename Iterator, typename Enable/* = void*/> 490 struct next_iterator 491 { callboost::spirit::traits::next_iterator492 static void call(Iterator& it) 493 { 494 ++it; 495 } 496 }; 497 498 template <typename Iterator> next(Iterator & it)499 void next(Iterator& it) 500 { 501 next_iterator<Iterator>::call(it); 502 } 503 next(unused_type const *)504 inline void next(unused_type const*) 505 { 506 // do nothing 507 } 508 509 /////////////////////////////////////////////////////////////////////////// 510 template <typename Iterator, typename Enable/* = void*/> 511 struct compare_iterators 512 { callboost::spirit::traits::compare_iterators513 static bool call(Iterator const& it1, Iterator const& it2) 514 { 515 return it1 == it2; 516 } 517 }; 518 519 template <typename Iterator> compare(Iterator & it1,Iterator & it2)520 bool compare(Iterator& it1, Iterator& it2) 521 { 522 return compare_iterators<Iterator>::call(it1, it2); 523 } 524 compare(unused_type const *,unused_type const *)525 inline bool compare(unused_type const*, unused_type const*) 526 { 527 return false; 528 } 529 }}} 530 531 /////////////////////////////////////////////////////////////////////////////// 532 namespace boost { namespace spirit { namespace result_of 533 { 534 /////////////////////////////////////////////////////////////////////////// 535 template <typename T> 536 struct optional_value 537 { 538 typedef T type; 539 }; 540 541 template <typename T> 542 struct optional_value<boost::optional<T> > 543 { 544 typedef T type; 545 }; 546 547 template <typename T> 548 struct optional_value<boost::optional<T> const> 549 { 550 typedef T const type; 551 }; 552 553 template <> 554 struct optional_value<unused_type> 555 { 556 typedef unused_type type; 557 }; 558 559 template <> 560 struct optional_value<unused_type const> 561 { 562 typedef unused_type type; 563 }; 564 565 /////////////////////////////////////////////////////////////////////////// 566 template <typename Container> 567 struct begin 568 : traits::container_iterator<Container> 569 {}; 570 571 template <typename Container> 572 struct end 573 : traits::container_iterator<Container> 574 {}; 575 576 template <typename Iterator> 577 struct deref 578 : traits::deref_iterator<Iterator> 579 {}; 580 581 template <> 582 struct deref<unused_type const*> 583 { 584 typedef unused_type type; 585 }; 586 587 }}} 588 589 #endif 590