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