]> git.lyx.org Git - lyx.git/blob - boost/boost/detail/ob_compressed_pair.hpp
major boost update
[lyx.git] / boost / boost / detail / ob_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 //  see libs/utility/compressed_pair.hpp
9 //
10 /* Release notes:
11    20 Jan 2001:
12         Fixed obvious bugs (David Abrahams)
13    07 Oct 2000:
14       Added better single argument constructor support.
15    03 Oct 2000:
16       Added VC6 support (JM).
17    23rd July 2000:
18       Additional comments added. (JM)
19    Jan 2000:
20       Original version: this version crippled for use with crippled compilers
21       - John Maddock Jan 2000.
22 */
23
24
25 #ifndef BOOST_OB_COMPRESSED_PAIR_HPP
26 #define BOOST_OB_COMPRESSED_PAIR_HPP
27
28 #include <algorithm>
29 #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
30 #include <boost/type_traits/object_traits.hpp>
31 #endif
32 #ifndef BOOST_SAME_TRAITS_HPP
33 #include <boost/type_traits/same_traits.hpp>
34 #endif
35 #ifndef BOOST_CALL_TRAITS_HPP
36 #include <boost/call_traits.hpp>
37 #endif
38
39 namespace boost
40 {
41 #ifdef BOOST_MSVC6_MEMBER_TEMPLATES
42 //
43 // use member templates to emulate
44 // partial specialisation.  Note that due to
45 // problems with overload resolution with VC6
46 // each of the compressed_pair versions that follow
47 // have one template single-argument constructor
48 // in place of two specific constructors:
49 //
50
51 template <class T1, class T2>
52 class compressed_pair;
53
54 namespace detail{
55
56 template <class A, class T1, class T2>
57 struct best_conversion_traits
58 {
59    typedef char one;
60    typedef char (&two)[2];
61    static A a;
62    static one test(T1);
63    static two test(T2);
64
65    enum { value = sizeof(test(a)) };
66 };
67
68 template <int>
69 struct init_one;
70
71 template <>
72 struct init_one<1>
73 {
74    template <class A, class T1, class T2>
75    static void init(const A& a, T1* p1, T2*)
76    {
77       *p1 = a;
78    }
79 };
80
81 template <>
82 struct init_one<2>
83 {
84    template <class A, class T1, class T2>
85    static void init(const A& a, T1*, T2* p2)
86    {
87       *p2 = a;
88    }
89 };
90
91
92 // T1 != T2, both non-empty
93 template <class T1, class T2>
94 class compressed_pair_0
95 {
96 private:
97    T1 _first;
98    T2 _second;
99 public:
100    typedef T1                                                 first_type;
101    typedef T2                                                 second_type;
102    typedef typename call_traits<first_type>::param_type       first_param_type;
103    typedef typename call_traits<second_type>::param_type      second_param_type;
104    typedef typename call_traits<first_type>::reference        first_reference;
105    typedef typename call_traits<second_type>::reference       second_reference;
106    typedef typename call_traits<first_type>::const_reference  first_const_reference;
107    typedef typename call_traits<second_type>::const_reference second_const_reference;
108
109             compressed_pair_0() : _first(), _second() {}
110             compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
111    template <class A>
112    explicit compressed_pair_0(const A& val)
113    {
114       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
115    }
116    compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
117       : _first(x.first()), _second(x.second()) {}
118
119 #if 0
120   compressed_pair_0& operator=(const compressed_pair_0& x) {
121     cout << "assigning compressed pair 0" << endl;
122     _first = x._first;
123     _second = x._second;
124     cout << "finished assigning compressed pair 0" << endl;
125     return *this;
126   }
127 #endif
128
129    first_reference       first()       { return _first; }
130    first_const_reference first() const { return _first; }
131
132    second_reference       second()       { return _second; }
133    second_const_reference second() const { return _second; }
134
135    void swap(compressed_pair_0& y)
136    {
137       using std::swap;
138       swap(_first, y._first);
139       swap(_second, y._second);
140    }
141 };
142
143 // T1 != T2, T2 empty
144 template <class T1, class T2>
145 class compressed_pair_1 : T2
146 {
147 private:
148    T1 _first;
149 public:
150    typedef T1                                                 first_type;
151    typedef T2                                                 second_type;
152    typedef typename call_traits<first_type>::param_type       first_param_type;
153    typedef typename call_traits<second_type>::param_type      second_param_type;
154    typedef typename call_traits<first_type>::reference        first_reference;
155    typedef typename call_traits<second_type>::reference       second_reference;
156    typedef typename call_traits<first_type>::const_reference  first_const_reference;
157    typedef typename call_traits<second_type>::const_reference second_const_reference;
158
159             compressed_pair_1() : T2(), _first() {}
160             compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
161
162    template <class A>
163    explicit compressed_pair_1(const A& val)
164    {
165       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
166    }
167
168    compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
169       : T2(x.second()), _first(x.first()) {}
170
171 #ifdef BOOST_MSVC
172   // Total weirdness. If the assignment to _first is moved after
173   // the call to the inherited operator=, then this breaks graph/test/graph.cpp
174   // by way of iterator_adaptor.
175   compressed_pair_1& operator=(const compressed_pair_1& x) {
176     _first = x._first;
177     T2::operator=(x);
178     return *this;
179   }
180 #endif
181
182    first_reference       first()       { return _first; }
183    first_const_reference first() const { return _first; }
184
185    second_reference       second()       { return *this; }
186    second_const_reference second() const { return *this; }
187
188    void swap(compressed_pair_1& y)
189    {
190       // no need to swap empty base class:
191       using std::swap;
192       swap(_first, y._first);
193    }
194 };
195
196 // T1 != T2, T1 empty
197 template <class T1, class T2>
198 class compressed_pair_2 : T1
199 {
200 private:
201    T2 _second;
202 public:
203    typedef T1                                                 first_type;
204    typedef T2                                                 second_type;
205    typedef typename call_traits<first_type>::param_type       first_param_type;
206    typedef typename call_traits<second_type>::param_type      second_param_type;
207    typedef typename call_traits<first_type>::reference        first_reference;
208    typedef typename call_traits<second_type>::reference       second_reference;
209    typedef typename call_traits<first_type>::const_reference  first_const_reference;
210    typedef typename call_traits<second_type>::const_reference second_const_reference;
211
212             compressed_pair_2() : T1(), _second() {}
213             compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
214    template <class A>
215    explicit compressed_pair_2(const A& val)
216    {
217       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
218    }
219    compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
220       : T1(x.first()), _second(x.second()) {}
221
222 #if 0
223   compressed_pair_2& operator=(const compressed_pair_2& x) {
224     cout << "assigning compressed pair 2" << endl;
225     T1::operator=(x);
226     _second = x._second;
227     cout << "finished assigning compressed pair 2" << endl;
228     return *this;
229   }
230 #endif
231    first_reference       first()       { return *this; }
232    first_const_reference first() const { return *this; }
233
234    second_reference       second()       { return _second; }
235    second_const_reference second() const { return _second; }
236
237    void swap(compressed_pair_2& y)
238    {
239       // no need to swap empty base class:
240       using std::swap;
241       swap(_second, y._second);
242    }
243 };
244
245 // T1 != T2, both empty
246 template <class T1, class T2>
247 class compressed_pair_3 : T1, T2
248 {
249 public:
250    typedef T1                                                 first_type;
251    typedef T2                                                 second_type;
252    typedef typename call_traits<first_type>::param_type       first_param_type;
253    typedef typename call_traits<second_type>::param_type      second_param_type;
254    typedef typename call_traits<first_type>::reference        first_reference;
255    typedef typename call_traits<second_type>::reference       second_reference;
256    typedef typename call_traits<first_type>::const_reference  first_const_reference;
257    typedef typename call_traits<second_type>::const_reference second_const_reference;
258
259             compressed_pair_3() : T1(), T2() {}
260             compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
261    template <class A>
262    explicit compressed_pair_3(const A& val)
263    {
264       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
265    }
266    compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
267       : T1(x.first()), T2(x.second()) {}
268
269    first_reference       first()       { return *this; }
270    first_const_reference first() const { return *this; }
271
272    second_reference       second()       { return *this; }
273    second_const_reference second() const { return *this; }
274
275    void swap(compressed_pair_3& y)
276    {
277       // no need to swap empty base classes:
278    }
279 };
280
281 // T1 == T2, and empty
282 template <class T1, class T2>
283 class compressed_pair_4 : T1
284 {
285 public:
286    typedef T1                                                 first_type;
287    typedef T2                                                 second_type;
288    typedef typename call_traits<first_type>::param_type       first_param_type;
289    typedef typename call_traits<second_type>::param_type      second_param_type;
290    typedef typename call_traits<first_type>::reference        first_reference;
291    typedef typename call_traits<second_type>::reference       second_reference;
292    typedef typename call_traits<first_type>::const_reference  first_const_reference;
293    typedef typename call_traits<second_type>::const_reference second_const_reference;
294
295             compressed_pair_4() : T1() {}
296             compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
297    // only one single argument constructor since T1 == T2
298    explicit compressed_pair_4(first_param_type x) : T1(x) {}
299    compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
300       : T1(x.first()){}
301
302    first_reference       first()       { return *this; }
303    first_const_reference first() const { return *this; }
304
305    second_reference       second()       { return *this; }
306    second_const_reference second() const { return *this; }
307
308    void swap(compressed_pair_4& y)
309    {
310       // no need to swap empty base classes:
311    }
312 };
313
314 // T1 == T2, not empty
315 template <class T1, class T2>
316 class compressed_pair_5
317 {
318 private:
319    T1 _first;
320    T2 _second;
321 public:
322    typedef T1                                                 first_type;
323    typedef T2                                                 second_type;
324    typedef typename call_traits<first_type>::param_type       first_param_type;
325    typedef typename call_traits<second_type>::param_type      second_param_type;
326    typedef typename call_traits<first_type>::reference        first_reference;
327    typedef typename call_traits<second_type>::reference       second_reference;
328    typedef typename call_traits<first_type>::const_reference  first_const_reference;
329    typedef typename call_traits<second_type>::const_reference second_const_reference;
330
331             compressed_pair_5() : _first(), _second() {}
332             compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
333    // only one single argument constructor since T1 == T2
334    explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
335    compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c) 
336       : _first(c.first()), _second(c.second()) {}
337
338    first_reference       first()       { return _first; }
339    first_const_reference first() const { return _first; }
340
341    second_reference       second()       { return _second; }
342    second_const_reference second() const { return _second; }
343
344    void swap(compressed_pair_5& y)
345    {
346       using std::swap;
347       swap(_first, y._first);
348       swap(_second, y._second);
349    }
350 };
351
352 template <bool e1, bool e2, bool same>
353 struct compressed_pair_chooser
354 {
355    template <class T1, class T2>
356    struct rebind
357    {
358       typedef compressed_pair_0<T1, T2> type;
359    };
360 };
361
362 template <>
363 struct compressed_pair_chooser<false, true, false>
364 {
365    template <class T1, class T2>
366    struct rebind
367    {
368       typedef compressed_pair_1<T1, T2> type;
369    };
370 };
371
372 template <>
373 struct compressed_pair_chooser<true, false, false>
374 {
375    template <class T1, class T2>
376    struct rebind
377    {
378       typedef compressed_pair_2<T1, T2> type;
379    };
380 };
381
382 template <>
383 struct compressed_pair_chooser<true, true, false>
384 {
385    template <class T1, class T2>
386    struct rebind
387    {
388       typedef compressed_pair_3<T1, T2> type;
389    };
390 };
391
392 template <>
393 struct compressed_pair_chooser<true, true, true>
394 {
395    template <class T1, class T2>
396    struct rebind
397    {
398       typedef compressed_pair_4<T1, T2> type;
399    };
400 };
401
402 template <>
403 struct compressed_pair_chooser<false, false, true>
404 {
405    template <class T1, class T2>
406    struct rebind
407    {
408       typedef compressed_pair_5<T1, T2> type;
409    };
410 };
411
412 template <class T1, class T2>
413 struct compressed_pair_traits
414 {
415 private:
416    typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
417    typedef typename chooser::template rebind<T1, T2> bound_type;
418 public:
419    typedef typename bound_type::type type;
420 };
421
422 } // namespace detail
423
424 template <class T1, class T2>
425 class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
426 {
427 private:
428    typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
429 public:
430    typedef T1                                                 first_type;
431    typedef T2                                                 second_type;
432    typedef typename call_traits<first_type>::param_type       first_param_type;
433    typedef typename call_traits<second_type>::param_type      second_param_type;
434    typedef typename call_traits<first_type>::reference        first_reference;
435    typedef typename call_traits<second_type>::reference       second_reference;
436    typedef typename call_traits<first_type>::const_reference  first_const_reference;
437    typedef typename call_traits<second_type>::const_reference second_const_reference;
438
439             compressed_pair() : base_type() {}
440             compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
441    template <class A>
442    explicit compressed_pair(const A& x) : base_type(x){}
443
444    first_reference       first()       { return base_type::first(); }
445    first_const_reference first() const { return base_type::first(); }
446
447    second_reference       second()       { return base_type::second(); }
448    second_const_reference second() const { return base_type::second(); }
449 };
450
451 template <class T1, class T2>
452 inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
453 {
454    x.swap(y);
455 }
456
457 #else
458 // no partial specialisation, no member templates:
459
460 template <class T1, class T2>
461 class compressed_pair
462 {
463 private:
464    T1 _first;
465    T2 _second;
466 public:
467    typedef T1                                                 first_type;
468    typedef T2                                                 second_type;
469    typedef typename call_traits<first_type>::param_type       first_param_type;
470    typedef typename call_traits<second_type>::param_type      second_param_type;
471    typedef typename call_traits<first_type>::reference        first_reference;
472    typedef typename call_traits<second_type>::reference       second_reference;
473    typedef typename call_traits<first_type>::const_reference  first_const_reference;
474    typedef typename call_traits<second_type>::const_reference second_const_reference;
475
476             compressed_pair() : _first(), _second() {}
477             compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
478    explicit compressed_pair(first_param_type x) : _first(x), _second() {}
479    // can't define this in case T1 == T2:
480    // explicit compressed_pair(second_param_type y) : _first(), _second(y) {}
481
482    first_reference       first()       { return _first; }
483    first_const_reference first() const { return _first; }
484
485    second_reference       second()       { return _second; }
486    second_const_reference second() const { return _second; }
487
488    void swap(compressed_pair& y)
489    {
490       using std::swap;
491       swap(_first, y._first);
492       swap(_second, y._second);
493    }
494 };
495
496 template <class T1, class T2>
497 inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
498 {
499    x.swap(y);
500 }
501
502 #endif
503
504 } // boost
505
506 #endif // BOOST_OB_COMPRESSED_PAIR_HPP
507
508
509