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.
8 // compressed_pair: pair that "compresses" empty members
9 // (see libs/utility/compressed_pair.htm)
11 // JM changes 25 Jan 2004:
12 // For the case where T1 == T2 and both are empty, then first() and second()
13 // should return different objects.
14 // JM changes 25 Jan 2000:
15 // Removed default arguments from compressed_pair_switch to get
16 // C++ Builder 4 to accept them
17 // rewriten swap to get gcc and C++ builder to compile.
18 // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
20 #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
21 #define BOOST_DETAIL_COMPRESSED_PAIR_HPP
25 #include <boost/type_traits/remove_cv.hpp>
26 #include <boost/type_traits/is_empty.hpp>
27 #include <boost/type_traits/is_same.hpp>
28 #include <boost/call_traits.hpp>
33 template <class T1, class T2>
34 class compressed_pair;
41 // JM altered 26 Jan 2000:
42 template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
43 struct compressed_pair_switch;
45 template <class T1, class T2>
46 struct compressed_pair_switch<T1, T2, false, false, false>
47 {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;};
53 template <class T1, class T2>
54 struct compressed_pair_switch<T1, T2, false, true, false>
55 {static const int value = 1;};
57 template <class T1, class T2>
58 struct compressed_pair_switch<T1, T2, false, false, true>
59 {static const int value = 2;};
61 template <class T1, class T2>
62 struct compressed_pair_switch<T1, T2, true, true, true>
63 {static const int value = 4;};
65 template <class T1, class T2>
66 struct compressed_pair_switch<T1, T2, true, false, false>
67 {static const int value = 5;};
69 template <class T1, class T2, int Version> class compressed_pair_imp;
72 // workaround for GCC (JM):
76 // can't call unqualified swap from within classname::swap
77 // as Koenig lookup rules will find only the classname::swap
78 // member function not the global declaration, so use cp_swap
79 // as a forwarding function (JM):
81 inline void cp_swap(T& t1, T& t2)
89 // 0 derive from neither
91 template <class T1, class T2>
92 class compressed_pair_imp<T1, T2, 0>
95 typedef T1 first_type;
96 typedef T2 second_type;
97 typedef typename call_traits<first_type>::param_type first_param_type;
98 typedef typename call_traits<second_type>::param_type second_param_type;
99 typedef typename call_traits<first_type>::reference first_reference;
100 typedef typename call_traits<second_type>::reference second_reference;
101 typedef typename call_traits<first_type>::const_reference first_const_reference;
102 typedef typename call_traits<second_type>::const_reference second_const_reference;
104 compressed_pair_imp() {}
106 compressed_pair_imp(first_param_type x, second_param_type y)
107 : first_(x), second_(y) {}
109 compressed_pair_imp(first_param_type x)
112 compressed_pair_imp(second_param_type y)
115 first_reference first() {return first_;}
116 first_const_reference first() const {return first_;}
118 second_reference second() {return second_;}
119 second_const_reference second() const {return second_;}
121 void swap(::boost::compressed_pair<T1, T2>& y)
123 cp_swap(first_, y.first());
124 cp_swap(second_, y.second());
133 template <class T1, class T2>
134 class compressed_pair_imp<T1, T2, 1>
138 typedef T1 first_type;
139 typedef T2 second_type;
140 typedef typename call_traits<first_type>::param_type first_param_type;
141 typedef typename call_traits<second_type>::param_type second_param_type;
142 typedef typename call_traits<first_type>::reference first_reference;
143 typedef typename call_traits<second_type>::reference second_reference;
144 typedef typename call_traits<first_type>::const_reference first_const_reference;
145 typedef typename call_traits<second_type>::const_reference second_const_reference;
147 compressed_pair_imp() {}
149 compressed_pair_imp(first_param_type x, second_param_type y)
150 : first_type(x), second_(y) {}
152 compressed_pair_imp(first_param_type x)
155 compressed_pair_imp(second_param_type y)
158 first_reference first() {return *this;}
159 first_const_reference first() const {return *this;}
161 second_reference second() {return second_;}
162 second_const_reference second() const {return second_;}
164 void swap(::boost::compressed_pair<T1,T2>& y)
166 // no need to swap empty base class:
167 cp_swap(second_, y.second());
175 template <class T1, class T2>
176 class compressed_pair_imp<T1, T2, 2>
180 typedef T1 first_type;
181 typedef T2 second_type;
182 typedef typename call_traits<first_type>::param_type first_param_type;
183 typedef typename call_traits<second_type>::param_type second_param_type;
184 typedef typename call_traits<first_type>::reference first_reference;
185 typedef typename call_traits<second_type>::reference second_reference;
186 typedef typename call_traits<first_type>::const_reference first_const_reference;
187 typedef typename call_traits<second_type>::const_reference second_const_reference;
189 compressed_pair_imp() {}
191 compressed_pair_imp(first_param_type x, second_param_type y)
192 : second_type(y), first_(x) {}
194 compressed_pair_imp(first_param_type x)
197 compressed_pair_imp(second_param_type y)
200 first_reference first() {return first_;}
201 first_const_reference first() const {return first_;}
203 second_reference second() {return *this;}
204 second_const_reference second() const {return *this;}
206 void swap(::boost::compressed_pair<T1,T2>& y)
208 // no need to swap empty base class:
209 cp_swap(first_, y.first());
216 // 3 derive from T1 and T2
218 template <class T1, class T2>
219 class compressed_pair_imp<T1, T2, 3>
224 typedef T1 first_type;
225 typedef T2 second_type;
226 typedef typename call_traits<first_type>::param_type first_param_type;
227 typedef typename call_traits<second_type>::param_type second_param_type;
228 typedef typename call_traits<first_type>::reference first_reference;
229 typedef typename call_traits<second_type>::reference second_reference;
230 typedef typename call_traits<first_type>::const_reference first_const_reference;
231 typedef typename call_traits<second_type>::const_reference second_const_reference;
233 compressed_pair_imp() {}
235 compressed_pair_imp(first_param_type x, second_param_type y)
236 : first_type(x), second_type(y) {}
238 compressed_pair_imp(first_param_type x)
241 compressed_pair_imp(second_param_type y)
244 first_reference first() {return *this;}
245 first_const_reference first() const {return *this;}
247 second_reference second() {return *this;}
248 second_const_reference second() const {return *this;}
250 // no need to swap empty bases:
251 void swap(::boost::compressed_pair<T1,T2>&) {}
255 // 4 T1 == T2, T1 and T2 both empty
256 // Note does not actually store an instance of T2 at all -
257 // but reuses T1 base class for both first() and second().
258 template <class T1, class T2>
259 class compressed_pair_imp<T1, T2, 4>
263 typedef T1 first_type;
264 typedef T2 second_type;
265 typedef typename call_traits<first_type>::param_type first_param_type;
266 typedef typename call_traits<second_type>::param_type second_param_type;
267 typedef typename call_traits<first_type>::reference first_reference;
268 typedef typename call_traits<second_type>::reference second_reference;
269 typedef typename call_traits<first_type>::const_reference first_const_reference;
270 typedef typename call_traits<second_type>::const_reference second_const_reference;
272 compressed_pair_imp() {}
274 compressed_pair_imp(first_param_type x, second_param_type y)
275 : first_type(x), m_second(y) {}
277 compressed_pair_imp(first_param_type x)
278 : first_type(x), m_second(x) {}
280 first_reference first() {return *this;}
281 first_const_reference first() const {return *this;}
283 second_reference second() {return m_second;}
284 second_const_reference second() const {return m_second;}
286 void swap(::boost::compressed_pair<T1,T2>&) {}
291 // 5 T1 == T2 and are not empty: //JM
293 template <class T1, class T2>
294 class compressed_pair_imp<T1, T2, 5>
297 typedef T1 first_type;
298 typedef T2 second_type;
299 typedef typename call_traits<first_type>::param_type first_param_type;
300 typedef typename call_traits<second_type>::param_type second_param_type;
301 typedef typename call_traits<first_type>::reference first_reference;
302 typedef typename call_traits<second_type>::reference second_reference;
303 typedef typename call_traits<first_type>::const_reference first_const_reference;
304 typedef typename call_traits<second_type>::const_reference second_const_reference;
306 compressed_pair_imp() {}
308 compressed_pair_imp(first_param_type x, second_param_type y)
309 : first_(x), second_(y) {}
311 compressed_pair_imp(first_param_type x)
312 : first_(x), second_(x) {}
314 first_reference first() {return first_;}
315 first_const_reference first() const {return first_;}
317 second_reference second() {return second_;}
318 second_const_reference second() const {return second_;}
320 void swap(::boost::compressed_pair<T1, T2>& y)
322 cp_swap(first_, y.first());
323 cp_swap(second_, y.second());
332 template <class T1, class T2>
333 class compressed_pair
334 : private ::boost::details::compressed_pair_imp<T1, T2,
335 ::boost::details::compressed_pair_switch<
338 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
339 ::boost::is_empty<T1>::value,
340 ::boost::is_empty<T2>::value>::value>
343 typedef details::compressed_pair_imp<T1, T2,
344 ::boost::details::compressed_pair_switch<
347 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
348 ::boost::is_empty<T1>::value,
349 ::boost::is_empty<T2>::value>::value> base;
351 typedef T1 first_type;
352 typedef T2 second_type;
353 typedef typename call_traits<first_type>::param_type first_param_type;
354 typedef typename call_traits<second_type>::param_type second_param_type;
355 typedef typename call_traits<first_type>::reference first_reference;
356 typedef typename call_traits<second_type>::reference second_reference;
357 typedef typename call_traits<first_type>::const_reference first_const_reference;
358 typedef typename call_traits<second_type>::const_reference second_const_reference;
360 compressed_pair() : base() {}
361 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
362 explicit compressed_pair(first_param_type x) : base(x) {}
363 explicit compressed_pair(second_param_type y) : base(y) {}
365 first_reference first() {return base::first();}
366 first_const_reference first() const {return base::first();}
368 second_reference second() {return base::second();}
369 second_const_reference second() const {return base::second();}
371 void swap(compressed_pair& y) { base::swap(y); }
375 // Partial specialisation for case where T1 == T2:
378 class compressed_pair<T, T>
379 : private details::compressed_pair_imp<T, T,
380 ::boost::details::compressed_pair_switch<
383 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
384 ::boost::is_empty<T>::value,
385 ::boost::is_empty<T>::value>::value>
388 typedef details::compressed_pair_imp<T, T,
389 ::boost::details::compressed_pair_switch<
392 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
393 ::boost::is_empty<T>::value,
394 ::boost::is_empty<T>::value>::value> base;
396 typedef T first_type;
397 typedef T second_type;
398 typedef typename call_traits<first_type>::param_type first_param_type;
399 typedef typename call_traits<second_type>::param_type second_param_type;
400 typedef typename call_traits<first_type>::reference first_reference;
401 typedef typename call_traits<second_type>::reference second_reference;
402 typedef typename call_traits<first_type>::const_reference first_const_reference;
403 typedef typename call_traits<second_type>::const_reference second_const_reference;
405 compressed_pair() : base() {}
406 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
407 #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
410 compressed_pair(first_param_type x) : base(x) {}
412 first_reference first() {return base::first();}
413 first_const_reference first() const {return base::first();}
415 second_reference second() {return base::second();}
416 second_const_reference second() const {return base::second();}
418 void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
421 template <class T1, class T2>
424 swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
431 #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP