1 /*============================================================================= 2 Copyright (c) 2004 Angus Leeming 3 Copyright (c) 2004 Joel de Guzman 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #ifndef BOOST_PHOENIX_CONTAINER_DETAIL_CONTAINER_HPP 9 #define BOOST_PHOENIX_CONTAINER_DETAIL_CONTAINER_HPP 10 11 #include <utility> 12 #include <boost/mpl/eval_if.hpp> 13 #include <boost/type_traits/is_same.hpp> 14 #include <boost/type_traits/is_const.hpp> 15 #include <boost/type_traits/is_convertible.hpp> 16 17 namespace boost { namespace phoenix { namespace stl 18 { 19 /////////////////////////////////////////////////////////////////////////////// 20 // 21 // Metafunctions "value_type_of", "key_type_of" etc. 22 // 23 // These metafunctions define a typedef "type" that returns the nested 24 // type if it exists. If not then the typedef returns void. 25 // 26 // For example, "value_type_of<std::vector<int> >::type" is "int" whilst 27 // "value_type_of<double>::type" is "void". 28 // 29 // I use a macro to define structs "value_type_of" etc simply to cut 30 // down on the amount of code. The macro is #undef-ed immediately after 31 // its final use. 32 // 33 /////////////////////////////////////////////////////////////////c////////////// 34 #define MEMBER_TYPE_OF(MEMBER_TYPE) \ 35 template <typename C> \ 36 struct BOOST_PP_CAT(MEMBER_TYPE, _of) \ 37 { \ 38 typedef typename C::MEMBER_TYPE type; \ 39 } 40 41 MEMBER_TYPE_OF(allocator_type); 42 MEMBER_TYPE_OF(const_iterator); 43 MEMBER_TYPE_OF(const_reference); 44 MEMBER_TYPE_OF(const_reverse_iterator); 45 MEMBER_TYPE_OF(container_type); 46 MEMBER_TYPE_OF(data_type); 47 MEMBER_TYPE_OF(iterator); 48 MEMBER_TYPE_OF(key_compare); 49 MEMBER_TYPE_OF(key_type); 50 MEMBER_TYPE_OF(reference); 51 MEMBER_TYPE_OF(reverse_iterator); 52 MEMBER_TYPE_OF(size_type); 53 MEMBER_TYPE_OF(value_compare); 54 MEMBER_TYPE_OF(value_type); 55 56 #undef MEMBER_TYPE_OF 57 58 /////////////////////////////////////////////////////////////////////////////// 59 // 60 // Const-Qualified types. 61 // 62 // Many of the stl member functions have const and non-const 63 // overloaded versions that return distinct types. For example: 64 // 65 // iterator begin(); 66 // const_iterator begin() const; 67 // 68 // The three class templates defined below, 69 // const_qualified_reference_of, const_qualified_iterator_of 70 // and const_qualified_reverse_iterator_of provide a means to extract 71 // this return type automatically. 72 // 73 /////////////////////////////////////////////////////////////////////////////// 74 template <typename C> 75 struct const_qualified_reference_of 76 { 77 typedef typename 78 boost::mpl::eval_if_c< 79 boost::is_const<C>::value 80 , const_reference_of<C> 81 , reference_of<C> 82 >::type 83 type; 84 }; 85 86 template <typename C> 87 struct const_qualified_iterator_of 88 { 89 typedef typename 90 boost::mpl::eval_if_c< 91 boost::is_const<C>::value 92 , const_iterator_of<C> 93 , iterator_of<C> 94 >::type 95 type; 96 }; 97 98 template <typename C> 99 struct const_qualified_reverse_iterator_of 100 { 101 typedef typename 102 boost::mpl::eval_if_c< 103 boost::is_const<C>::value 104 , const_reverse_iterator_of<C> 105 , reverse_iterator_of<C> 106 >::type 107 type; 108 }; 109 110 /////////////////////////////////////////////////////////////////////////////// 111 // 112 // has_mapped_type<C> 113 // 114 // Given a container C, determine if it is a map, multimap, unordered_map, 115 // or unordered_multimap by checking if it has a member type named "mapped_type". 116 // 117 /////////////////////////////////////////////////////////////////////////////// 118 namespace stl_impl 119 { 120 struct one { char a[1]; }; 121 struct two { char a[2]; }; 122 123 template <typename C> 124 one has_mapped_type(typename C::mapped_type(*)()); 125 126 template <typename C> 127 two has_mapped_type(...); 128 } 129 130 template <typename C> 131 struct has_mapped_type 132 : boost::mpl::bool_< 133 sizeof(stl_impl::has_mapped_type<C>(0)) == sizeof(stl_impl::one) 134 > 135 {}; 136 137 /////////////////////////////////////////////////////////////////////////////// 138 // 139 // has_key_type<C> 140 // 141 // Given a container C, determine if it is a Associative Container 142 // by checking if it has a member type named "key_type". 143 // 144 /////////////////////////////////////////////////////////////////////////////// 145 namespace stl_impl 146 { 147 template <typename C> 148 one has_key_type(typename C::key_type(*)()); 149 150 template <typename C> 151 two has_key_type(...); 152 } 153 154 template <typename C> 155 struct has_key_type 156 : boost::mpl::bool_< 157 sizeof(stl_impl::has_key_type<C>(0)) == sizeof(stl_impl::one) 158 > 159 {}; 160 161 /////////////////////////////////////////////////////////////////////////////// 162 // 163 // is_key_type_of<C, Arg> 164 // 165 // Lazy evaluation friendly predicate. 166 // 167 /////////////////////////////////////////////////////////////////////////////// 168 169 template <typename C, typename Arg> 170 struct is_key_type_of 171 : boost::is_convertible<Arg, typename key_type_of<C>::type> 172 {}; 173 174 /////////////////////////////////////////////////////////////////////////////// 175 // 176 // map_insert_returns_pair<C> 177 // 178 // Distinguish a map from a multimap by checking the return type 179 // of its "insert" member function. A map returns a pair while 180 // a multimap returns an iterator. 181 // 182 /////////////////////////////////////////////////////////////////////////////// 183 namespace stl_impl 184 { 185 // Cool implementation of map_insert_returns_pair by Daniel Wallin. 186 // Thanks Daniel!!! I owe you a Pizza! 187 188 template<class A, class B> 189 one map_insert_returns_pair_check(std::pair<A,B> const&); 190 191 template <typename T> 192 two map_insert_returns_pair_check(T const&); 193 194 template <typename C> 195 struct map_insert_returns_pair 196 { 197 static typename C::value_type const& get; 198 BOOST_STATIC_CONSTANT(int, 199 value = sizeof( 200 map_insert_returns_pair_check(((C*)0)->insert(get)))); 201 typedef boost::mpl::bool_<value == sizeof(one)> type; 202 }; 203 } 204 205 template <typename C> 206 struct map_insert_returns_pair 207 : stl_impl::map_insert_returns_pair<C>::type {}; 208 209 }}} // namespace boost::phoenix::stl 210 211 #endif // BOOST_PHOENIX_STL_CONTAINER_TRAITS_HPP 212