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