1 // (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
\r
2 // Use, modification and distribution are subject to the Boost Software License,
\r
3 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
\r
4 // http://www.boost.org/LICENSE_1_0.txt).
\r
6 // See http://www.boost.org/libs/utility for most recent version including documentation.
\r
7 // see libs/utility/compressed_pair.hpp
\r
11 Fixed obvious bugs (David Abrahams)
\r
13 Added better single argument constructor support.
\r
15 Added VC6 support (JM).
\r
17 Additional comments added. (JM)
\r
19 Original version: this version crippled for use with crippled compilers
\r
20 - John Maddock Jan 2000.
\r
24 #ifndef BOOST_OB_COMPRESSED_PAIR_HPP
\r
25 #define BOOST_OB_COMPRESSED_PAIR_HPP
\r
27 #include <algorithm>
\r
28 #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
\r
29 #include <boost/type_traits/object_traits.hpp>
\r
31 #ifndef BOOST_SAME_TRAITS_HPP
\r
32 #include <boost/type_traits/same_traits.hpp>
\r
34 #ifndef BOOST_CALL_TRAITS_HPP
\r
35 #include <boost/call_traits.hpp>
\r
40 #ifdef BOOST_MSVC6_MEMBER_TEMPLATES
\r
42 // use member templates to emulate
\r
43 // partial specialisation. Note that due to
\r
44 // problems with overload resolution with VC6
\r
45 // each of the compressed_pair versions that follow
\r
46 // have one template single-argument constructor
\r
47 // in place of two specific constructors:
\r
50 template <class T1, class T2>
\r
51 class compressed_pair;
\r
55 template <class A, class T1, class T2>
\r
56 struct best_conversion_traits
\r
59 typedef char (&two)[2];
\r
61 static one test(T1);
\r
62 static two test(T2);
\r
64 enum { value = sizeof(test(a)) };
\r
73 template <class A, class T1, class T2>
\r
74 static void init(const A& a, T1* p1, T2*)
\r
83 template <class A, class T1, class T2>
\r
84 static void init(const A& a, T1*, T2* p2)
\r
91 // T1 != T2, both non-empty
\r
92 template <class T1, class T2>
\r
93 class compressed_pair_0
\r
99 typedef T1 first_type;
\r
100 typedef T2 second_type;
\r
101 typedef typename call_traits<first_type>::param_type first_param_type;
\r
102 typedef typename call_traits<second_type>::param_type second_param_type;
\r
103 typedef typename call_traits<first_type>::reference first_reference;
\r
104 typedef typename call_traits<second_type>::reference second_reference;
\r
105 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
106 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
108 compressed_pair_0() : _first(), _second() {}
\r
109 compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
\r
111 explicit compressed_pair_0(const A& val)
\r
113 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
\r
115 compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
\r
116 : _first(x.first()), _second(x.second()) {}
\r
119 compressed_pair_0& operator=(const compressed_pair_0& x) {
\r
120 cout << "assigning compressed pair 0" << endl;
\r
122 _second = x._second;
\r
123 cout << "finished assigning compressed pair 0" << endl;
\r
128 first_reference first() { return _first; }
\r
129 first_const_reference first() const { return _first; }
\r
131 second_reference second() { return _second; }
\r
132 second_const_reference second() const { return _second; }
\r
134 void swap(compressed_pair_0& y)
\r
137 swap(_first, y._first);
\r
138 swap(_second, y._second);
\r
142 // T1 != T2, T2 empty
\r
143 template <class T1, class T2>
\r
144 class compressed_pair_1 : T2
\r
149 typedef T1 first_type;
\r
150 typedef T2 second_type;
\r
151 typedef typename call_traits<first_type>::param_type first_param_type;
\r
152 typedef typename call_traits<second_type>::param_type second_param_type;
\r
153 typedef typename call_traits<first_type>::reference first_reference;
\r
154 typedef typename call_traits<second_type>::reference second_reference;
\r
155 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
156 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
158 compressed_pair_1() : T2(), _first() {}
\r
159 compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
\r
162 explicit compressed_pair_1(const A& val)
\r
164 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
\r
167 compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
\r
168 : T2(x.second()), _first(x.first()) {}
\r
170 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
\r
171 // Total weirdness. If the assignment to _first is moved after
\r
172 // the call to the inherited operator=, then this breaks graph/test/graph.cpp
\r
173 // by way of iterator_adaptor.
\r
174 compressed_pair_1& operator=(const compressed_pair_1& x) {
\r
181 first_reference first() { return _first; }
\r
182 first_const_reference first() const { return _first; }
\r
184 second_reference second() { return *this; }
\r
185 second_const_reference second() const { return *this; }
\r
187 void swap(compressed_pair_1& y)
\r
189 // no need to swap empty base class:
\r
191 swap(_first, y._first);
\r
195 // T1 != T2, T1 empty
\r
196 template <class T1, class T2>
\r
197 class compressed_pair_2 : T1
\r
202 typedef T1 first_type;
\r
203 typedef T2 second_type;
\r
204 typedef typename call_traits<first_type>::param_type first_param_type;
\r
205 typedef typename call_traits<second_type>::param_type second_param_type;
\r
206 typedef typename call_traits<first_type>::reference first_reference;
\r
207 typedef typename call_traits<second_type>::reference second_reference;
\r
208 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
209 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
211 compressed_pair_2() : T1(), _second() {}
\r
212 compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
\r
214 explicit compressed_pair_2(const A& val)
\r
216 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
\r
218 compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
\r
219 : T1(x.first()), _second(x.second()) {}
\r
222 compressed_pair_2& operator=(const compressed_pair_2& x) {
\r
223 cout << "assigning compressed pair 2" << endl;
\r
225 _second = x._second;
\r
226 cout << "finished assigning compressed pair 2" << endl;
\r
230 first_reference first() { return *this; }
\r
231 first_const_reference first() const { return *this; }
\r
233 second_reference second() { return _second; }
\r
234 second_const_reference second() const { return _second; }
\r
236 void swap(compressed_pair_2& y)
\r
238 // no need to swap empty base class:
\r
240 swap(_second, y._second);
\r
244 // T1 != T2, both empty
\r
245 template <class T1, class T2>
\r
246 class compressed_pair_3 : T1, T2
\r
249 typedef T1 first_type;
\r
250 typedef T2 second_type;
\r
251 typedef typename call_traits<first_type>::param_type first_param_type;
\r
252 typedef typename call_traits<second_type>::param_type second_param_type;
\r
253 typedef typename call_traits<first_type>::reference first_reference;
\r
254 typedef typename call_traits<second_type>::reference second_reference;
\r
255 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
256 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
258 compressed_pair_3() : T1(), T2() {}
\r
259 compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
\r
261 explicit compressed_pair_3(const A& val)
\r
263 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
\r
265 compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
\r
266 : T1(x.first()), T2(x.second()) {}
\r
268 first_reference first() { return *this; }
\r
269 first_const_reference first() const { return *this; }
\r
271 second_reference second() { return *this; }
\r
272 second_const_reference second() const { return *this; }
\r
274 void swap(compressed_pair_3& y)
\r
276 // no need to swap empty base classes:
\r
280 // T1 == T2, and empty
\r
281 template <class T1, class T2>
\r
282 class compressed_pair_4 : T1
\r
285 typedef T1 first_type;
\r
286 typedef T2 second_type;
\r
287 typedef typename call_traits<first_type>::param_type first_param_type;
\r
288 typedef typename call_traits<second_type>::param_type second_param_type;
\r
289 typedef typename call_traits<first_type>::reference first_reference;
\r
290 typedef typename call_traits<second_type>::reference second_reference;
\r
291 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
292 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
294 compressed_pair_4() : T1() {}
\r
295 compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
\r
296 // only one single argument constructor since T1 == T2
\r
297 explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
\r
298 compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
\r
299 : T1(x.first()), m_second(x.second()) {}
\r
301 first_reference first() { return *this; }
\r
302 first_const_reference first() const { return *this; }
\r
304 second_reference second() { return m_second; }
\r
305 second_const_reference second() const { return m_second; }
\r
307 void swap(compressed_pair_4& y)
\r
309 // no need to swap empty base classes:
\r
315 // T1 == T2, not empty
\r
316 template <class T1, class T2>
\r
317 class compressed_pair_5
\r
323 typedef T1 first_type;
\r
324 typedef T2 second_type;
\r
325 typedef typename call_traits<first_type>::param_type first_param_type;
\r
326 typedef typename call_traits<second_type>::param_type second_param_type;
\r
327 typedef typename call_traits<first_type>::reference first_reference;
\r
328 typedef typename call_traits<second_type>::reference second_reference;
\r
329 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
330 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
332 compressed_pair_5() : _first(), _second() {}
\r
333 compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
\r
334 // only one single argument constructor since T1 == T2
\r
335 explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
\r
336 compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
\r
337 : _first(c.first()), _second(c.second()) {}
\r
339 first_reference first() { return _first; }
\r
340 first_const_reference first() const { return _first; }
\r
342 second_reference second() { return _second; }
\r
343 second_const_reference second() const { return _second; }
\r
345 void swap(compressed_pair_5& y)
\r
348 swap(_first, y._first);
\r
349 swap(_second, y._second);
\r
353 template <bool e1, bool e2, bool same>
\r
354 struct compressed_pair_chooser
\r
356 template <class T1, class T2>
\r
359 typedef compressed_pair_0<T1, T2> type;
\r
364 struct compressed_pair_chooser<false, true, false>
\r
366 template <class T1, class T2>
\r
369 typedef compressed_pair_1<T1, T2> type;
\r
374 struct compressed_pair_chooser<true, false, false>
\r
376 template <class T1, class T2>
\r
379 typedef compressed_pair_2<T1, T2> type;
\r
384 struct compressed_pair_chooser<true, true, false>
\r
386 template <class T1, class T2>
\r
389 typedef compressed_pair_3<T1, T2> type;
\r
394 struct compressed_pair_chooser<true, true, true>
\r
396 template <class T1, class T2>
\r
399 typedef compressed_pair_4<T1, T2> type;
\r
404 struct compressed_pair_chooser<false, false, true>
\r
406 template <class T1, class T2>
\r
409 typedef compressed_pair_5<T1, T2> type;
\r
413 template <class T1, class T2>
\r
414 struct compressed_pair_traits
\r
417 typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
\r
418 typedef typename chooser::template rebind<T1, T2> bound_type;
\r
420 typedef typename bound_type::type type;
\r
423 } // namespace detail
\r
425 template <class T1, class T2>
\r
426 class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
\r
429 typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
\r
431 typedef T1 first_type;
\r
432 typedef T2 second_type;
\r
433 typedef typename call_traits<first_type>::param_type first_param_type;
\r
434 typedef typename call_traits<second_type>::param_type second_param_type;
\r
435 typedef typename call_traits<first_type>::reference first_reference;
\r
436 typedef typename call_traits<second_type>::reference second_reference;
\r
437 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
438 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
440 compressed_pair() : base_type() {}
\r
441 compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
\r
443 explicit compressed_pair(const A& x) : base_type(x){}
\r
445 first_reference first() { return base_type::first(); }
\r
446 first_const_reference first() const { return base_type::first(); }
\r
448 second_reference second() { return base_type::second(); }
\r
449 second_const_reference second() const { return base_type::second(); }
\r
452 template <class T1, class T2>
\r
453 inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
\r
459 // no partial specialisation, no member templates:
\r
461 template <class T1, class T2>
\r
462 class compressed_pair
\r
468 typedef T1 first_type;
\r
469 typedef T2 second_type;
\r
470 typedef typename call_traits<first_type>::param_type first_param_type;
\r
471 typedef typename call_traits<second_type>::param_type second_param_type;
\r
472 typedef typename call_traits<first_type>::reference first_reference;
\r
473 typedef typename call_traits<second_type>::reference second_reference;
\r
474 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
475 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
477 compressed_pair() : _first(), _second() {}
\r
478 compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
\r
479 explicit compressed_pair(first_param_type x) : _first(x), _second() {}
\r
480 // can't define this in case T1 == T2:
\r
481 // explicit compressed_pair(second_param_type y) : _first(), _second(y) {}
\r
483 first_reference first() { return _first; }
\r
484 first_const_reference first() const { return _first; }
\r
486 second_reference second() { return _second; }
\r
487 second_const_reference second() const { return _second; }
\r
489 void swap(compressed_pair& y)
\r
492 swap(_first, y._first);
\r
493 swap(_second, y._second);
\r
497 template <class T1, class T2>
\r
498 inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
\r
507 #endif // BOOST_OB_COMPRESSED_PAIR_HPP
\r