]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/compressed_pair.hpp
* Add the iostreams and range libs to our copy of boost
[lyx.git] / boost / boost / detail / compressed_pair.hpp
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
30 namespace boost
31 {
32
33 template <class T1, class T2>
34 class compressed_pair;
35
36
37 // compressed_pair
38
39 namespace 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
332 template <class T1, class T2>
333 class 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 {
342 private:
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;
350 public:
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 //
377 template <class T>
378 class 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 {
387 private:
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;
395 public:
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
421 template <class T1, class T2>
422 inline
423 void
424 swap(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