Chris@16: /*============================================================================= Chris@16: Copyright (c) 2004 Angus Leeming Chris@16: Copyright (c) 2004 Joel de Guzman 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: #ifndef BOOST_PHOENIX_CONTAINER_DETAIL_CONTAINER_HPP Chris@16: #define BOOST_PHOENIX_CONTAINER_DETAIL_CONTAINER_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace phoenix { namespace stl Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // Metafunctions "value_type_of", "key_type_of" etc. Chris@16: // Chris@16: // These metafunctions define a typedef "type" that returns the nested Chris@16: // type if it exists. If not then the typedef returns void. Chris@16: // Chris@16: // For example, "value_type_of >::type" is "int" whilst Chris@16: // "value_type_of::type" is "void". Chris@16: // Chris@16: // I use a macro to define structs "value_type_of" etc simply to cut Chris@16: // down on the amount of code. The macro is #undef-ed immediately after Chris@16: // its final use. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////c////////////// Chris@16: #define MEMBER_TYPE_OF(MEMBER_TYPE) \ Chris@16: template \ Chris@16: struct BOOST_PP_CAT(MEMBER_TYPE, _of) \ Chris@16: { \ Chris@16: typedef typename C::MEMBER_TYPE type; \ Chris@16: } Chris@16: Chris@16: MEMBER_TYPE_OF(allocator_type); Chris@16: MEMBER_TYPE_OF(const_iterator); Chris@16: MEMBER_TYPE_OF(const_reference); Chris@16: MEMBER_TYPE_OF(const_reverse_iterator); Chris@16: MEMBER_TYPE_OF(container_type); Chris@16: MEMBER_TYPE_OF(data_type); Chris@16: MEMBER_TYPE_OF(iterator); Chris@16: MEMBER_TYPE_OF(key_compare); Chris@16: MEMBER_TYPE_OF(key_type); Chris@16: MEMBER_TYPE_OF(reference); Chris@16: MEMBER_TYPE_OF(reverse_iterator); Chris@16: MEMBER_TYPE_OF(size_type); Chris@16: MEMBER_TYPE_OF(value_compare); Chris@16: MEMBER_TYPE_OF(value_type); Chris@16: Chris@16: #undef MEMBER_TYPE_OF Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // Const-Qualified types. Chris@16: // Chris@16: // Many of the stl member functions have const and non-const Chris@16: // overloaded versions that return distinct types. For example: Chris@16: // Chris@16: // iterator begin(); Chris@16: // const_iterator begin() const; Chris@16: // Chris@16: // The three class templates defined below, Chris@16: // const_qualified_reference_of, const_qualified_iterator_of Chris@16: // and const_qualified_reverse_iterator_of provide a means to extract Chris@16: // this return type automatically. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct const_qualified_reference_of Chris@16: { Chris@16: typedef typename Chris@16: boost::mpl::eval_if_c< Chris@16: boost::is_const::value Chris@16: , const_reference_of Chris@16: , reference_of Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct const_qualified_iterator_of Chris@16: { Chris@16: typedef typename Chris@16: boost::mpl::eval_if_c< Chris@16: boost::is_const::value Chris@16: , const_iterator_of Chris@16: , iterator_of Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct const_qualified_reverse_iterator_of Chris@16: { Chris@16: typedef typename Chris@16: boost::mpl::eval_if_c< Chris@16: boost::is_const::value Chris@16: , const_reverse_iterator_of Chris@16: , reverse_iterator_of Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // has_mapped_type Chris@16: // Chris@16: // Given a container C, determine if it is a map or multimap Chris@16: // by checking if it has a member type named "mapped_type". Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace stl_impl Chris@16: { Chris@16: struct one { char a[1]; }; Chris@16: struct two { char a[2]; }; Chris@16: Chris@16: template Chris@16: one has_mapped_type(typename C::mapped_type(*)()); Chris@16: Chris@16: template Chris@16: two has_mapped_type(...); Chris@16: Chris@16: template Chris@16: struct enable_if_is_void Chris@16: {}; Chris@16: Chris@16: template<> Chris@16: struct enable_if_is_void Chris@16: { Chris@16: typedef void type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct disable_if_is_void Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct disable_if_is_void Chris@16: {}; Chris@16: } Chris@16: Chris@16: template Chris@16: struct has_mapped_type Chris@16: : boost::mpl::bool_< Chris@16: sizeof(stl_impl::has_mapped_type(0)) == sizeof(stl_impl::one) Chris@16: > Chris@16: {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // map_insert_returns_pair Chris@16: // Chris@16: // Distinguish a map from a multimap by checking the return type Chris@16: // of its "insert" member function. A map returns a pair while Chris@16: // a multimap returns an iterator. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace stl_impl Chris@16: { Chris@16: // Cool implementation of map_insert_returns_pair by Daniel Wallin. Chris@16: // Thanks Daniel!!! I owe you a Pizza! Chris@16: Chris@16: template Chris@16: one map_insert_returns_pair_check(std::pair const&); Chris@16: Chris@16: template Chris@16: two map_insert_returns_pair_check(T const&); Chris@16: Chris@16: template Chris@16: struct map_insert_returns_pair Chris@16: { Chris@16: static typename C::value_type const& get; Chris@16: BOOST_STATIC_CONSTANT(int, Chris@16: value = sizeof( Chris@16: map_insert_returns_pair_check(((C*)0)->insert(get)))); Chris@16: typedef boost::mpl::bool_ type; Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: struct map_insert_returns_pair Chris@16: : stl_impl::map_insert_returns_pair::type {}; Chris@16: Chris@16: }}} // namespace boost::phoenix::stl Chris@16: Chris@16: #endif // BOOST_PHOENIX_STL_CONTAINER_TRAITS_HPP