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