Chris@16: /*============================================================================= Chris@16: Copyright (c) 2001-2011 Joel de Guzman Chris@16: Copyright (c) 2001-2011 Hartmut Kaiser Chris@16: http://spirit.sourceforge.net/ Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: #if !defined(BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM) Chris@16: #define BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include // for boost::detail::iterator_traits Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit { namespace traits Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // This file contains some container utils for stl containers. The Chris@16: // utilities provided also accept spirit's unused_type; all no-ops. Chris@16: // Compiler optimization will easily strip these away. Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(reference) Chris@16: } Chris@16: Chris@16: template Chris@16: struct is_container Chris@16: : mpl::bool_< Chris@16: detail::has_value_type::value && Chris@16: detail::has_iterator::value && Chris@16: detail::has_size_type::value && Chris@16: detail::has_reference::value> Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_container Chris@16: : is_container Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_container > Chris@16: : is_container Chris@16: {}; Chris@16: Chris@101: #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) Chris@101: template Chris@101: struct is_container > Chris@101: : is_container Chris@101: {}; Chris@101: Chris@101: template Chris@101: struct is_container > Chris@101: : mpl::bool_::value || Chris@101: is_container >::value> Chris@101: {}; Chris@101: Chris@101: #else Chris@16: #define BOOST_SPIRIT_IS_CONTAINER(z, N, data) \ Chris@16: is_container::value || \ Chris@16: /***/ Chris@16: Chris@16: // make sure unused variant parameters do not affect the outcome Chris@16: template <> Chris@16: struct is_container Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_container > Chris@16: : mpl::bool_ Chris@16: {}; Chris@16: Chris@16: #undef BOOST_SPIRIT_IS_CONTAINER Chris@101: #endif Chris@16: Chris@16: template Chris@16: struct is_iterator_range Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_iterator_range > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct remove_value_const Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct remove_value_const Chris@16: : remove_value_const Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct remove_value_const > Chris@16: { Chris@16: typedef typename remove_value_const::type first_type; Chris@16: typedef typename remove_value_const::type second_type; Chris@16: typedef std::pair type; Chris@16: }; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: //[customization_container_value_default Chris@16: template Chris@16: struct container_value Chris@16: : detail::remove_value_const Chris@16: {}; Chris@16: //] Chris@16: Chris@16: template Chris@16: struct container_value Chris@16: : container_value Chris@16: {}; Chris@16: Chris@16: // this will be instantiated if the optional holds a container Chris@16: template Chris@16: struct container_value > Chris@16: : container_value Chris@16: {}; Chris@16: Chris@16: // this will be instantiated if the variant holds a container Chris@16: template Chris@16: struct container_value > Chris@16: { Chris@16: typedef typename Chris@16: variant::types Chris@16: types; Chris@16: typedef typename Chris@16: mpl::find_if >::type Chris@16: iter; Chris@16: Chris@16: typedef typename container_value< Chris@16: typename mpl::if_< Chris@16: is_same::type> Chris@16: , unused_type, typename mpl::deref::type Chris@16: >::type Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: //[customization_container_value_unused Chris@16: template <> Chris@16: struct container_value Chris@16: { Chris@16: typedef unused_type type; Chris@16: }; Chris@16: //] Chris@16: Chris@16: template <> Chris@16: struct container_value Chris@16: { Chris@16: typedef unused_type type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct container_iterator Chris@16: { Chris@16: typedef typename Container::iterator type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct container_iterator Chris@16: : container_iterator Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct container_iterator Chris@16: { Chris@16: typedef typename Container::const_iterator type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct container_iterator > Chris@16: : container_iterator Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct container_iterator const> Chris@16: : container_iterator Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct container_iterator > Chris@16: { Chris@16: typedef typename range_const_iterator< Chris@16: iterator_range >::type type; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct container_iterator Chris@16: { Chris@16: typedef unused_type const* type; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct container_iterator Chris@16: { Chris@16: typedef unused_type const* type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct optional_attribute Chris@16: { Chris@16: typedef T const& type; Chris@16: Chris@16: static type call(T const& val) Chris@16: { Chris@16: return val; Chris@16: } Chris@16: Chris@16: static bool is_valid(T const&) Chris@16: { Chris@16: return true; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct optional_attribute > Chris@16: { Chris@16: typedef T const& type; Chris@16: Chris@16: static type call(boost::optional const& val) Chris@16: { Chris@16: return boost::get(val); Chris@16: } Chris@16: Chris@16: static bool is_valid(boost::optional const& val) Chris@16: { Chris@101: return !!val; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: typename optional_attribute::type Chris@16: optional_value(T const& val) Chris@16: { Chris@16: return optional_attribute::call(val); Chris@16: } Chris@16: Chris@16: inline unused_type optional_value(unused_type) Chris@16: { Chris@16: return unused; Chris@16: } Chris@16: Chris@16: template Chris@16: bool has_optional_value(T const& val) Chris@16: { Chris@16: return optional_attribute::is_valid(val); Chris@16: } Chris@16: Chris@16: inline bool has_optional_value(unused_type) Chris@16: { Chris@16: return true; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: bool push_back(Container& c, T const& val); Chris@16: Chris@16: //[customization_push_back_default Chris@16: template Chris@16: struct push_back_container Chris@16: { Chris@16: static bool call(Container& c, T const& val) Chris@16: { Chris@16: c.insert(c.end(), val); Chris@16: return true; Chris@16: } Chris@16: }; Chris@16: //] Chris@16: Chris@16: template Chris@16: struct push_back_container, T> Chris@16: { Chris@16: static bool call(boost::optional& c, T const& val) Chris@16: { Chris@16: if (!c) Chris@16: c = Container(); Chris@16: return push_back(boost::get(c), val); Chris@16: } Chris@16: }; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct push_back_visitor : public static_visitor<> Chris@16: { Chris@16: typedef bool result_type; Chris@16: Chris@16: push_back_visitor(T const& t) : t_(t) {} Chris@16: Chris@16: template Chris@16: bool push_back_impl(Container& c, mpl::true_) const Chris@16: { Chris@16: return push_back(c, t_); Chris@16: } Chris@16: Chris@16: template Chris@16: bool push_back_impl(T_&, mpl::false_) const Chris@16: { Chris@16: // this variant doesn't hold a container Chris@16: BOOST_ASSERT(false && "This variant doesn't hold a container"); Chris@16: return false; Chris@16: } Chris@16: Chris@16: template Chris@16: bool operator()(T_& c) const Chris@16: { Chris@16: return push_back_impl(c, typename is_container::type()); Chris@16: } Chris@16: Chris@16: T const& t_; Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: struct push_back_container, T> Chris@16: { Chris@16: static bool call(variant& c, T const& val) Chris@16: { Chris@16: return apply_visitor(detail::push_back_visitor(val), c); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: bool push_back(Container& c, T const& val) Chris@16: { Chris@16: return push_back_container::call(c, val); Chris@16: } Chris@16: Chris@16: //[customization_push_back_unused Chris@16: template Chris@16: bool push_back(Container&, unused_type) Chris@16: { Chris@16: return true; Chris@16: } Chris@16: //] Chris@16: Chris@16: template Chris@16: bool push_back(unused_type, T const&) Chris@16: { Chris@16: return true; Chris@16: } Chris@16: Chris@16: inline bool push_back(unused_type, unused_type) Chris@16: { Chris@16: return true; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct is_empty_container Chris@16: { Chris@16: static bool call(Container const& c) Chris@16: { Chris@16: return c.empty(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: bool is_empty(Container const& c) Chris@16: { Chris@16: return is_empty_container::call(c); Chris@16: } Chris@16: Chris@16: inline bool is_empty(unused_type) Chris@16: { Chris@16: return true; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Ensure the attribute is actually a container type Chris@16: template Chris@16: struct make_container_attribute Chris@16: { Chris@16: static void call(Container&) Chris@16: { Chris@16: // for static types this function does nothing Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: void make_container(T& t) Chris@16: { Chris@16: make_container_attribute::call(t); Chris@16: } Chris@16: Chris@16: inline void make_container(unused_type) Chris@16: { Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct begin_container Chris@16: { Chris@16: static typename container_iterator::type call(Container& c) Chris@16: { Chris@16: return c.begin(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: typename spirit::result_of::begin::type Chris@16: begin(Container& c) Chris@16: { Chris@16: return begin_container::call(c); Chris@16: } Chris@16: Chris@16: inline unused_type const* Chris@16: begin(unused_type) Chris@16: { Chris@16: return &unused; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct end_container Chris@16: { Chris@16: static typename container_iterator::type call(Container& c) Chris@16: { Chris@16: return c.end(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline typename spirit::result_of::end::type Chris@16: end(Container& c) Chris@16: { Chris@16: return end_container::call(c); Chris@16: } Chris@16: Chris@16: inline unused_type const* Chris@16: end(unused_type) Chris@16: { Chris@16: return &unused; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct deref_iterator Chris@16: { Chris@16: typedef typename boost::detail::iterator_traits::reference type; Chris@16: static type call(Iterator& it) Chris@16: { Chris@16: return *it; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: typename deref_iterator::type Chris@16: deref(Iterator& it) Chris@16: { Chris@16: return deref_iterator::call(it); Chris@16: } Chris@16: Chris@16: inline unused_type Chris@16: deref(unused_type const*) Chris@16: { Chris@16: return unused; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct next_iterator Chris@16: { Chris@16: static void call(Iterator& it) Chris@16: { Chris@16: ++it; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: void next(Iterator& it) Chris@16: { Chris@16: next_iterator::call(it); Chris@16: } Chris@16: Chris@16: inline void next(unused_type const*) Chris@16: { Chris@16: // do nothing Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct compare_iterators Chris@16: { Chris@16: static bool call(Iterator const& it1, Iterator const& it2) Chris@16: { Chris@16: return it1 == it2; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: bool compare(Iterator& it1, Iterator& it2) Chris@16: { Chris@16: return compare_iterators::call(it1, it2); Chris@16: } Chris@16: Chris@16: inline bool compare(unused_type const*, unused_type const*) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: }}} Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit { namespace result_of Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct optional_value Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct optional_value > Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct optional_value const> Chris@16: { Chris@16: typedef T const type; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct optional_value Chris@16: { Chris@16: typedef unused_type type; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct optional_value Chris@16: { Chris@16: typedef unused_type type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct begin Chris@16: : traits::container_iterator Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct end Chris@16: : traits::container_iterator Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct deref Chris@16: : traits::deref_iterator Chris@16: {}; Chris@16: Chris@16: template <> Chris@16: struct deref Chris@16: { Chris@16: typedef unused_type type; Chris@16: }; Chris@16: Chris@16: }}} Chris@16: Chris@16: #endif