ob_compressed_pair.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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. // see libs/utility/compressed_pair.hpp
  8. //
  9. /* Release notes:
  10. 20 Jan 2001:
  11. Fixed obvious bugs (David Abrahams)
  12. 07 Oct 2000:
  13. Added better single argument constructor support.
  14. 03 Oct 2000:
  15. Added VC6 support (JM).
  16. 23rd July 2000:
  17. Additional comments added. (JM)
  18. Jan 2000:
  19. Original version: this version crippled for use with crippled compilers
  20. - John Maddock Jan 2000.
  21. */
  22. #ifndef BOOST_OB_COMPRESSED_PAIR_HPP
  23. #define BOOST_OB_COMPRESSED_PAIR_HPP
  24. #include <algorithm>
  25. #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
  26. #include <boost/type_traits/object_traits.hpp>
  27. #endif
  28. #ifndef BOOST_SAME_TRAITS_HPP
  29. #include <boost/type_traits/same_traits.hpp>
  30. #endif
  31. #ifndef BOOST_CALL_TRAITS_HPP
  32. #include <boost/call_traits.hpp>
  33. #endif
  34. namespace boost
  35. {
  36. #ifdef BOOST_MSVC6_MEMBER_TEMPLATES
  37. //
  38. // use member templates to emulate
  39. // partial specialisation. Note that due to
  40. // problems with overload resolution with VC6
  41. // each of the compressed_pair versions that follow
  42. // have one template single-argument constructor
  43. // in place of two specific constructors:
  44. //
  45. template <class T1, class T2>
  46. class compressed_pair;
  47. namespace detail{
  48. template <class A, class T1, class T2>
  49. struct best_conversion_traits
  50. {
  51. typedef char one;
  52. typedef char (&two)[2];
  53. static A a;
  54. static one test(T1);
  55. static two test(T2);
  56. enum { value = sizeof(test(a)) };
  57. };
  58. template <int>
  59. struct init_one;
  60. template <>
  61. struct init_one<1>
  62. {
  63. template <class A, class T1, class T2>
  64. static void init(const A& a, T1* p1, T2*)
  65. {
  66. *p1 = a;
  67. }
  68. };
  69. template <>
  70. struct init_one<2>
  71. {
  72. template <class A, class T1, class T2>
  73. static void init(const A& a, T1*, T2* p2)
  74. {
  75. *p2 = a;
  76. }
  77. };
  78. // T1 != T2, both non-empty
  79. template <class T1, class T2>
  80. class compressed_pair_0
  81. {
  82. private:
  83. T1 _first;
  84. T2 _second;
  85. public:
  86. typedef T1 first_type;
  87. typedef T2 second_type;
  88. typedef typename call_traits<first_type>::param_type first_param_type;
  89. typedef typename call_traits<second_type>::param_type second_param_type;
  90. typedef typename call_traits<first_type>::reference first_reference;
  91. typedef typename call_traits<second_type>::reference second_reference;
  92. typedef typename call_traits<first_type>::const_reference first_const_reference;
  93. typedef typename call_traits<second_type>::const_reference second_const_reference;
  94. compressed_pair_0() : _first(), _second() {}
  95. compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
  96. template <class A>
  97. explicit compressed_pair_0(const A& val)
  98. {
  99. init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
  100. }
  101. compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
  102. : _first(x.first()), _second(x.second()) {}
  103. #if 0
  104. compressed_pair_0& operator=(const compressed_pair_0& x) {
  105. cout << "assigning compressed pair 0" << endl;
  106. _first = x._first;
  107. _second = x._second;
  108. cout << "finished assigning compressed pair 0" << endl;
  109. return *this;
  110. }
  111. #endif
  112. first_reference first() { return _first; }
  113. first_const_reference first() const { return _first; }
  114. second_reference second() { return _second; }
  115. second_const_reference second() const { return _second; }
  116. void swap(compressed_pair_0& y)
  117. {
  118. using std::swap;
  119. swap(_first, y._first);
  120. swap(_second, y._second);
  121. }
  122. };
  123. // T1 != T2, T2 empty
  124. template <class T1, class T2>
  125. class compressed_pair_1 : T2
  126. {
  127. private:
  128. T1 _first;
  129. public:
  130. typedef T1 first_type;
  131. typedef T2 second_type;
  132. typedef typename call_traits<first_type>::param_type first_param_type;
  133. typedef typename call_traits<second_type>::param_type second_param_type;
  134. typedef typename call_traits<first_type>::reference first_reference;
  135. typedef typename call_traits<second_type>::reference second_reference;
  136. typedef typename call_traits<first_type>::const_reference first_const_reference;
  137. typedef typename call_traits<second_type>::const_reference second_const_reference;
  138. compressed_pair_1() : T2(), _first() {}
  139. compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
  140. template <class A>
  141. explicit compressed_pair_1(const A& val)
  142. {
  143. init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
  144. }
  145. compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
  146. : T2(x.second()), _first(x.first()) {}
  147. #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
  148. // Total weirdness. If the assignment to _first is moved after
  149. // the call to the inherited operator=, then this breaks graph/test/graph.cpp
  150. // by way of iterator_adaptor.
  151. compressed_pair_1& operator=(const compressed_pair_1& x) {
  152. _first = x._first;
  153. T2::operator=(x);
  154. return *this;
  155. }
  156. #endif
  157. first_reference first() { return _first; }
  158. first_const_reference first() const { return _first; }
  159. second_reference second() { return *this; }
  160. second_const_reference second() const { return *this; }
  161. void swap(compressed_pair_1& y)
  162. {
  163. // no need to swap empty base class:
  164. using std::swap;
  165. swap(_first, y._first);
  166. }
  167. };
  168. // T1 != T2, T1 empty
  169. template <class T1, class T2>
  170. class compressed_pair_2 : T1
  171. {
  172. private:
  173. T2 _second;
  174. public:
  175. typedef T1 first_type;
  176. typedef T2 second_type;
  177. typedef typename call_traits<first_type>::param_type first_param_type;
  178. typedef typename call_traits<second_type>::param_type second_param_type;
  179. typedef typename call_traits<first_type>::reference first_reference;
  180. typedef typename call_traits<second_type>::reference second_reference;
  181. typedef typename call_traits<first_type>::const_reference first_const_reference;
  182. typedef typename call_traits<second_type>::const_reference second_const_reference;
  183. compressed_pair_2() : T1(), _second() {}
  184. compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
  185. template <class A>
  186. explicit compressed_pair_2(const A& val)
  187. {
  188. init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
  189. }
  190. compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
  191. : T1(x.first()), _second(x.second()) {}
  192. #if 0
  193. compressed_pair_2& operator=(const compressed_pair_2& x) {
  194. cout << "assigning compressed pair 2" << endl;
  195. T1::operator=(x);
  196. _second = x._second;
  197. cout << "finished assigning compressed pair 2" << endl;
  198. return *this;
  199. }
  200. #endif
  201. first_reference first() { return *this; }
  202. first_const_reference first() const { return *this; }
  203. second_reference second() { return _second; }
  204. second_const_reference second() const { return _second; }
  205. void swap(compressed_pair_2& y)
  206. {
  207. // no need to swap empty base class:
  208. using std::swap;
  209. swap(_second, y._second);
  210. }
  211. };
  212. // T1 != T2, both empty
  213. template <class T1, class T2>
  214. class compressed_pair_3 : T1, T2
  215. {
  216. public:
  217. typedef T1 first_type;
  218. typedef T2 second_type;
  219. typedef typename call_traits<first_type>::param_type first_param_type;
  220. typedef typename call_traits<second_type>::param_type second_param_type;
  221. typedef typename call_traits<first_type>::reference first_reference;
  222. typedef typename call_traits<second_type>::reference second_reference;
  223. typedef typename call_traits<first_type>::const_reference first_const_reference;
  224. typedef typename call_traits<second_type>::const_reference second_const_reference;
  225. compressed_pair_3() : T1(), T2() {}
  226. compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
  227. template <class A>
  228. explicit compressed_pair_3(const A& val)
  229. {
  230. init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
  231. }
  232. compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
  233. : T1(x.first()), T2(x.second()) {}
  234. first_reference first() { return *this; }
  235. first_const_reference first() const { return *this; }
  236. second_reference second() { return *this; }
  237. second_const_reference second() const { return *this; }
  238. void swap(compressed_pair_3& y)
  239. {
  240. // no need to swap empty base classes:
  241. }
  242. };
  243. // T1 == T2, and empty
  244. template <class T1, class T2>
  245. class compressed_pair_4 : T1
  246. {
  247. public:
  248. typedef T1 first_type;
  249. typedef T2 second_type;
  250. typedef typename call_traits<first_type>::param_type first_param_type;
  251. typedef typename call_traits<second_type>::param_type second_param_type;
  252. typedef typename call_traits<first_type>::reference first_reference;
  253. typedef typename call_traits<second_type>::reference second_reference;
  254. typedef typename call_traits<first_type>::const_reference first_const_reference;
  255. typedef typename call_traits<second_type>::const_reference second_const_reference;
  256. compressed_pair_4() : T1() {}
  257. compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
  258. // only one single argument constructor since T1 == T2
  259. explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
  260. compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
  261. : T1(x.first()), m_second(x.second()) {}
  262. first_reference first() { return *this; }
  263. first_const_reference first() const { return *this; }
  264. second_reference second() { return m_second; }
  265. second_const_reference second() const { return m_second; }
  266. void swap(compressed_pair_4& y)
  267. {
  268. // no need to swap empty base classes:
  269. }
  270. private:
  271. T2 m_second;
  272. };
  273. // T1 == T2, not empty
  274. template <class T1, class T2>
  275. class compressed_pair_5
  276. {
  277. private:
  278. T1 _first;
  279. T2 _second;
  280. public:
  281. typedef T1 first_type;
  282. typedef T2 second_type;
  283. typedef typename call_traits<first_type>::param_type first_param_type;
  284. typedef typename call_traits<second_type>::param_type second_param_type;
  285. typedef typename call_traits<first_type>::reference first_reference;
  286. typedef typename call_traits<second_type>::reference second_reference;
  287. typedef typename call_traits<first_type>::const_reference first_const_reference;
  288. typedef typename call_traits<second_type>::const_reference second_const_reference;
  289. compressed_pair_5() : _first(), _second() {}
  290. compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
  291. // only one single argument constructor since T1 == T2
  292. explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
  293. compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
  294. : _first(c.first()), _second(c.second()) {}
  295. first_reference first() { return _first; }
  296. first_const_reference first() const { return _first; }
  297. second_reference second() { return _second; }
  298. second_const_reference second() const { return _second; }
  299. void swap(compressed_pair_5& y)
  300. {
  301. using std::swap;
  302. swap(_first, y._first);
  303. swap(_second, y._second);
  304. }
  305. };
  306. template <bool e1, bool e2, bool same>
  307. struct compressed_pair_chooser
  308. {
  309. template <class T1, class T2>
  310. struct rebind
  311. {
  312. typedef compressed_pair_0<T1, T2> type;
  313. };
  314. };
  315. template <>
  316. struct compressed_pair_chooser<false, true, false>
  317. {
  318. template <class T1, class T2>
  319. struct rebind
  320. {
  321. typedef compressed_pair_1<T1, T2> type;
  322. };
  323. };
  324. template <>
  325. struct compressed_pair_chooser<true, false, false>
  326. {
  327. template <class T1, class T2>
  328. struct rebind
  329. {
  330. typedef compressed_pair_2<T1, T2> type;
  331. };
  332. };
  333. template <>
  334. struct compressed_pair_chooser<true, true, false>
  335. {
  336. template <class T1, class T2>
  337. struct rebind
  338. {
  339. typedef compressed_pair_3<T1, T2> type;
  340. };
  341. };
  342. template <>
  343. struct compressed_pair_chooser<true, true, true>
  344. {
  345. template <class T1, class T2>
  346. struct rebind
  347. {
  348. typedef compressed_pair_4<T1, T2> type;
  349. };
  350. };
  351. template <>
  352. struct compressed_pair_chooser<false, false, true>
  353. {
  354. template <class T1, class T2>
  355. struct rebind
  356. {
  357. typedef compressed_pair_5<T1, T2> type;
  358. };
  359. };
  360. template <class T1, class T2>
  361. struct compressed_pair_traits
  362. {
  363. private:
  364. typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
  365. typedef typename chooser::template rebind<T1, T2> bound_type;
  366. public:
  367. typedef typename bound_type::type type;
  368. };
  369. } // namespace detail
  370. template <class T1, class T2>
  371. class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
  372. {
  373. private:
  374. typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
  375. public:
  376. typedef T1 first_type;
  377. typedef T2 second_type;
  378. typedef typename call_traits<first_type>::param_type first_param_type;
  379. typedef typename call_traits<second_type>::param_type second_param_type;
  380. typedef typename call_traits<first_type>::reference first_reference;
  381. typedef typename call_traits<second_type>::reference second_reference;
  382. typedef typename call_traits<first_type>::const_reference first_const_reference;
  383. typedef typename call_traits<second_type>::const_reference second_const_reference;
  384. compressed_pair() : base_type() {}
  385. compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
  386. template <class A>
  387. explicit compressed_pair(const A& x) : base_type(x){}
  388. first_reference first() { return base_type::first(); }
  389. first_const_reference first() const { return base_type::first(); }
  390. second_reference second() { return base_type::second(); }
  391. second_const_reference second() const { return base_type::second(); }
  392. };
  393. template <class T1, class T2>
  394. inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
  395. {
  396. x.swap(y);
  397. }
  398. #else
  399. // no partial specialisation, no member templates:
  400. template <class T1, class T2>
  401. class compressed_pair
  402. {
  403. private:
  404. T1 _first;
  405. T2 _second;
  406. public:
  407. typedef T1 first_type;
  408. typedef T2 second_type;
  409. typedef typename call_traits<first_type>::param_type first_param_type;
  410. typedef typename call_traits<second_type>::param_type second_param_type;
  411. typedef typename call_traits<first_type>::reference first_reference;
  412. typedef typename call_traits<second_type>::reference second_reference;
  413. typedef typename call_traits<first_type>::const_reference first_const_reference;
  414. typedef typename call_traits<second_type>::const_reference second_const_reference;
  415. compressed_pair() : _first(), _second() {}
  416. compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
  417. explicit compressed_pair(first_param_type x) : _first(x), _second() {}
  418. // can't define this in case T1 == T2:
  419. // explicit compressed_pair(second_param_type y) : _first(), _second(y) {}
  420. first_reference first() { return _first; }
  421. first_const_reference first() const { return _first; }
  422. second_reference second() { return _second; }
  423. second_const_reference second() const { return _second; }
  424. void swap(compressed_pair& y)
  425. {
  426. using std::swap;
  427. swap(_first, y._first);
  428. swap(_second, y._second);
  429. }
  430. };
  431. template <class T1, class T2>
  432. inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
  433. {
  434. x.swap(y);
  435. }
  436. #endif
  437. } // boost
  438. #endif // BOOST_OB_COMPRESSED_PAIR_HPP