1 /*=============================================================================
2 Copyright (c) 2004 Angus Leeming
3 Copyright (c) 2004 Joel de Guzman
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
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>
17 namespace boost { namespace phoenix { namespace stl
19 ///////////////////////////////////////////////////////////////////////////////
21 // Metafunctions "value_type_of", "key_type_of" etc.
23 // These metafunctions define a typedef "type" that returns the nested
24 // type if it exists. If not then the typedef returns void.
26 // For example, "value_type_of<std::vector<int> >::type" is "int" whilst
27 // "value_type_of<double>::type" is "void".
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
33 /////////////////////////////////////////////////////////////////c//////////////
34 #define MEMBER_TYPE_OF(MEMBER_TYPE) \
35 template <typename C> \
36 struct BOOST_PP_CAT(MEMBER_TYPE, _of) \
38 typedef typename C::MEMBER_TYPE type; \
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);
58 ///////////////////////////////////////////////////////////////////////////////
60 // Const-Qualified types.
62 // Many of the stl member functions have const and non-const
63 // overloaded versions that return distinct types. For example:
66 // const_iterator begin() const;
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.
73 ///////////////////////////////////////////////////////////////////////////////
75 struct const_qualified_reference_of
78 boost::mpl::eval_if_c<
79 boost::is_const<C>::value
80 , const_reference_of<C>
87 struct const_qualified_iterator_of
90 boost::mpl::eval_if_c<
91 boost::is_const<C>::value
92 , const_iterator_of<C>
99 struct const_qualified_reverse_iterator_of
102 boost::mpl::eval_if_c<
103 boost::is_const<C>::value
104 , const_reverse_iterator_of<C>
105 , reverse_iterator_of<C>
110 ///////////////////////////////////////////////////////////////////////////////
112 // has_mapped_type<C>
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".
117 ///////////////////////////////////////////////////////////////////////////////
120 struct one { char a[1]; };
121 struct two { char a[2]; };
123 template <typename C>
124 one has_mapped_type(typename C::mapped_type(*)());
126 template <typename C>
127 two has_mapped_type(...);
130 template <typename C>
131 struct has_mapped_type
133 sizeof(stl_impl::has_mapped_type<C>(0)) == sizeof(stl_impl::one)
137 ///////////////////////////////////////////////////////////////////////////////
141 // Given a container C, determine if it is a Associative Container
142 // by checking if it has a member type named "key_type".
144 ///////////////////////////////////////////////////////////////////////////////
147 template <typename C>
148 one has_key_type(typename C::key_type(*)());
150 template <typename C>
151 two has_key_type(...);
154 template <typename C>
157 sizeof(stl_impl::has_key_type<C>(0)) == sizeof(stl_impl::one)
161 ///////////////////////////////////////////////////////////////////////////////
163 // is_key_type_of<C, Arg>
165 // Lazy evaluation friendly predicate.
167 ///////////////////////////////////////////////////////////////////////////////
169 template <typename C, typename Arg>
170 struct is_key_type_of
171 : boost::is_convertible<Arg, typename key_type_of<C>::type>
174 ///////////////////////////////////////////////////////////////////////////////
176 // map_insert_returns_pair<C>
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.
182 ///////////////////////////////////////////////////////////////////////////////
185 // Cool implementation of map_insert_returns_pair by Daniel Wallin.
186 // Thanks Daniel!!! I owe you a Pizza!
188 template<class A, class B>
189 one map_insert_returns_pair_check(std::pair<A,B> const&);
191 template <typename T>
192 two map_insert_returns_pair_check(T const&);
194 template <typename C>
195 struct map_insert_returns_pair
197 static typename C::value_type const& get;
198 BOOST_STATIC_CONSTANT(int,
200 map_insert_returns_pair_check(((C*)0)->insert(get))));
201 typedef boost::mpl::bool_<value == sizeof(one)> type;
205 template <typename C>
206 struct map_insert_returns_pair
207 : stl_impl::map_insert_returns_pair<C>::type {};
209 }}} // namespace boost::phoenix::stl
211 #endif // BOOST_PHOENIX_STL_CONTAINER_TRAITS_HPP