source: NonGTP/Boost/boost/detail/compressed_pair.hpp @ 857

Revision 857, 16.2 KB checked in by igarcia, 18 years ago (diff)
Line 
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/compressed_pair.htm)
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
30namespace boost
31{
32
33template <class T1, class T2>
34class compressed_pair;
35
36
37// compressed_pair
38
39namespace details
40{
41   // JM altered 26 Jan 2000:
42   template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
43   struct compressed_pair_switch;
44
45   template <class T1, class T2>
46   struct compressed_pair_switch<T1, T2, false, false, false>
47      {static const int value = 0;};
48
49   template <class T1, class T2>
50   struct compressed_pair_switch<T1, T2, false, true, true>
51      {static const int value = 3;};
52
53   template <class T1, class T2>
54   struct compressed_pair_switch<T1, T2, false, true, false>
55      {static const int value = 1;};
56
57   template <class T1, class T2>
58   struct compressed_pair_switch<T1, T2, false, false, true>
59      {static const int value = 2;};
60
61   template <class T1, class T2>
62   struct compressed_pair_switch<T1, T2, true, true, true>
63      {static const int value = 4;};
64
65   template <class T1, class T2>
66   struct compressed_pair_switch<T1, T2, true, false, false>
67      {static const int value = 5;};
68
69   template <class T1, class T2, int Version> class compressed_pair_imp;
70
71#ifdef __GNUC__
72   // workaround for GCC (JM):
73   using std::swap;
74#endif
75   //
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):
80   template <typename T>
81   inline void cp_swap(T& t1, T& t2)
82   {
83#ifndef __GNUC__
84      using std::swap;
85#endif
86      swap(t1, t2);
87   }
88
89   // 0    derive from neither
90
91   template <class T1, class T2>
92   class compressed_pair_imp<T1, T2, 0>
93   {
94   public:
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;
103
104      compressed_pair_imp() {}
105
106      compressed_pair_imp(first_param_type x, second_param_type y)
107         : first_(x), second_(y) {}
108
109      compressed_pair_imp(first_param_type x)
110         : first_(x) {}
111
112      compressed_pair_imp(second_param_type y)
113         : second_(y) {}
114
115      first_reference       first()       {return first_;}
116      first_const_reference first() const {return first_;}
117
118      second_reference       second()       {return second_;}
119      second_const_reference second() const {return second_;}
120
121      void swap(::boost::compressed_pair<T1, T2>& y)
122      {
123         cp_swap(first_, y.first());
124         cp_swap(second_, y.second());
125      }
126   private:
127      first_type first_;
128      second_type second_;
129   };
130
131   // 1    derive from T1
132
133   template <class T1, class T2>
134   class compressed_pair_imp<T1, T2, 1>
135      : private ::boost::remove_cv<T1>::type
136   {
137   public:
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;
146
147      compressed_pair_imp() {}
148
149      compressed_pair_imp(first_param_type x, second_param_type y)
150         : first_type(x), second_(y) {}
151
152      compressed_pair_imp(first_param_type x)
153         : first_type(x) {}
154
155      compressed_pair_imp(second_param_type y)
156         : second_(y) {}
157
158      first_reference       first()       {return *this;}
159      first_const_reference first() const {return *this;}
160
161      second_reference       second()       {return second_;}
162      second_const_reference second() const {return second_;}
163
164      void swap(::boost::compressed_pair<T1,T2>& y)
165      {
166         // no need to swap empty base class:
167         cp_swap(second_, y.second());
168      }
169   private:
170      second_type second_;
171   };
172
173   // 2    derive from T2
174
175   template <class T1, class T2>
176   class compressed_pair_imp<T1, T2, 2>
177      : private ::boost::remove_cv<T2>::type
178   {
179   public:
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;
188
189      compressed_pair_imp() {}
190
191      compressed_pair_imp(first_param_type x, second_param_type y)
192         : second_type(y), first_(x) {}
193
194      compressed_pair_imp(first_param_type x)
195         : first_(x) {}
196
197      compressed_pair_imp(second_param_type y)
198         : second_type(y) {}
199
200      first_reference       first()       {return first_;}
201      first_const_reference first() const {return first_;}
202
203      second_reference       second()       {return *this;}
204      second_const_reference second() const {return *this;}
205
206      void swap(::boost::compressed_pair<T1,T2>& y)
207      {
208         // no need to swap empty base class:
209         cp_swap(first_, y.first());
210      }
211
212   private:
213      first_type first_;
214   };
215
216   // 3    derive from T1 and T2
217
218   template <class T1, class T2>
219   class compressed_pair_imp<T1, T2, 3>
220      : private ::boost::remove_cv<T1>::type,
221        private ::boost::remove_cv<T2>::type
222   {
223   public:
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;
232
233      compressed_pair_imp() {}
234
235      compressed_pair_imp(first_param_type x, second_param_type y)
236         : first_type(x), second_type(y) {}
237
238      compressed_pair_imp(first_param_type x)
239         : first_type(x) {}
240
241      compressed_pair_imp(second_param_type y)
242         : second_type(y) {}
243
244      first_reference       first()       {return *this;}
245      first_const_reference first() const {return *this;}
246
247      second_reference       second()       {return *this;}
248      second_const_reference second() const {return *this;}
249      //
250      // no need to swap empty bases:
251      void swap(::boost::compressed_pair<T1,T2>&) {}
252   };
253
254   // JM
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>
260      : private ::boost::remove_cv<T1>::type
261   {
262   public:
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;
271
272      compressed_pair_imp() {}
273
274      compressed_pair_imp(first_param_type x, second_param_type y)
275         : first_type(x), m_second(y) {}
276
277      compressed_pair_imp(first_param_type x)
278         : first_type(x), m_second(x) {}
279
280      first_reference       first()       {return *this;}
281      first_const_reference first() const {return *this;}
282
283      second_reference       second()       {return m_second;}
284      second_const_reference second() const {return m_second;}
285
286      void swap(::boost::compressed_pair<T1,T2>&) {}
287   private:
288      T2 m_second;
289   };
290
291   // 5    T1 == T2 and are not empty:   //JM
292
293   template <class T1, class T2>
294   class compressed_pair_imp<T1, T2, 5>
295   {
296   public:
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;
305
306      compressed_pair_imp() {}
307
308      compressed_pair_imp(first_param_type x, second_param_type y)
309         : first_(x), second_(y) {}
310
311      compressed_pair_imp(first_param_type x)
312         : first_(x), second_(x) {}
313
314      first_reference       first()       {return first_;}
315      first_const_reference first() const {return first_;}
316
317      second_reference       second()       {return second_;}
318      second_const_reference second() const {return second_;}
319
320      void swap(::boost::compressed_pair<T1, T2>& y)
321      {
322         cp_swap(first_, y.first());
323         cp_swap(second_, y.second());
324      }
325   private:
326      first_type first_;
327      second_type second_;
328   };
329
330}  // details
331
332template <class T1, class T2>
333class compressed_pair
334   : private ::boost::details::compressed_pair_imp<T1, T2,
335             ::boost::details::compressed_pair_switch<
336                    T1,
337                    T2,
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>
341{
342private:
343   typedef details::compressed_pair_imp<T1, T2,
344             ::boost::details::compressed_pair_switch<
345                    T1,
346                    T2,
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;
350public:
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;
359
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) {}
364
365   first_reference       first()       {return base::first();}
366   first_const_reference first() const {return base::first();}
367
368   second_reference       second()       {return base::second();}
369   second_const_reference second() const {return base::second();}
370
371   void swap(compressed_pair& y) { base::swap(y); }
372};
373
374// JM
375// Partial specialisation for case where T1 == T2:
376//
377template <class T>
378class compressed_pair<T, T>
379   : private details::compressed_pair_imp<T, T,
380             ::boost::details::compressed_pair_switch<
381                    T,
382                    T,
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>
386{
387private:
388   typedef details::compressed_pair_imp<T, T,
389             ::boost::details::compressed_pair_switch<
390                    T,
391                    T,
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;
395public:
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;
404
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))
408   explicit
409#endif
410      compressed_pair(first_param_type x) : base(x) {}
411
412   first_reference       first()       {return base::first();}
413   first_const_reference first() const {return base::first();}
414
415   second_reference       second()       {return base::second();}
416   second_const_reference second() const {return base::second();}
417
418   void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
419};
420
421template <class T1, class T2>
422inline
423void
424swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
425{
426   x.swap(y);
427}
428
429} // boost
430
431#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
432
Note: See TracBrowser for help on using the repository browser.