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).
5//
6// See http://www.boost.org/libs/utility for most recent version including documentation.
7
8// compressed_pair: pair that "compresses" empty members
9// (see libs/utility/doc/html/compressed_pair.html)
10//
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.
19
20#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
21#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
22
23#include <algorithm>
24
25#include <boost/type_traits/remove_cv.hpp>
26#include <boost/type_traits/is_empty.hpp>
27#include <boost/type_traits/is_final.hpp>
28#include <boost/type_traits/is_same.hpp>
29#include <boost/call_traits.hpp>
30
31#ifdef BOOST_MSVC
32# pragma warning(push)
33# pragma warning(disable:4512)
34#endif
35namespace boost
36{
37
38template <class T1, class T2>
39class compressed_pair;
40
41
42// compressed_pair
43
44namespace details
45{
46 template<class T, bool E = boost::is_final<T>::value>
47 struct compressed_pair_empty
48 : ::boost::false_type { };
49
50 template<class T>
51 struct compressed_pair_empty<T, false>
52 : ::boost::is_empty<T> { };
53
54 // JM altered 26 Jan 2000:
55 template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
56 struct compressed_pair_switch;
57
58 template <class T1, class T2>
59 struct compressed_pair_switch<T1, T2, false, false, false>
60 {static const int value = 0;};
61
62 template <class T1, class T2>
63 struct compressed_pair_switch<T1, T2, false, true, true>
64 {static const int value = 3;};
65
66 template <class T1, class T2>
67 struct compressed_pair_switch<T1, T2, false, true, false>
68 {static const int value = 1;};
69
70 template <class T1, class T2>
71 struct compressed_pair_switch<T1, T2, false, false, true>
72 {static const int value = 2;};
73
74 template <class T1, class T2>
75 struct compressed_pair_switch<T1, T2, true, true, true>
76 {static const int value = 4;};
77
78 template <class T1, class T2>
79 struct compressed_pair_switch<T1, T2, true, false, false>
80 {static const int value = 5;};
81
82 template <class T1, class T2, int Version> class compressed_pair_imp;
83
84#ifdef __GNUC__
85 // workaround for GCC (JM):
86 using std::swap;
87#endif
88 //
89 // can't call unqualified swap from within classname::swap
90 // as Koenig lookup rules will find only the classname::swap
91 // member function not the global declaration, so use cp_swap
92 // as a forwarding function (JM):
93 template <typename T>
94 inline void cp_swap(T& t1, T& t2)
95 {
96#ifndef __GNUC__
97 using std::swap;
98#endif
99 swap(t1, t2);
100 }
101
102 // 0 derive from neither
103
104 template <class T1, class T2>
105 class compressed_pair_imp<T1, T2, 0>
106 {
107 public:
108 typedef T1 first_type;
109 typedef T2 second_type;
110 typedef typename call_traits<first_type>::param_type first_param_type;
111 typedef typename call_traits<second_type>::param_type second_param_type;
112 typedef typename call_traits<first_type>::reference first_reference;
113 typedef typename call_traits<second_type>::reference second_reference;
114 typedef typename call_traits<first_type>::const_reference first_const_reference;
115 typedef typename call_traits<second_type>::const_reference second_const_reference;
116
117 compressed_pair_imp() {}
118
119 compressed_pair_imp(first_param_type x, second_param_type y)
120 : first_(x), second_(y) {}
121
122 compressed_pair_imp(first_param_type x)
123 : first_(x) {}
124
125 compressed_pair_imp(second_param_type y)
126 : second_(y) {}
127
128 first_reference first() {return first_;}
129 first_const_reference first() const {return first_;}
130
131 second_reference second() {return second_;}
132 second_const_reference second() const {return second_;}
133
134 void swap(::boost::compressed_pair<T1, T2>& y)
135 {
136 cp_swap(first_, y.first());
137 cp_swap(second_, y.second());
138 }
139 private:
140 first_type first_;
141 second_type second_;
142 };
143
144 // 1 derive from T1
145
146 template <class T1, class T2>
147 class compressed_pair_imp<T1, T2, 1>
148 : protected ::boost::remove_cv<T1>::type
149 {
150 public:
151 typedef T1 first_type;
152 typedef T2 second_type;
153 typedef typename call_traits<first_type>::param_type first_param_type;
154 typedef typename call_traits<second_type>::param_type second_param_type;
155 typedef typename call_traits<first_type>::reference first_reference;
156 typedef typename call_traits<second_type>::reference second_reference;
157 typedef typename call_traits<first_type>::const_reference first_const_reference;
158 typedef typename call_traits<second_type>::const_reference second_const_reference;
159
160 compressed_pair_imp() {}
161
162 compressed_pair_imp(first_param_type x, second_param_type y)
163 : first_type(x), second_(y) {}
164
165 compressed_pair_imp(first_param_type x)
166 : first_type(x) {}
167
168 compressed_pair_imp(second_param_type y)
169 : second_(y) {}
170
171 first_reference first() {return *this;}
172 first_const_reference first() const {return *this;}
173
174 second_reference second() {return second_;}
175 second_const_reference second() const {return second_;}
176
177 void swap(::boost::compressed_pair<T1,T2>& y)
178 {
179 // no need to swap empty base class:
180 cp_swap(second_, y.second());
181 }
182 private:
183 second_type second_;
184 };
185
186 // 2 derive from T2
187
188 template <class T1, class T2>
189 class compressed_pair_imp<T1, T2, 2>
190 : protected ::boost::remove_cv<T2>::type
191 {
192 public:
193 typedef T1 first_type;
194 typedef T2 second_type;
195 typedef typename call_traits<first_type>::param_type first_param_type;
196 typedef typename call_traits<second_type>::param_type second_param_type;
197 typedef typename call_traits<first_type>::reference first_reference;
198 typedef typename call_traits<second_type>::reference second_reference;
199 typedef typename call_traits<first_type>::const_reference first_const_reference;
200 typedef typename call_traits<second_type>::const_reference second_const_reference;
201
202 compressed_pair_imp() {}
203
204 compressed_pair_imp(first_param_type x, second_param_type y)
205 : second_type(y), first_(x) {}
206
207 compressed_pair_imp(first_param_type x)
208 : first_(x) {}
209
210 compressed_pair_imp(second_param_type y)
211 : second_type(y) {}
212
213 first_reference first() {return first_;}
214 first_const_reference first() const {return first_;}
215
216 second_reference second() {return *this;}
217 second_const_reference second() const {return *this;}
218
219 void swap(::boost::compressed_pair<T1,T2>& y)
220 {
221 // no need to swap empty base class:
222 cp_swap(first_, y.first());
223 }
224
225 private:
226 first_type first_;
227 };
228
229 // 3 derive from T1 and T2
230
231 template <class T1, class T2>
232 class compressed_pair_imp<T1, T2, 3>
233 : protected ::boost::remove_cv<T1>::type,
234 protected ::boost::remove_cv<T2>::type
235 {
236 public:
237 typedef T1 first_type;
238 typedef T2 second_type;
239 typedef typename call_traits<first_type>::param_type first_param_type;
240 typedef typename call_traits<second_type>::param_type second_param_type;
241 typedef typename call_traits<first_type>::reference first_reference;
242 typedef typename call_traits<second_type>::reference second_reference;
243 typedef typename call_traits<first_type>::const_reference first_const_reference;
244 typedef typename call_traits<second_type>::const_reference second_const_reference;
245
246 compressed_pair_imp() {}
247
248 compressed_pair_imp(first_param_type x, second_param_type y)
249 : first_type(x), second_type(y) {}
250
251 compressed_pair_imp(first_param_type x)
252 : first_type(x) {}
253
254 compressed_pair_imp(second_param_type y)
255 : second_type(y) {}
256
257 first_reference first() {return *this;}
258 first_const_reference first() const {return *this;}
259
260 second_reference second() {return *this;}
261 second_const_reference second() const {return *this;}
262 //
263 // no need to swap empty bases:
264 void swap(::boost::compressed_pair<T1,T2>&) {}
265 };
266
267 // JM
268 // 4 T1 == T2, T1 and T2 both empty
269 // Originally this did not store an instance of T2 at all
270 // but that led to problems beause it meant &x.first() == &x.second()
271 // which is not true for any other kind of pair, so now we store an instance
272 // of T2 just in case the user is relying on first() and second() returning
273 // different objects (albeit both empty).
274 template <class T1, class T2>
275 class compressed_pair_imp<T1, T2, 4>
276 : protected ::boost::remove_cv<T1>::type
277 {
278 public:
279 typedef T1 first_type;
280 typedef T2 second_type;
281 typedef typename call_traits<first_type>::param_type first_param_type;
282 typedef typename call_traits<second_type>::param_type second_param_type;
283 typedef typename call_traits<first_type>::reference first_reference;
284 typedef typename call_traits<second_type>::reference second_reference;
285 typedef typename call_traits<first_type>::const_reference first_const_reference;
286 typedef typename call_traits<second_type>::const_reference second_const_reference;
287
288 compressed_pair_imp() {}
289
290 compressed_pair_imp(first_param_type x, second_param_type y)
291 : first_type(x), m_second(y) {}
292
293 compressed_pair_imp(first_param_type x)
294 : first_type(x), m_second(x) {}
295
296 first_reference first() {return *this;}
297 first_const_reference first() const {return *this;}
298
299 second_reference second() {return m_second;}
300 second_const_reference second() const {return m_second;}
301
302 void swap(::boost::compressed_pair<T1,T2>&) {}
303 private:
304 T2 m_second;
305 };
306
307 // 5 T1 == T2 and are not empty: //JM
308
309 template <class T1, class T2>
310 class compressed_pair_imp<T1, T2, 5>
311 {
312 public:
313 typedef T1 first_type;
314 typedef T2 second_type;
315 typedef typename call_traits<first_type>::param_type first_param_type;
316 typedef typename call_traits<second_type>::param_type second_param_type;
317 typedef typename call_traits<first_type>::reference first_reference;
318 typedef typename call_traits<second_type>::reference second_reference;
319 typedef typename call_traits<first_type>::const_reference first_const_reference;
320 typedef typename call_traits<second_type>::const_reference second_const_reference;
321
322 compressed_pair_imp() {}
323
324 compressed_pair_imp(first_param_type x, second_param_type y)
325 : first_(x), second_(y) {}
326
327 compressed_pair_imp(first_param_type x)
328 : first_(x), second_(x) {}
329
330 first_reference first() {return first_;}
331 first_const_reference first() const {return first_;}
332
333 second_reference second() {return second_;}
334 second_const_reference second() const {return second_;}
335
336 void swap(::boost::compressed_pair<T1, T2>& y)
337 {
338 cp_swap(first_, y.first());
339 cp_swap(second_, y.second());
340 }
341 private:
342 first_type first_;
343 second_type second_;
344 };
345
346} // details
347
348template <class T1, class T2>
349class compressed_pair
350#ifndef BOOST_UTILITY_DOCS
351 : private ::boost::details::compressed_pair_imp<T1, T2,
352 ::boost::details::compressed_pair_switch<
353 T1,
354 T2,
355 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
356 ::boost::details::compressed_pair_empty<T1>::value,
357 ::boost::details::compressed_pair_empty<T2>::value>::value>
358#endif // BOOST_UTILITY_DOCS
359{
360private:
361 typedef details::compressed_pair_imp<T1, T2,
362 ::boost::details::compressed_pair_switch<
363 T1,
364 T2,
365 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
366 ::boost::details::compressed_pair_empty<T1>::value,
367 ::boost::details::compressed_pair_empty<T2>::value>::value> base;
368public:
369 typedef T1 first_type;
370 typedef T2 second_type;
371 typedef typename call_traits<first_type>::param_type first_param_type;
372 typedef typename call_traits<second_type>::param_type second_param_type;
373 typedef typename call_traits<first_type>::reference first_reference;
374 typedef typename call_traits<second_type>::reference second_reference;
375 typedef typename call_traits<first_type>::const_reference first_const_reference;
376 typedef typename call_traits<second_type>::const_reference second_const_reference;
377
378 compressed_pair() : base() {}
379 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
380 explicit compressed_pair(first_param_type x) : base(x) {}
381 explicit compressed_pair(second_param_type y) : base(y) {}
382
383 first_reference first() {return base::first();}
384 first_const_reference first() const {return base::first();}
385
386 second_reference second() {return base::second();}
387 second_const_reference second() const {return base::second();}
388
389 void swap(compressed_pair& y) { base::swap(y); }
390};
391
392// JM
393// Partial specialisation for case where T1 == T2:
394//
395template <class T>
396class compressed_pair<T, T>
397#ifndef BOOST_UTILITY_DOCS
398 : private details::compressed_pair_imp<T, T,
399 ::boost::details::compressed_pair_switch<
400 T,
401 T,
402 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
403 ::boost::details::compressed_pair_empty<T>::value,
404 ::boost::details::compressed_pair_empty<T>::value>::value>
405#endif // BOOST_UTILITY_DOCS
406{
407private:
408 typedef details::compressed_pair_imp<T, T,
409 ::boost::details::compressed_pair_switch<
410 T,
411 T,
412 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
413 ::boost::details::compressed_pair_empty<T>::value,
414 ::boost::details::compressed_pair_empty<T>::value>::value> base;
415public:
416 typedef T first_type;
417 typedef T second_type;
418 typedef typename call_traits<first_type>::param_type first_param_type;
419 typedef typename call_traits<second_type>::param_type second_param_type;
420 typedef typename call_traits<first_type>::reference first_reference;
421 typedef typename call_traits<second_type>::reference second_reference;
422 typedef typename call_traits<first_type>::const_reference first_const_reference;
423 typedef typename call_traits<second_type>::const_reference second_const_reference;
424
425 compressed_pair() : base() {}
426 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
427#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
428 explicit
429#endif
430 compressed_pair(first_param_type x) : base(x) {}
431
432 first_reference first() {return base::first();}
433 first_const_reference first() const {return base::first();}
434
435 second_reference second() {return base::second();}
436 second_const_reference second() const {return base::second();}
437
438 void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
439};
440
441template <class T1, class T2>
442inline
443void
444swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
445{
446 x.swap(y);
447}
448
449} // boost
450
451#ifdef BOOST_MSVC
452# pragma warning(pop)
453#endif
454
455#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
456
457

source code of boost/libs/utility/include/boost/detail/compressed_pair.hpp