compressed_pair.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
  2. // Use, modification and distribution are subject to the Boost Software License,
  3. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt).
  5. //
  6. // See http://www.boost.org/libs/utility for most recent version including documentation.
  7. // compressed_pair: pair that "compresses" empty members
  8. // (see libs/utility/doc/html/compressed_pair.html)
  9. //
  10. // JM changes 25 Jan 2004:
  11. // For the case where T1 == T2 and both are empty, then first() and second()
  12. // should return different objects.
  13. // JM changes 25 Jan 2000:
  14. // Removed default arguments from compressed_pair_switch to get
  15. // C++ Builder 4 to accept them
  16. // rewriten swap to get gcc and C++ builder to compile.
  17. // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
  18. #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
  19. #define BOOST_DETAIL_COMPRESSED_PAIR_HPP
  20. #include <algorithm>
  21. #include <boost/type_traits/remove_cv.hpp>
  22. #include <boost/type_traits/is_empty.hpp>
  23. #include <boost/type_traits/is_same.hpp>
  24. #include <boost/call_traits.hpp>
  25. #ifdef BOOST_MSVC
  26. # pragma warning(push)
  27. # pragma warning(disable:4512)
  28. #endif
  29. namespace boost
  30. {
  31. template <class T1, class T2>
  32. class compressed_pair;
  33. // compressed_pair
  34. namespace details
  35. {
  36. // JM altered 26 Jan 2000:
  37. template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
  38. struct compressed_pair_switch;
  39. template <class T1, class T2>
  40. struct compressed_pair_switch<T1, T2, false, false, false>
  41. {static const int value = 0;};
  42. template <class T1, class T2>
  43. struct compressed_pair_switch<T1, T2, false, true, true>
  44. {static const int value = 3;};
  45. template <class T1, class T2>
  46. struct compressed_pair_switch<T1, T2, false, true, false>
  47. {static const int value = 1;};
  48. template <class T1, class T2>
  49. struct compressed_pair_switch<T1, T2, false, false, true>
  50. {static const int value = 2;};
  51. template <class T1, class T2>
  52. struct compressed_pair_switch<T1, T2, true, true, true>
  53. {static const int value = 4;};
  54. template <class T1, class T2>
  55. struct compressed_pair_switch<T1, T2, true, false, false>
  56. {static const int value = 5;};
  57. template <class T1, class T2, int Version> class compressed_pair_imp;
  58. #ifdef __GNUC__
  59. // workaround for GCC (JM):
  60. using std::swap;
  61. #endif
  62. //
  63. // can't call unqualified swap from within classname::swap
  64. // as Koenig lookup rules will find only the classname::swap
  65. // member function not the global declaration, so use cp_swap
  66. // as a forwarding function (JM):
  67. template <typename T>
  68. inline void cp_swap(T& t1, T& t2)
  69. {
  70. #ifndef __GNUC__
  71. using std::swap;
  72. #endif
  73. swap(t1, t2);
  74. }
  75. // 0 derive from neither
  76. template <class T1, class T2>
  77. class compressed_pair_imp<T1, T2, 0>
  78. {
  79. public:
  80. typedef T1 first_type;
  81. typedef T2 second_type;
  82. typedef typename call_traits<first_type>::param_type first_param_type;
  83. typedef typename call_traits<second_type>::param_type second_param_type;
  84. typedef typename call_traits<first_type>::reference first_reference;
  85. typedef typename call_traits<second_type>::reference second_reference;
  86. typedef typename call_traits<first_type>::const_reference first_const_reference;
  87. typedef typename call_traits<second_type>::const_reference second_const_reference;
  88. compressed_pair_imp() {}
  89. compressed_pair_imp(first_param_type x, second_param_type y)
  90. : first_(x), second_(y) {}
  91. compressed_pair_imp(first_param_type x)
  92. : first_(x) {}
  93. compressed_pair_imp(second_param_type y)
  94. : second_(y) {}
  95. first_reference first() {return first_;}
  96. first_const_reference first() const {return first_;}
  97. second_reference second() {return second_;}
  98. second_const_reference second() const {return second_;}
  99. void swap(::boost::compressed_pair<T1, T2>& y)
  100. {
  101. cp_swap(first_, y.first());
  102. cp_swap(second_, y.second());
  103. }
  104. private:
  105. first_type first_;
  106. second_type second_;
  107. };
  108. // 1 derive from T1
  109. template <class T1, class T2>
  110. class compressed_pair_imp<T1, T2, 1>
  111. : protected ::boost::remove_cv<T1>::type
  112. {
  113. public:
  114. typedef T1 first_type;
  115. typedef T2 second_type;
  116. typedef typename call_traits<first_type>::param_type first_param_type;
  117. typedef typename call_traits<second_type>::param_type second_param_type;
  118. typedef typename call_traits<first_type>::reference first_reference;
  119. typedef typename call_traits<second_type>::reference second_reference;
  120. typedef typename call_traits<first_type>::const_reference first_const_reference;
  121. typedef typename call_traits<second_type>::const_reference second_const_reference;
  122. compressed_pair_imp() {}
  123. compressed_pair_imp(first_param_type x, second_param_type y)
  124. : first_type(x), second_(y) {}
  125. compressed_pair_imp(first_param_type x)
  126. : first_type(x) {}
  127. compressed_pair_imp(second_param_type y)
  128. : second_(y) {}
  129. first_reference first() {return *this;}
  130. first_const_reference first() const {return *this;}
  131. second_reference second() {return second_;}
  132. second_const_reference second() const {return second_;}
  133. void swap(::boost::compressed_pair<T1,T2>& y)
  134. {
  135. // no need to swap empty base class:
  136. cp_swap(second_, y.second());
  137. }
  138. private:
  139. second_type second_;
  140. };
  141. // 2 derive from T2
  142. template <class T1, class T2>
  143. class compressed_pair_imp<T1, T2, 2>
  144. : protected ::boost::remove_cv<T2>::type
  145. {
  146. public:
  147. typedef T1 first_type;
  148. typedef T2 second_type;
  149. typedef typename call_traits<first_type>::param_type first_param_type;
  150. typedef typename call_traits<second_type>::param_type second_param_type;
  151. typedef typename call_traits<first_type>::reference first_reference;
  152. typedef typename call_traits<second_type>::reference second_reference;
  153. typedef typename call_traits<first_type>::const_reference first_const_reference;
  154. typedef typename call_traits<second_type>::const_reference second_const_reference;
  155. compressed_pair_imp() {}
  156. compressed_pair_imp(first_param_type x, second_param_type y)
  157. : second_type(y), first_(x) {}
  158. compressed_pair_imp(first_param_type x)
  159. : first_(x) {}
  160. compressed_pair_imp(second_param_type y)
  161. : second_type(y) {}
  162. first_reference first() {return first_;}
  163. first_const_reference first() const {return first_;}
  164. second_reference second() {return *this;}
  165. second_const_reference second() const {return *this;}
  166. void swap(::boost::compressed_pair<T1,T2>& y)
  167. {
  168. // no need to swap empty base class:
  169. cp_swap(first_, y.first());
  170. }
  171. private:
  172. first_type first_;
  173. };
  174. // 3 derive from T1 and T2
  175. template <class T1, class T2>
  176. class compressed_pair_imp<T1, T2, 3>
  177. : protected ::boost::remove_cv<T1>::type,
  178. protected ::boost::remove_cv<T2>::type
  179. {
  180. public:
  181. typedef T1 first_type;
  182. typedef T2 second_type;
  183. typedef typename call_traits<first_type>::param_type first_param_type;
  184. typedef typename call_traits<second_type>::param_type second_param_type;
  185. typedef typename call_traits<first_type>::reference first_reference;
  186. typedef typename call_traits<second_type>::reference second_reference;
  187. typedef typename call_traits<first_type>::const_reference first_const_reference;
  188. typedef typename call_traits<second_type>::const_reference second_const_reference;
  189. compressed_pair_imp() {}
  190. compressed_pair_imp(first_param_type x, second_param_type y)
  191. : first_type(x), second_type(y) {}
  192. compressed_pair_imp(first_param_type x)
  193. : first_type(x) {}
  194. compressed_pair_imp(second_param_type y)
  195. : second_type(y) {}
  196. first_reference first() {return *this;}
  197. first_const_reference first() const {return *this;}
  198. second_reference second() {return *this;}
  199. second_const_reference second() const {return *this;}
  200. //
  201. // no need to swap empty bases:
  202. void swap(::boost::compressed_pair<T1,T2>&) {}
  203. };
  204. // JM
  205. // 4 T1 == T2, T1 and T2 both empty
  206. // Originally this did not store an instance of T2 at all
  207. // but that led to problems beause it meant &x.first() == &x.second()
  208. // which is not true for any other kind of pair, so now we store an instance
  209. // of T2 just in case the user is relying on first() and second() returning
  210. // different objects (albeit both empty).
  211. template <class T1, class T2>
  212. class compressed_pair_imp<T1, T2, 4>
  213. : protected ::boost::remove_cv<T1>::type
  214. {
  215. public:
  216. typedef T1 first_type;
  217. typedef T2 second_type;
  218. typedef typename call_traits<first_type>::param_type first_param_type;
  219. typedef typename call_traits<second_type>::param_type second_param_type;
  220. typedef typename call_traits<first_type>::reference first_reference;
  221. typedef typename call_traits<second_type>::reference second_reference;
  222. typedef typename call_traits<first_type>::const_reference first_const_reference;
  223. typedef typename call_traits<second_type>::const_reference second_const_reference;
  224. compressed_pair_imp() {}
  225. compressed_pair_imp(first_param_type x, second_param_type y)
  226. : first_type(x), m_second(y) {}
  227. compressed_pair_imp(first_param_type x)
  228. : first_type(x), m_second(x) {}
  229. first_reference first() {return *this;}
  230. first_const_reference first() const {return *this;}
  231. second_reference second() {return m_second;}
  232. second_const_reference second() const {return m_second;}
  233. void swap(::boost::compressed_pair<T1,T2>&) {}
  234. private:
  235. T2 m_second;
  236. };
  237. // 5 T1 == T2 and are not empty: //JM
  238. template <class T1, class T2>
  239. class compressed_pair_imp<T1, T2, 5>
  240. {
  241. public:
  242. typedef T1 first_type;
  243. typedef T2 second_type;
  244. typedef typename call_traits<first_type>::param_type first_param_type;
  245. typedef typename call_traits<second_type>::param_type second_param_type;
  246. typedef typename call_traits<first_type>::reference first_reference;
  247. typedef typename call_traits<second_type>::reference second_reference;
  248. typedef typename call_traits<first_type>::const_reference first_const_reference;
  249. typedef typename call_traits<second_type>::const_reference second_const_reference;
  250. compressed_pair_imp() {}
  251. compressed_pair_imp(first_param_type x, second_param_type y)
  252. : first_(x), second_(y) {}
  253. compressed_pair_imp(first_param_type x)
  254. : first_(x), second_(x) {}
  255. first_reference first() {return first_;}
  256. first_const_reference first() const {return first_;}
  257. second_reference second() {return second_;}
  258. second_const_reference second() const {return second_;}
  259. void swap(::boost::compressed_pair<T1, T2>& y)
  260. {
  261. cp_swap(first_, y.first());
  262. cp_swap(second_, y.second());
  263. }
  264. private:
  265. first_type first_;
  266. second_type second_;
  267. };
  268. } // details
  269. template <class T1, class T2>
  270. class compressed_pair
  271. : private ::boost::details::compressed_pair_imp<T1, T2,
  272. ::boost::details::compressed_pair_switch<
  273. T1,
  274. T2,
  275. ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
  276. ::boost::is_empty<T1>::value,
  277. ::boost::is_empty<T2>::value>::value>
  278. {
  279. private:
  280. typedef details::compressed_pair_imp<T1, T2,
  281. ::boost::details::compressed_pair_switch<
  282. T1,
  283. T2,
  284. ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
  285. ::boost::is_empty<T1>::value,
  286. ::boost::is_empty<T2>::value>::value> base;
  287. public:
  288. typedef T1 first_type;
  289. typedef T2 second_type;
  290. typedef typename call_traits<first_type>::param_type first_param_type;
  291. typedef typename call_traits<second_type>::param_type second_param_type;
  292. typedef typename call_traits<first_type>::reference first_reference;
  293. typedef typename call_traits<second_type>::reference second_reference;
  294. typedef typename call_traits<first_type>::const_reference first_const_reference;
  295. typedef typename call_traits<second_type>::const_reference second_const_reference;
  296. compressed_pair() : base() {}
  297. compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
  298. explicit compressed_pair(first_param_type x) : base(x) {}
  299. explicit compressed_pair(second_param_type y) : base(y) {}
  300. first_reference first() {return base::first();}
  301. first_const_reference first() const {return base::first();}
  302. second_reference second() {return base::second();}
  303. second_const_reference second() const {return base::second();}
  304. void swap(compressed_pair& y) { base::swap(y); }
  305. };
  306. // JM
  307. // Partial specialisation for case where T1 == T2:
  308. //
  309. template <class T>
  310. class compressed_pair<T, T>
  311. : private details::compressed_pair_imp<T, T,
  312. ::boost::details::compressed_pair_switch<
  313. T,
  314. T,
  315. ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
  316. ::boost::is_empty<T>::value,
  317. ::boost::is_empty<T>::value>::value>
  318. {
  319. private:
  320. typedef details::compressed_pair_imp<T, T,
  321. ::boost::details::compressed_pair_switch<
  322. T,
  323. T,
  324. ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
  325. ::boost::is_empty<T>::value,
  326. ::boost::is_empty<T>::value>::value> base;
  327. public:
  328. typedef T first_type;
  329. typedef T second_type;
  330. typedef typename call_traits<first_type>::param_type first_param_type;
  331. typedef typename call_traits<second_type>::param_type second_param_type;
  332. typedef typename call_traits<first_type>::reference first_reference;
  333. typedef typename call_traits<second_type>::reference second_reference;
  334. typedef typename call_traits<first_type>::const_reference first_const_reference;
  335. typedef typename call_traits<second_type>::const_reference second_const_reference;
  336. compressed_pair() : base() {}
  337. compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
  338. #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
  339. explicit
  340. #endif
  341. compressed_pair(first_param_type x) : base(x) {}
  342. first_reference first() {return base::first();}
  343. first_const_reference first() const {return base::first();}
  344. second_reference second() {return base::second();}
  345. second_const_reference second() const {return base::second();}
  346. void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
  347. };
  348. template <class T1, class T2>
  349. inline
  350. void
  351. swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
  352. {
  353. x.swap(y);
  354. }
  355. } // boost
  356. #ifdef BOOST_MSVC
  357. # pragma warning(pop)
  358. #endif
  359. #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP