]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/compressed_pair.hpp
2002-05-24 Lars Gullik Bj�nnes <larsbj@birdstep.com>
[lyx.git] / boost / boost / detail / compressed_pair.hpp
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.
6
7 //  See http://www.boost.org for most recent version including documentation.
8
9 // compressed_pair: pair that "compresses" empty members
10 // (see libs/utility/compressed_pair.htm)
11 //
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.
17
18 #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
19 #define BOOST_DETAIL_COMPRESSED_PAIR_HPP
20
21 #include <algorithm>
22 #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
23 #include <boost/type_traits/object_traits.hpp>
24 #endif
25 #ifndef BOOST_SAME_TRAITS_HPP
26 #include <boost/type_traits/same_traits.hpp>
27 #endif
28 #ifndef BOOST_CALL_TRAITS_HPP
29 #include <boost/call_traits.hpp>
30 #endif
31
32 namespace boost
33 {
34
35 template <class T1, class T2>
36 class compressed_pair;
37
38
39 // compressed_pair
40
41 namespace details
42 {
43    // JM altered 26 Jan 2000:
44    template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
45    struct compressed_pair_switch;
46
47    template <class T1, class T2>
48    struct compressed_pair_switch<T1, T2, false, false, false>
49       {static const int value = 0;};
50
51    template <class T1, class T2>
52    struct compressed_pair_switch<T1, T2, false, true, true>
53       {static const int value = 3;};
54
55    template <class T1, class T2>
56    struct compressed_pair_switch<T1, T2, false, true, false>
57       {static const int value = 1;};
58
59    template <class T1, class T2>
60    struct compressed_pair_switch<T1, T2, false, false, true>
61       {static const int value = 2;};
62
63    template <class T1, class T2>
64    struct compressed_pair_switch<T1, T2, true, true, true>
65       {static const int value = 4;};
66
67    template <class T1, class T2>
68    struct compressed_pair_switch<T1, T2, true, false, false>
69       {static const int value = 5;};
70
71    template <class T1, class T2, int Version> class compressed_pair_imp;
72
73 #ifdef __GNUC__
74    // workaround for GCC (JM):
75    using std::swap;
76 #endif
77    //
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):
82    template <typename T>
83    inline void cp_swap(T& t1, T& t2)
84    {
85 #ifndef __GNUC__
86       using std::swap;
87 #endif
88       swap(t1, t2);
89    }
90
91    // 0    derive from neither
92
93    template <class T1, class T2>
94    class compressed_pair_imp<T1, T2, 0>
95    {
96    public:
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;
105
106       compressed_pair_imp() {} 
107
108       compressed_pair_imp(first_param_type x, second_param_type y)
109          : first_(x), second_(y) {}
110
111       compressed_pair_imp(first_param_type x)
112          : first_(x) {}
113
114       compressed_pair_imp(second_param_type y)
115          : second_(y) {}
116
117       first_reference       first()       {return first_;}
118       first_const_reference first() const {return first_;}
119
120       second_reference       second()       {return second_;}
121       second_const_reference second() const {return second_;}
122
123       void swap(::boost::compressed_pair<T1, T2>& y)
124       {
125          cp_swap(first_, y.first());
126          cp_swap(second_, y.second());
127       }
128    private:
129       first_type first_;
130       second_type second_;
131    };
132
133    // 1    derive from T1
134
135    template <class T1, class T2>
136    class compressed_pair_imp<T1, T2, 1>
137       : private T1
138    {
139    public:
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;
148
149       compressed_pair_imp() {}
150
151       compressed_pair_imp(first_param_type x, second_param_type y)
152          : first_type(x), second_(y) {}
153
154       compressed_pair_imp(first_param_type x)
155          : first_type(x) {}
156
157       compressed_pair_imp(second_param_type y)
158          : second_(y) {}
159
160       first_reference       first()       {return *this;}
161       first_const_reference first() const {return *this;}
162
163       second_reference       second()       {return second_;}
164       second_const_reference second() const {return second_;}
165
166       void swap(::boost::compressed_pair<T1,T2>& y)
167       {
168          // no need to swap empty base class:
169          cp_swap(second_, y.second());
170       }
171    private:
172       second_type second_;
173    };
174
175    // 2    derive from T2
176
177    template <class T1, class T2>
178    class compressed_pair_imp<T1, T2, 2>
179       : private T2
180    {
181    public:
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;
190
191       compressed_pair_imp() {}
192
193       compressed_pair_imp(first_param_type x, second_param_type y)
194          : second_type(y), first_(x) {}
195
196       compressed_pair_imp(first_param_type x)
197          : first_(x) {}
198
199       compressed_pair_imp(second_param_type y)
200          : second_type(y) {}
201
202       first_reference       first()       {return first_;}
203       first_const_reference first() const {return first_;}
204
205       second_reference       second()       {return *this;}
206       second_const_reference second() const {return *this;}
207
208       void swap(::boost::compressed_pair<T1,T2>& y)
209       {
210          // no need to swap empty base class:
211          cp_swap(first_, y.first());
212       }
213
214    private:
215       first_type first_;
216    };
217
218    // 3    derive from T1 and T2
219
220    template <class T1, class T2>
221    class compressed_pair_imp<T1, T2, 3>
222       : private T1,
223         private T2
224    {
225    public:
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;
234
235       compressed_pair_imp() {}
236
237       compressed_pair_imp(first_param_type x, second_param_type y)
238          : first_type(x), second_type(y) {}
239
240       compressed_pair_imp(first_param_type x)
241          : first_type(x) {}
242
243       compressed_pair_imp(second_param_type y)
244          : second_type(y) {}
245
246       first_reference       first()       {return *this;}
247       first_const_reference first() const {return *this;}
248
249       second_reference       second()       {return *this;}
250       second_const_reference second() const {return *this;}
251       //
252       // no need to swap empty bases:
253       void swap(::boost::compressed_pair<T1,T2>&) {}
254    };
255
256    // JM
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>
262       : private T1
263    {
264    public:
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;
273
274       compressed_pair_imp() {}
275
276       compressed_pair_imp(first_param_type x, second_param_type)
277          : first_type(x) {}
278
279       compressed_pair_imp(first_param_type x)
280          : first_type(x) {}
281
282       first_reference       first()       {return *this;}
283       first_const_reference first() const {return *this;}
284
285       second_reference       second()       {return *this;}
286       second_const_reference second() const {return *this;}
287
288       void swap(::boost::compressed_pair<T1,T2>&) {}
289    private:
290    };
291
292    // 5    T1 == T2 and are not empty:   //JM
293
294    template <class T1, class T2>
295    class compressed_pair_imp<T1, T2, 5>
296    {
297    public:
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;
306
307       compressed_pair_imp() {}
308
309       compressed_pair_imp(first_param_type x, second_param_type y)
310          : first_(x), second_(y) {}
311
312       compressed_pair_imp(first_param_type x)
313          : first_(x), second_(x) {}
314
315       first_reference       first()       {return first_;}
316       first_const_reference first() const {return first_;}
317
318       second_reference       second()       {return second_;}
319       second_const_reference second() const {return second_;}
320
321       void swap(::boost::compressed_pair<T1, T2>& y)
322       {
323          cp_swap(first_, y.first());
324          cp_swap(second_, y.second());
325       }
326    private:
327       first_type first_;
328       second_type second_;
329    };
330
331 }  // details
332
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<
337                     T1,
338                     T2,
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>
342 {
343 private:
344    typedef details::compressed_pair_imp<T1, T2,
345              ::boost::details::compressed_pair_switch<
346                     T1,
347                     T2,
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;
351 public:
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;
360
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) {}
365
366    first_reference       first()       {return base::first();}
367    first_const_reference first() const {return base::first();}
368
369    second_reference       second()       {return base::second();}
370    second_const_reference second() const {return base::second();}
371
372    void swap(compressed_pair& y) { base::swap(y); }
373 };
374
375 // JM
376 // Partial specialisation for case where T1 == T2:
377 //
378 template <class T>
379 class compressed_pair<T, T>
380    : private details::compressed_pair_imp<T, T,
381              ::boost::details::compressed_pair_switch<
382                     T,
383                     T,
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>
387 {
388 private:
389    typedef details::compressed_pair_imp<T, T,
390              ::boost::details::compressed_pair_switch<
391                     T,
392                     T,
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;
396 public:
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;
405
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))
409    explicit 
410 #endif
411       compressed_pair(first_param_type x) : base(x) {}
412
413    first_reference       first()       {return base::first();}
414    first_const_reference first() const {return base::first();}
415
416    second_reference       second()       {return base::second();}
417    second_const_reference second() const {return base::second();}
418
419    void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
420 };
421
422 template <class T1, class T2>
423 inline
424 void
425 swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
426 {
427    x.swap(y);
428 }
429
430 } // boost
431
432 #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
433
434
435