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_same.hpp>
28#include <boost/call_traits.hpp>
29
30#ifdef BOOST_MSVC
31# pragma warning(push)
32# pragma warning(disable:4512)
33#endif
34namespace boost
35{
36
37template <class T1, class T2>
38class compressed_pair;
39
40
41// compressed_pair
42
43namespace details
44{
45 // JM altered 26 Jan 2000:
46 template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
47 struct compressed_pair_switch;
48
49 template <class T1, class T2>
50 struct compressed_pair_switch<T1, T2, false, false, false>
51 {static const int value = 0;};
52
53 template <class T1, class T2>
54 struct compressed_pair_switch<T1, T2, false, true, true>
55 {static const int value = 3;};
56
57 template <class T1, class T2>
58 struct compressed_pair_switch<T1, T2, false, true, false>
59 {static const int value = 1;};
60
61 template <class T1, class T2>
62 struct compressed_pair_switch<T1, T2, false, false, true>
63 {static const int value = 2;};
64
65 template <class T1, class T2>
66 struct compressed_pair_switch<T1, T2, true, true, true>
67 {static const int value = 4;};
68
69 template <class T1, class T2>
70 struct compressed_pair_switch<T1, T2, true, false, false>
71 {static const int value = 5;};
72
73 template <class T1, class T2, int Version> class compressed_pair_imp;
74
75#ifdef __GNUC__
76 // workaround for GCC (JM):
77 using std::swap;
78#endif
79 //
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):
84 template <typename T>
85 inline void cp_swap(T& t1, T& t2)
86 {
87#ifndef __GNUC__
88 using std::swap;
89#endif
90 swap(t1, t2);
91 }
92
93 // 0 derive from neither
94
95 template <class T1, class T2>
96 class compressed_pair_imp<T1, T2, 0>
97 {
98 public:
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;
107
108 compressed_pair_imp() {}
109
110 compressed_pair_imp(first_param_type x, second_param_type y)
111 : first_(x), second_(y) {}
112
113 compressed_pair_imp(first_param_type x)
114 : first_(x) {}
115
116 compressed_pair_imp(second_param_type y)
117 : second_(y) {}
118
119 first_reference first() {return first_;}
120 first_const_reference first() const {return first_;}
121
122 second_reference second() {return second_;}
123 second_const_reference second() const {return second_;}
124
125 void swap(::boost::compressed_pair<T1, T2>& y)
126 {
127 cp_swap(first_, y.first());
128 cp_swap(second_, y.second());
129 }
130 private:
131 first_type first_;
132 second_type second_;
133 };
134
135 // 1 derive from T1
136
137 template <class T1, class T2>
138 class compressed_pair_imp<T1, T2, 1>
139 : protected ::boost::remove_cv<T1>::type
140 {
141 public:
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;
150
151 compressed_pair_imp() {}
152
153 compressed_pair_imp(first_param_type x, second_param_type y)
154 : first_type(x), second_(y) {}
155
156 compressed_pair_imp(first_param_type x)
157 : first_type(x) {}
158
159 compressed_pair_imp(second_param_type y)
160 : second_(y) {}
161
162 first_reference first() {return *this;}
163 first_const_reference first() const {return *this;}
164
165 second_reference second() {return second_;}
166 second_const_reference second() const {return second_;}
167
168 void swap(::boost::compressed_pair<T1,T2>& y)
169 {
170 // no need to swap empty base class:
171 cp_swap(second_, y.second());
172 }
173 private:
174 second_type second_;
175 };
176
177 // 2 derive from T2
178
179 template <class T1, class T2>
180 class compressed_pair_imp<T1, T2, 2>
181 : protected ::boost::remove_cv<T2>::type
182 {
183 public:
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;
192
193 compressed_pair_imp() {}
194
195 compressed_pair_imp(first_param_type x, second_param_type y)
196 : second_type(y), first_(x) {}
197
198 compressed_pair_imp(first_param_type x)
199 : first_(x) {}
200
201 compressed_pair_imp(second_param_type y)
202 : second_type(y) {}
203
204 first_reference first() {return first_;}
205 first_const_reference first() const {return first_;}
206
207 second_reference second() {return *this;}
208 second_const_reference second() const {return *this;}
209
210 void swap(::boost::compressed_pair<T1,T2>& y)
211 {
212 // no need to swap empty base class:
213 cp_swap(first_, y.first());
214 }
215
216 private:
217 first_type first_;
218 };
219
220 // 3 derive from T1 and T2
221
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
226 {
227 public:
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;
236
237 compressed_pair_imp() {}
238
239 compressed_pair_imp(first_param_type x, second_param_type y)
240 : first_type(x), second_type(y) {}
241
242 compressed_pair_imp(first_param_type x)
243 : first_type(x) {}
244
245 compressed_pair_imp(second_param_type y)
246 : second_type(y) {}
247
248 first_reference first() {return *this;}
249 first_const_reference first() const {return *this;}
250
251 second_reference second() {return *this;}
252 second_const_reference second() const {return *this;}
253 //
254 // no need to swap empty bases:
255 void swap(::boost::compressed_pair<T1,T2>&) {}
256 };
257
258 // JM
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
268 {
269 public:
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;
278
279 compressed_pair_imp() {}
280
281 compressed_pair_imp(first_param_type x, second_param_type y)
282 : first_type(x), m_second(y) {}
283
284 compressed_pair_imp(first_param_type x)
285 : first_type(x), m_second(x) {}
286
287 first_reference first() {return *this;}
288 first_const_reference first() const {return *this;}
289
290 second_reference second() {return m_second;}
291 second_const_reference second() const {return m_second;}
292
293 void swap(::boost::compressed_pair<T1,T2>&) {}
294 private:
295 T2 m_second;
296 };
297
298 // 5 T1 == T2 and are not empty: //JM
299
300 template <class T1, class T2>
301 class compressed_pair_imp<T1, T2, 5>
302 {
303 public:
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;
312
313 compressed_pair_imp() {}
314
315 compressed_pair_imp(first_param_type x, second_param_type y)
316 : first_(x), second_(y) {}
317
318 compressed_pair_imp(first_param_type x)
319 : first_(x), second_(x) {}
320
321 first_reference first() {return first_;}
322 first_const_reference first() const {return first_;}
323
324 second_reference second() {return second_;}
325 second_const_reference second() const {return second_;}
326
327 void swap(::boost::compressed_pair<T1, T2>& y)
328 {
329 cp_swap(first_, y.first());
330 cp_swap(second_, y.second());
331 }
332 private:
333 first_type first_;
334 second_type second_;
335 };
336
337} // details
338
339template <class T1, class T2>
340class compressed_pair
341 : private ::boost::details::compressed_pair_imp<T1, T2,
342 ::boost::details::compressed_pair_switch<
343 T1,
344 T2,
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>
348{
349private:
350 typedef details::compressed_pair_imp<T1, T2,
351 ::boost::details::compressed_pair_switch<
352 T1,
353 T2,
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;
357public:
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;
366
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) {}
371
372 first_reference first() {return base::first();}
373 first_const_reference first() const {return base::first();}
374
375 second_reference second() {return base::second();}
376 second_const_reference second() const {return base::second();}
377
378 void swap(compressed_pair& y) { base::swap(y); }
379};
380
381// JM
382// Partial specialisation for case where T1 == T2:
383//
384template <class T>
385class compressed_pair<T, T>
386 : private details::compressed_pair_imp<T, T,
387 ::boost::details::compressed_pair_switch<
388 T,
389 T,
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>
393{
394private:
395 typedef details::compressed_pair_imp<T, T,
396 ::boost::details::compressed_pair_switch<
397 T,
398 T,
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;
402public:
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;
411
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))
415 explicit
416#endif
417 compressed_pair(first_param_type x) : base(x) {}
418
419 first_reference first() {return base::first();}
420 first_const_reference first() const {return base::first();}
421
422 second_reference second() {return base::second();}
423 second_const_reference second() const {return base::second();}
424
425 void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
426};
427
428template <class T1, class T2>
429inline
430void
431swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
432{
433 x.swap(y);
434}
435
436} // boost
437
438#ifdef BOOST_MSVC
439# pragma warning(pop)
440#endif
441
442#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
443
444

source code of boost/boost/detail/compressed_pair.hpp