/*============================================================================= Copyright (c) 2001-2014 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_X3_CONTAINER_FEBRUARY_06_2007_1001AM) #define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM #include #include #include #include #include #include #include #include #include namespace boost { namespace spirit { namespace x3 { namespace traits { /////////////////////////////////////////////////////////////////////////// // This file contains some container utils for stl containers. /////////////////////////////////////////////////////////////////////////// namespace detail { BOOST_TTI_HAS_TYPE(value_type) BOOST_TTI_HAS_TYPE(iterator) BOOST_TTI_HAS_TYPE(size_type) BOOST_TTI_HAS_TYPE(reference) BOOST_TTI_HAS_TYPE(key_type) } template using is_container = mpl::bool_< detail::has_type_value_type::value && detail::has_type_iterator::value && detail::has_type_size_type::value && detail::has_type_reference::value>; template using is_associative = mpl::bool_< detail::has_type_key_type::value>; template struct is_reservable : mpl::false_ {}; template struct is_reservable().reserve(0))> : mpl::true_ {}; /////////////////////////////////////////////////////////////////////////// namespace detail { template struct remove_value_const : mpl::identity {}; 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; }; } /////////////////////////////////////////////////////////////////////// template struct container_value : detail::remove_value_const {}; template struct container_value : container_value {}; // There is no single container value for fusion maps, but because output // of this metafunc is used to check wheter parser's attribute can be // saved to container, we simply return whole fusion::map as is // so that check can be done in traits::is_substitute specialisation template struct container_value , fusion::traits::is_associative , mpl::false_ >::type >::type> : mpl::identity {}; template <> struct container_value : mpl::identity {}; /////////////////////////////////////////////////////////////////////////// template struct container_iterator : mpl::identity {}; template struct container_iterator : mpl::identity {}; template <> struct container_iterator : mpl::identity {}; template <> struct container_iterator : mpl::identity {}; /////////////////////////////////////////////////////////////////////////// template bool push_back(Container& c, T&& val); template struct push_back_container { template static bool call(Container& c, T&& val) { c.insert(c.end(), static_cast(val)); return true; } }; template inline bool push_back(Container& c, T&& val) { return push_back_container::call(c, static_cast(val)); } template inline bool push_back(Container&, unused_type) { return true; } template inline bool push_back(unused_type, T&&) { return true; } inline bool push_back(unused_type, unused_type) { return true; } /////////////////////////////////////////////////////////////////////////// template bool append(Container& c, Iterator first, Iterator last); template struct append_container { private: template static void reserve(Container& /* c */, Iterator /* first */, Iterator /* last */, mpl::false_) { // Not all containers have "reserve" } template static void reserve(Container& c, Iterator first, Iterator last, mpl::true_) { c.reserve(c.size() + std::distance(first, last)); } template static void insert(Container& c, Iterator first, Iterator last, mpl::false_) { c.insert(c.end(), first, last); } template static void insert(Container& c, Iterator first, Iterator last, mpl::true_) { c.insert(first, last); } public: template static bool call(Container& c, Iterator first, Iterator last) { reserve(c, first, last, is_reservable{}); insert(c, first, last, is_associative{}); return true; } }; template inline bool append(Container& c, Iterator first, Iterator last) { return append_container::call(c, first, last); } template inline bool append(unused_type, Iterator /* first */, Iterator /* last */) { return true; } /////////////////////////////////////////////////////////////////////////// template struct is_empty_container { static bool call(Container const& c) { return c.empty(); } }; template inline bool is_empty(Container const& c) { return is_empty_container::call(c); } inline bool is_empty(unused_type) { return true; } /////////////////////////////////////////////////////////////////////////// template struct begin_container { static typename container_iterator::type call(Container& c) { return c.begin(); } }; template inline typename container_iterator::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 container_iterator::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; } /////////////////////////////////////////////////////////////////////////// template struct build_container : mpl::identity> {}; template struct build_container > : build_container {}; template <> struct build_container : mpl::identity {}; template <> struct build_container : mpl::identity {}; }}}} #endif