compressed_pair.hpp 17 KB

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