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