container.hpp 6.8 KB

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