1 // (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
2 // Permission to copy, use, modify, sell and
3 // distribute this software is granted provided this copyright notice appears
4 // in all copies. This software is provided "as is" without express or implied
5 // warranty, and with no claim as to its suitability for any purpose.
7 // See http://www.boost.org for most recent version including documentation.
9 // compressed_pair: pair that "compresses" empty members
10 // (see libs/utility/compressed_pair.htm)
12 // JM changes 25 Jan 2000:
13 // Removed default arguments from compressed_pair_switch to get
14 // C++ Builder 4 to accept them
15 // rewriten swap to get gcc and C++ builder to compile.
16 // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
18 #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
19 #define BOOST_DETAIL_COMPRESSED_PAIR_HPP
22 #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
23 #include <boost/type_traits/object_traits.hpp>
25 #ifndef BOOST_SAME_TRAITS_HPP
26 #include <boost/type_traits/same_traits.hpp>
28 #ifndef BOOST_CALL_TRAITS_HPP
29 #include <boost/call_traits.hpp>
35 template <class T1, class T2>
36 class compressed_pair;
43 // JM altered 26 Jan 2000:
44 template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
45 struct compressed_pair_switch;
47 template <class T1, class T2>
48 struct compressed_pair_switch<T1, T2, false, false, false>
49 {static const int value = 0;};
51 template <class T1, class T2>
52 struct compressed_pair_switch<T1, T2, false, true, true>
53 {static const int value = 3;};
55 template <class T1, class T2>
56 struct compressed_pair_switch<T1, T2, false, true, false>
57 {static const int value = 1;};
59 template <class T1, class T2>
60 struct compressed_pair_switch<T1, T2, false, false, true>
61 {static const int value = 2;};
63 template <class T1, class T2>
64 struct compressed_pair_switch<T1, T2, true, true, true>
65 {static const int value = 4;};
67 template <class T1, class T2>
68 struct compressed_pair_switch<T1, T2, true, false, false>
69 {static const int value = 5;};
71 template <class T1, class T2, int Version> class compressed_pair_imp;
74 // workaround for GCC (JM):
78 // can't call unqualified swap from within classname::swap
79 // as Koenig lookup rules will find only the classname::swap
80 // member function not the global declaration, so use cp_swap
81 // as a forwarding function (JM):
83 inline void cp_swap(T& t1, T& t2)
91 // 0 derive from neither
93 template <class T1, class T2>
94 class compressed_pair_imp<T1, T2, 0>
97 typedef T1 first_type;
98 typedef T2 second_type;
99 typedef typename call_traits<first_type>::param_type first_param_type;
100 typedef typename call_traits<second_type>::param_type second_param_type;
101 typedef typename call_traits<first_type>::reference first_reference;
102 typedef typename call_traits<second_type>::reference second_reference;
103 typedef typename call_traits<first_type>::const_reference first_const_reference;
104 typedef typename call_traits<second_type>::const_reference second_const_reference;
106 compressed_pair_imp() {}
108 compressed_pair_imp(first_param_type x, second_param_type y)
109 : first_(x), second_(y) {}
111 compressed_pair_imp(first_param_type x)
114 compressed_pair_imp(second_param_type y)
117 first_reference first() {return first_;}
118 first_const_reference first() const {return first_;}
120 second_reference second() {return second_;}
121 second_const_reference second() const {return second_;}
123 void swap(::boost::compressed_pair<T1, T2>& y)
125 cp_swap(first_, y.first());
126 cp_swap(second_, y.second());
135 template <class T1, class T2>
136 class compressed_pair_imp<T1, T2, 1>
140 typedef T1 first_type;
141 typedef T2 second_type;
142 typedef typename call_traits<first_type>::param_type first_param_type;
143 typedef typename call_traits<second_type>::param_type second_param_type;
144 typedef typename call_traits<first_type>::reference first_reference;
145 typedef typename call_traits<second_type>::reference second_reference;
146 typedef typename call_traits<first_type>::const_reference first_const_reference;
147 typedef typename call_traits<second_type>::const_reference second_const_reference;
149 compressed_pair_imp() {}
151 compressed_pair_imp(first_param_type x, second_param_type y)
152 : first_type(x), second_(y) {}
154 compressed_pair_imp(first_param_type x)
157 compressed_pair_imp(second_param_type y)
160 first_reference first() {return *this;}
161 first_const_reference first() const {return *this;}
163 second_reference second() {return second_;}
164 second_const_reference second() const {return second_;}
166 void swap(::boost::compressed_pair<T1,T2>& y)
168 // no need to swap empty base class:
169 cp_swap(second_, y.second());
177 template <class T1, class T2>
178 class compressed_pair_imp<T1, T2, 2>
182 typedef T1 first_type;
183 typedef T2 second_type;
184 typedef typename call_traits<first_type>::param_type first_param_type;
185 typedef typename call_traits<second_type>::param_type second_param_type;
186 typedef typename call_traits<first_type>::reference first_reference;
187 typedef typename call_traits<second_type>::reference second_reference;
188 typedef typename call_traits<first_type>::const_reference first_const_reference;
189 typedef typename call_traits<second_type>::const_reference second_const_reference;
191 compressed_pair_imp() {}
193 compressed_pair_imp(first_param_type x, second_param_type y)
194 : second_type(y), first_(x) {}
196 compressed_pair_imp(first_param_type x)
199 compressed_pair_imp(second_param_type y)
202 first_reference first() {return first_;}
203 first_const_reference first() const {return first_;}
205 second_reference second() {return *this;}
206 second_const_reference second() const {return *this;}
208 void swap(::boost::compressed_pair<T1,T2>& y)
210 // no need to swap empty base class:
211 cp_swap(first_, y.first());
218 // 3 derive from T1 and T2
220 template <class T1, class T2>
221 class compressed_pair_imp<T1, T2, 3>
226 typedef T1 first_type;
227 typedef T2 second_type;
228 typedef typename call_traits<first_type>::param_type first_param_type;
229 typedef typename call_traits<second_type>::param_type second_param_type;
230 typedef typename call_traits<first_type>::reference first_reference;
231 typedef typename call_traits<second_type>::reference second_reference;
232 typedef typename call_traits<first_type>::const_reference first_const_reference;
233 typedef typename call_traits<second_type>::const_reference second_const_reference;
235 compressed_pair_imp() {}
237 compressed_pair_imp(first_param_type x, second_param_type y)
238 : first_type(x), second_type(y) {}
240 compressed_pair_imp(first_param_type x)
243 compressed_pair_imp(second_param_type y)
246 first_reference first() {return *this;}
247 first_const_reference first() const {return *this;}
249 second_reference second() {return *this;}
250 second_const_reference second() const {return *this;}
252 // no need to swap empty bases:
253 void swap(::boost::compressed_pair<T1,T2>&) {}
257 // 4 T1 == T2, T1 and T2 both empty
258 // Note does not actually store an instance of T2 at all -
259 // but reuses T1 base class for both first() and second().
260 template <class T1, class T2>
261 class compressed_pair_imp<T1, T2, 4>
265 typedef T1 first_type;
266 typedef T2 second_type;
267 typedef typename call_traits<first_type>::param_type first_param_type;
268 typedef typename call_traits<second_type>::param_type second_param_type;
269 typedef typename call_traits<first_type>::reference first_reference;
270 typedef typename call_traits<second_type>::reference second_reference;
271 typedef typename call_traits<first_type>::const_reference first_const_reference;
272 typedef typename call_traits<second_type>::const_reference second_const_reference;
274 compressed_pair_imp() {}
276 compressed_pair_imp(first_param_type x, second_param_type)
279 compressed_pair_imp(first_param_type x)
282 first_reference first() {return *this;}
283 first_const_reference first() const {return *this;}
285 second_reference second() {return *this;}
286 second_const_reference second() const {return *this;}
288 void swap(::boost::compressed_pair<T1,T2>&) {}
292 // 5 T1 == T2 and are not empty: //JM
294 template <class T1, class T2>
295 class compressed_pair_imp<T1, T2, 5>
298 typedef T1 first_type;
299 typedef T2 second_type;
300 typedef typename call_traits<first_type>::param_type first_param_type;
301 typedef typename call_traits<second_type>::param_type second_param_type;
302 typedef typename call_traits<first_type>::reference first_reference;
303 typedef typename call_traits<second_type>::reference second_reference;
304 typedef typename call_traits<first_type>::const_reference first_const_reference;
305 typedef typename call_traits<second_type>::const_reference second_const_reference;
307 compressed_pair_imp() {}
309 compressed_pair_imp(first_param_type x, second_param_type y)
310 : first_(x), second_(y) {}
312 compressed_pair_imp(first_param_type x)
313 : first_(x), second_(x) {}
315 first_reference first() {return first_;}
316 first_const_reference first() const {return first_;}
318 second_reference second() {return second_;}
319 second_const_reference second() const {return second_;}
321 void swap(::boost::compressed_pair<T1, T2>& y)
323 cp_swap(first_, y.first());
324 cp_swap(second_, y.second());
333 template <class T1, class T2>
334 class compressed_pair
335 : private ::boost::details::compressed_pair_imp<T1, T2,
336 ::boost::details::compressed_pair_switch<
339 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
340 ::boost::is_empty<T1>::value,
341 ::boost::is_empty<T2>::value>::value>
344 typedef details::compressed_pair_imp<T1, T2,
345 ::boost::details::compressed_pair_switch<
348 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
349 ::boost::is_empty<T1>::value,
350 ::boost::is_empty<T2>::value>::value> base;
352 typedef T1 first_type;
353 typedef T2 second_type;
354 typedef typename call_traits<first_type>::param_type first_param_type;
355 typedef typename call_traits<second_type>::param_type second_param_type;
356 typedef typename call_traits<first_type>::reference first_reference;
357 typedef typename call_traits<second_type>::reference second_reference;
358 typedef typename call_traits<first_type>::const_reference first_const_reference;
359 typedef typename call_traits<second_type>::const_reference second_const_reference;
361 compressed_pair() : base() {}
362 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
363 explicit compressed_pair(first_param_type x) : base(x) {}
364 explicit compressed_pair(second_param_type y) : base(y) {}
366 first_reference first() {return base::first();}
367 first_const_reference first() const {return base::first();}
369 second_reference second() {return base::second();}
370 second_const_reference second() const {return base::second();}
372 void swap(compressed_pair& y) { base::swap(y); }
376 // Partial specialisation for case where T1 == T2:
379 class compressed_pair<T, T>
380 : private details::compressed_pair_imp<T, T,
381 ::boost::details::compressed_pair_switch<
384 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
385 ::boost::is_empty<T>::value,
386 ::boost::is_empty<T>::value>::value>
389 typedef details::compressed_pair_imp<T, T,
390 ::boost::details::compressed_pair_switch<
393 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
394 ::boost::is_empty<T>::value,
395 ::boost::is_empty<T>::value>::value> base;
397 typedef T first_type;
398 typedef T second_type;
399 typedef typename call_traits<first_type>::param_type first_param_type;
400 typedef typename call_traits<second_type>::param_type second_param_type;
401 typedef typename call_traits<first_type>::reference first_reference;
402 typedef typename call_traits<second_type>::reference second_reference;
403 typedef typename call_traits<first_type>::const_reference first_const_reference;
404 typedef typename call_traits<second_type>::const_reference second_const_reference;
406 compressed_pair() : base() {}
407 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
408 #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
411 compressed_pair(first_param_type x) : base(x) {}
413 first_reference first() {return base::first();}
414 first_const_reference first() const {return base::first();}
416 second_reference second() {return base::second();}
417 second_const_reference second() const {return base::second();}
419 void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
422 template <class T1, class T2>
425 swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
432 #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP