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>
31 # pragma warning(push)
32 # pragma warning(disable:4512)
37 template <class T1
, class T2
>
38 class compressed_pair
;
45 // JM altered 26 Jan 2000:
46 template <class T1
, class T2
, bool IsSame
, bool FirstEmpty
, bool SecondEmpty
>
47 struct compressed_pair_switch
;
49 template <class T1
, class T2
>
50 struct compressed_pair_switch
<T1
, T2
, false, false, false>
51 {static const int value
= 0;};
53 template <class T1
, class T2
>
54 struct compressed_pair_switch
<T1
, T2
, false, true, true>
55 {static const int value
= 3;};
57 template <class T1
, class T2
>
58 struct compressed_pair_switch
<T1
, T2
, false, true, false>
59 {static const int value
= 1;};
61 template <class T1
, class T2
>
62 struct compressed_pair_switch
<T1
, T2
, false, false, true>
63 {static const int value
= 2;};
65 template <class T1
, class T2
>
66 struct compressed_pair_switch
<T1
, T2
, true, true, true>
67 {static const int value
= 4;};
69 template <class T1
, class T2
>
70 struct compressed_pair_switch
<T1
, T2
, true, false, false>
71 {static const int value
= 5;};
73 template <class T1
, class T2
, int Version
> class compressed_pair_imp
;
76 // workaround for GCC (JM):
80 // can't call unqualified swap from within classname::swap
81 // as Koenig lookup rules will find only the classname::swap
82 // member function not the global declaration, so use cp_swap
83 // as a forwarding function (JM):
85 inline void cp_swap(T
& t1
, T
& t2
)
93 // 0 derive from neither
95 template <class T1
, class T2
>
96 class compressed_pair_imp
<T1
, T2
, 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_imp() {}
110 compressed_pair_imp(first_param_type x
, second_param_type y
)
111 : first_(x
), second_(y
) {}
113 compressed_pair_imp(first_param_type x
)
116 compressed_pair_imp(second_param_type y
)
119 first_reference
first() {return first_
;}
120 first_const_reference
first() const {return first_
;}
122 second_reference
second() {return second_
;}
123 second_const_reference
second() const {return second_
;}
125 void swap(::boost::compressed_pair
<T1
, T2
>& y
)
127 cp_swap(first_
, y
.first());
128 cp_swap(second_
, y
.second());
137 template <class T1
, class T2
>
138 class compressed_pair_imp
<T1
, T2
, 1>
139 : protected ::boost::remove_cv
<T1
>::type
142 typedef T1 first_type
;
143 typedef T2 second_type
;
144 typedef typename call_traits
<first_type
>::param_type first_param_type
;
145 typedef typename call_traits
<second_type
>::param_type second_param_type
;
146 typedef typename call_traits
<first_type
>::reference first_reference
;
147 typedef typename call_traits
<second_type
>::reference second_reference
;
148 typedef typename call_traits
<first_type
>::const_reference first_const_reference
;
149 typedef typename call_traits
<second_type
>::const_reference second_const_reference
;
151 compressed_pair_imp() {}
153 compressed_pair_imp(first_param_type x
, second_param_type y
)
154 : first_type(x
), second_(y
) {}
156 compressed_pair_imp(first_param_type x
)
159 compressed_pair_imp(second_param_type y
)
162 first_reference
first() {return *this;}
163 first_const_reference
first() const {return *this;}
165 second_reference
second() {return second_
;}
166 second_const_reference
second() const {return second_
;}
168 void swap(::boost::compressed_pair
<T1
,T2
>& y
)
170 // no need to swap empty base class:
171 cp_swap(second_
, y
.second());
179 template <class T1
, class T2
>
180 class compressed_pair_imp
<T1
, T2
, 2>
181 : protected ::boost::remove_cv
<T2
>::type
184 typedef T1 first_type
;
185 typedef T2 second_type
;
186 typedef typename call_traits
<first_type
>::param_type first_param_type
;
187 typedef typename call_traits
<second_type
>::param_type second_param_type
;
188 typedef typename call_traits
<first_type
>::reference first_reference
;
189 typedef typename call_traits
<second_type
>::reference second_reference
;
190 typedef typename call_traits
<first_type
>::const_reference first_const_reference
;
191 typedef typename call_traits
<second_type
>::const_reference second_const_reference
;
193 compressed_pair_imp() {}
195 compressed_pair_imp(first_param_type x
, second_param_type y
)
196 : second_type(y
), first_(x
) {}
198 compressed_pair_imp(first_param_type x
)
201 compressed_pair_imp(second_param_type y
)
204 first_reference
first() {return first_
;}
205 first_const_reference
first() const {return first_
;}
207 second_reference
second() {return *this;}
208 second_const_reference
second() const {return *this;}
210 void swap(::boost::compressed_pair
<T1
,T2
>& y
)
212 // no need to swap empty base class:
213 cp_swap(first_
, y
.first());
220 // 3 derive from T1 and T2
222 template <class T1
, class T2
>
223 class compressed_pair_imp
<T1
, T2
, 3>
224 : protected ::boost::remove_cv
<T1
>::type
,
225 protected ::boost::remove_cv
<T2
>::type
228 typedef T1 first_type
;
229 typedef T2 second_type
;
230 typedef typename call_traits
<first_type
>::param_type first_param_type
;
231 typedef typename call_traits
<second_type
>::param_type second_param_type
;
232 typedef typename call_traits
<first_type
>::reference first_reference
;
233 typedef typename call_traits
<second_type
>::reference second_reference
;
234 typedef typename call_traits
<first_type
>::const_reference first_const_reference
;
235 typedef typename call_traits
<second_type
>::const_reference second_const_reference
;
237 compressed_pair_imp() {}
239 compressed_pair_imp(first_param_type x
, second_param_type y
)
240 : first_type(x
), second_type(y
) {}
242 compressed_pair_imp(first_param_type x
)
245 compressed_pair_imp(second_param_type y
)
248 first_reference
first() {return *this;}
249 first_const_reference
first() const {return *this;}
251 second_reference
second() {return *this;}
252 second_const_reference
second() const {return *this;}
254 // no need to swap empty bases:
255 void swap(::boost::compressed_pair
<T1
,T2
>&) {}
259 // 4 T1 == T2, T1 and T2 both empty
260 // Originally this did not store an instance of T2 at all
261 // but that led to problems beause it meant &x.first() == &x.second()
262 // which is not true for any other kind of pair, so now we store an instance
263 // of T2 just in case the user is relying on first() and second() returning
264 // different objects (albeit both empty).
265 template <class T1
, class T2
>
266 class compressed_pair_imp
<T1
, T2
, 4>
267 : protected ::boost::remove_cv
<T1
>::type
270 typedef T1 first_type
;
271 typedef T2 second_type
;
272 typedef typename call_traits
<first_type
>::param_type first_param_type
;
273 typedef typename call_traits
<second_type
>::param_type second_param_type
;
274 typedef typename call_traits
<first_type
>::reference first_reference
;
275 typedef typename call_traits
<second_type
>::reference second_reference
;
276 typedef typename call_traits
<first_type
>::const_reference first_const_reference
;
277 typedef typename call_traits
<second_type
>::const_reference second_const_reference
;
279 compressed_pair_imp() {}
281 compressed_pair_imp(first_param_type x
, second_param_type y
)
282 : first_type(x
), m_second(y
) {}
284 compressed_pair_imp(first_param_type x
)
285 : first_type(x
), m_second(x
) {}
287 first_reference
first() {return *this;}
288 first_const_reference
first() const {return *this;}
290 second_reference
second() {return m_second
;}
291 second_const_reference
second() const {return m_second
;}
293 void swap(::boost::compressed_pair
<T1
,T2
>&) {}
298 // 5 T1 == T2 and are not empty: //JM
300 template <class T1
, class T2
>
301 class compressed_pair_imp
<T1
, T2
, 5>
304 typedef T1 first_type
;
305 typedef T2 second_type
;
306 typedef typename call_traits
<first_type
>::param_type first_param_type
;
307 typedef typename call_traits
<second_type
>::param_type second_param_type
;
308 typedef typename call_traits
<first_type
>::reference first_reference
;
309 typedef typename call_traits
<second_type
>::reference second_reference
;
310 typedef typename call_traits
<first_type
>::const_reference first_const_reference
;
311 typedef typename call_traits
<second_type
>::const_reference second_const_reference
;
313 compressed_pair_imp() {}
315 compressed_pair_imp(first_param_type x
, second_param_type y
)
316 : first_(x
), second_(y
) {}
318 compressed_pair_imp(first_param_type x
)
319 : first_(x
), second_(x
) {}
321 first_reference
first() {return first_
;}
322 first_const_reference
first() const {return first_
;}
324 second_reference
second() {return second_
;}
325 second_const_reference
second() const {return second_
;}
327 void swap(::boost::compressed_pair
<T1
, T2
>& y
)
329 cp_swap(first_
, y
.first());
330 cp_swap(second_
, y
.second());
339 template <class T1
, class T2
>
340 class compressed_pair
341 : private ::boost::details::compressed_pair_imp
<T1
, T2
,
342 ::boost::details::compressed_pair_switch
<
345 ::boost::is_same
<typename remove_cv
<T1
>::type
, typename remove_cv
<T2
>::type
>::value
,
346 ::boost::is_empty
<T1
>::value
,
347 ::boost::is_empty
<T2
>::value
>::value
>
350 typedef details::compressed_pair_imp
<T1
, T2
,
351 ::boost::details::compressed_pair_switch
<
354 ::boost::is_same
<typename remove_cv
<T1
>::type
, typename remove_cv
<T2
>::type
>::value
,
355 ::boost::is_empty
<T1
>::value
,
356 ::boost::is_empty
<T2
>::value
>::value
> base
;
358 typedef T1 first_type
;
359 typedef T2 second_type
;
360 typedef typename call_traits
<first_type
>::param_type first_param_type
;
361 typedef typename call_traits
<second_type
>::param_type second_param_type
;
362 typedef typename call_traits
<first_type
>::reference first_reference
;
363 typedef typename call_traits
<second_type
>::reference second_reference
;
364 typedef typename call_traits
<first_type
>::const_reference first_const_reference
;
365 typedef typename call_traits
<second_type
>::const_reference second_const_reference
;
367 compressed_pair() : base() {}
368 compressed_pair(first_param_type x
, second_param_type y
) : base(x
, y
) {}
369 explicit compressed_pair(first_param_type x
) : base(x
) {}
370 explicit compressed_pair(second_param_type y
) : base(y
) {}
372 first_reference
first() {return base::first();}
373 first_const_reference
first() const {return base::first();}
375 second_reference
second() {return base::second();}
376 second_const_reference
second() const {return base::second();}
378 void swap(compressed_pair
& y
) { base::swap(y
); }
382 // Partial specialisation for case where T1 == T2:
385 class compressed_pair
<T
, T
>
386 : private details::compressed_pair_imp
<T
, T
,
387 ::boost::details::compressed_pair_switch
<
390 ::boost::is_same
<typename remove_cv
<T
>::type
, typename remove_cv
<T
>::type
>::value
,
391 ::boost::is_empty
<T
>::value
,
392 ::boost::is_empty
<T
>::value
>::value
>
395 typedef details::compressed_pair_imp
<T
, T
,
396 ::boost::details::compressed_pair_switch
<
399 ::boost::is_same
<typename remove_cv
<T
>::type
, typename remove_cv
<T
>::type
>::value
,
400 ::boost::is_empty
<T
>::value
,
401 ::boost::is_empty
<T
>::value
>::value
> base
;
403 typedef T first_type
;
404 typedef T second_type
;
405 typedef typename call_traits
<first_type
>::param_type first_param_type
;
406 typedef typename call_traits
<second_type
>::param_type second_param_type
;
407 typedef typename call_traits
<first_type
>::reference first_reference
;
408 typedef typename call_traits
<second_type
>::reference second_reference
;
409 typedef typename call_traits
<first_type
>::const_reference first_const_reference
;
410 typedef typename call_traits
<second_type
>::const_reference second_const_reference
;
412 compressed_pair() : base() {}
413 compressed_pair(first_param_type x
, second_param_type y
) : base(x
, y
) {}
414 #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
417 compressed_pair(first_param_type x
) : base(x
) {}
419 first_reference
first() {return base::first();}
420 first_const_reference
first() const {return base::first();}
422 second_reference
second() {return base::second();}
423 second_const_reference
second() const {return base::second();}
425 void swap(::boost::compressed_pair
<T
,T
>& y
) { base::swap(y
); }
428 template <class T1
, class T2
>
431 swap(compressed_pair
<T1
, T2
>& x
, compressed_pair
<T1
, T2
>& y
)
439 # pragma warning(pop)
442 #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP