pair.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2012.
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/container for documentation.
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
  13. #define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
  14. #if defined(_MSC_VER)
  15. # pragma once
  16. #endif
  17. #include "config_begin.hpp"
  18. #include <boost/container/detail/workaround.hpp>
  19. #include <boost/container/detail/mpl.hpp>
  20. #include <boost/container/detail/type_traits.hpp>
  21. #include <boost/container/detail/mpl.hpp>
  22. #include <boost/container/detail/type_traits.hpp>
  23. #include <utility> //std::pair
  24. #include <algorithm> //std::swap
  25. #include <boost/move/utility.hpp>
  26. #include <boost/type_traits/is_class.hpp>
  27. #ifndef BOOST_CONTAINER_PERFECT_FORWARDING
  28. #include <boost/container/detail/preprocessor.hpp>
  29. #endif
  30. namespace boost {
  31. namespace container {
  32. namespace container_detail {
  33. template <class T1, class T2>
  34. struct pair;
  35. template <class T>
  36. struct is_pair
  37. {
  38. static const bool value = false;
  39. };
  40. template <class T1, class T2>
  41. struct is_pair< pair<T1, T2> >
  42. {
  43. static const bool value = true;
  44. };
  45. template <class T1, class T2>
  46. struct is_pair< std::pair<T1, T2> >
  47. {
  48. static const bool value = true;
  49. };
  50. struct pair_nat;
  51. struct piecewise_construct_t { };
  52. static const piecewise_construct_t piecewise_construct = piecewise_construct_t();
  53. /*
  54. template <class T1, class T2>
  55. struct pair
  56. {
  57. template <class U, class V> pair(pair<U, V>&& p);
  58. template <class... Args1, class... Args2>
  59. pair(piecewise_construct_t, tuple<Args1...> first_args,
  60. tuple<Args2...> second_args);
  61. template <class U, class V> pair& operator=(const pair<U, V>& p);
  62. pair& operator=(pair&& p) noexcept(is_nothrow_move_assignable<T1>::value &&
  63. is_nothrow_move_assignable<T2>::value);
  64. template <class U, class V> pair& operator=(pair<U, V>&& p);
  65. void swap(pair& p) noexcept(noexcept(swap(first, p.first)) &&
  66. noexcept(swap(second, p.second)));
  67. };
  68. template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&);
  69. template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&);
  70. template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&);
  71. template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&);
  72. template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&);
  73. template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&);
  74. */
  75. template <class T1, class T2>
  76. struct pair
  77. {
  78. private:
  79. BOOST_COPYABLE_AND_MOVABLE(pair)
  80. public:
  81. typedef T1 first_type;
  82. typedef T2 second_type;
  83. T1 first;
  84. T2 second;
  85. //Default constructor
  86. pair()
  87. : first(), second()
  88. {}
  89. //pair copy assignment
  90. pair(const pair& x)
  91. : first(x.first), second(x.second)
  92. {}
  93. //pair move constructor
  94. pair(BOOST_RV_REF(pair) p)
  95. : first(::boost::move(p.first)), second(::boost::move(p.second))
  96. {}
  97. template <class D, class S>
  98. pair(const pair<D, S> &p)
  99. : first(p.first), second(p.second)
  100. {}
  101. template <class D, class S>
  102. pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
  103. : first(::boost::move(p.first)), second(::boost::move(p.second))
  104. {}
  105. //pair from two values
  106. pair(const T1 &t1, const T2 &t2)
  107. : first(t1)
  108. , second(t2)
  109. {}
  110. template<class U, class V>
  111. pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
  112. : first(::boost::forward<U>(u))
  113. , second(::boost::forward<V>(v))
  114. {}
  115. //And now compatibility with std::pair
  116. pair(const std::pair<T1, T2>& x)
  117. : first(x.first), second(x.second)
  118. {}
  119. template <class D, class S>
  120. pair(const std::pair<D, S>& p)
  121. : first(p.first), second(p.second)
  122. {}
  123. pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
  124. : first(::boost::move(p.first)), second(::boost::move(p.second))
  125. {}
  126. template <class D, class S>
  127. pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
  128. : first(::boost::move(p.first)), second(::boost::move(p.second))
  129. {}
  130. //piecewise_construct missing
  131. //template <class U, class V> pair(pair<U, V>&& p);
  132. //template <class... Args1, class... Args2>
  133. // pair(piecewise_construct_t, tuple<Args1...> first_args,
  134. // tuple<Args2...> second_args);
  135. /*
  136. //Variadic versions
  137. template<class U>
  138. pair(BOOST_CONTAINER_PP_PARAM(U, u), typename container_detail::disable_if
  139. < container_detail::is_pair< typename container_detail::remove_ref_const<U>::type >, pair_nat>::type* = 0)
  140. : first(::boost::forward<U>(u))
  141. , second()
  142. {}
  143. #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
  144. template<class U, class V, class ...Args>
  145. pair(U &&u, V &&v)
  146. : first(::boost::forward<U>(u))
  147. , second(::boost::forward<V>(v), ::boost::forward<Args>(args)...)
  148. {}
  149. #else
  150. #define BOOST_PP_LOCAL_MACRO(n) \
  151. template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \
  152. pair(BOOST_CONTAINER_PP_PARAM(U, u) \
  153. ,BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  154. : first(::boost::forward<U>(u)) \
  155. , second(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \
  156. {} \
  157. //!
  158. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  159. #include BOOST_PP_LOCAL_ITERATE()
  160. #endif
  161. */
  162. //pair copy assignment
  163. pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p)
  164. {
  165. first = p.first;
  166. second = p.second;
  167. return *this;
  168. }
  169. //pair move assignment
  170. pair& operator=(BOOST_RV_REF(pair) p)
  171. {
  172. first = ::boost::move(p.first);
  173. second = ::boost::move(p.second);
  174. return *this;
  175. }
  176. template <class D, class S>
  177. typename ::boost::container::container_detail::enable_if_c
  178. < !(::boost::container::container_detail::is_same<T1, D>::value &&
  179. ::boost::container::container_detail::is_same<T2, S>::value)
  180. , pair &>::type
  181. operator=(const pair<D, S>&p)
  182. {
  183. first = p.first;
  184. second = p.second;
  185. return *this;
  186. }
  187. template <class D, class S>
  188. typename ::boost::container::container_detail::enable_if_c
  189. < !(::boost::container::container_detail::is_same<T1, D>::value &&
  190. ::boost::container::container_detail::is_same<T2, S>::value)
  191. , pair &>::type
  192. operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
  193. {
  194. first = ::boost::move(p.first);
  195. second = ::boost::move(p.second);
  196. return *this;
  197. }
  198. //std::pair copy assignment
  199. pair& operator=(const std::pair<T1, T2> &p)
  200. {
  201. first = p.first;
  202. second = p.second;
  203. return *this;
  204. }
  205. template <class D, class S>
  206. pair& operator=(const std::pair<D, S> &p)
  207. {
  208. first = ::boost::move(p.first);
  209. second = ::boost::move(p.second);
  210. return *this;
  211. }
  212. //std::pair move assignment
  213. pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
  214. {
  215. first = ::boost::move(p.first);
  216. second = ::boost::move(p.second);
  217. return *this;
  218. }
  219. template <class D, class S>
  220. pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
  221. {
  222. first = ::boost::move(p.first);
  223. second = ::boost::move(p.second);
  224. return *this;
  225. }
  226. //swap
  227. void swap(pair& p)
  228. {
  229. using std::swap;
  230. swap(this->first, p.first);
  231. swap(this->second, p.second);
  232. }
  233. };
  234. template <class T1, class T2>
  235. inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
  236. { return static_cast<bool>(x.first == y.first && x.second == y.second); }
  237. template <class T1, class T2>
  238. inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
  239. { return static_cast<bool>(x.first < y.first ||
  240. (!(y.first < x.first) && x.second < y.second)); }
  241. template <class T1, class T2>
  242. inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
  243. { return static_cast<bool>(!(x == y)); }
  244. template <class T1, class T2>
  245. inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
  246. { return y < x; }
  247. template <class T1, class T2>
  248. inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
  249. { return static_cast<bool>(!(x < y)); }
  250. template <class T1, class T2>
  251. inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
  252. { return static_cast<bool>(!(y < x)); }
  253. template <class T1, class T2>
  254. inline pair<T1, T2> make_pair(T1 x, T2 y)
  255. { return pair<T1, T2>(x, y); }
  256. template <class T1, class T2>
  257. inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
  258. {
  259. swap(x.first, y.first);
  260. swap(x.second, y.second);
  261. }
  262. } //namespace container_detail {
  263. } //namespace container {
  264. //Without this specialization recursive flat_(multi)map instantiation fails
  265. //because is_enum needs to instantiate the recursive pair, leading to a compilation error).
  266. //This breaks the cycle clearly stating that pair is not an enum avoiding any instantiation.
  267. template<class T>
  268. struct is_enum;
  269. template<class T, class U>
  270. struct is_enum< ::boost::container::container_detail::pair<T, U> >
  271. {
  272. static const bool value = false;
  273. };
  274. //This specialization is needed to avoid instantiation of pair in
  275. //is_class, and allow recursive maps.
  276. template <class T1, class T2>
  277. struct is_class< ::boost::container::container_detail::pair<T1, T2> >
  278. : public ::boost::true_type
  279. {};
  280. #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
  281. template<class T1, class T2>
  282. struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> >
  283. : ::boost::true_type
  284. {};
  285. #endif
  286. } //namespace boost {
  287. #include <boost/container/detail/config_end.hpp>
  288. #endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP