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

Revision 857, 16.9 KB checked in by igarcia, 19 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//  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
38namespace 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
50template <class T1, class T2>
51class compressed_pair;
52
53namespace detail{
54
55template <class A, class T1, class T2>
56struct 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
67template <int>
68struct init_one;
69
70template <>
71struct 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
80template <>
81struct 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
92template <class T1, class T2>
93class compressed_pair_0
94{
95private:
96   T1 _first;
97   T2 _second;
98public:
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
143template <class T1, class T2>
144class compressed_pair_1 : T2
145{
146private:
147   T1 _first;
148public:
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
196template <class T1, class T2>
197class compressed_pair_2 : T1
198{
199private:
200   T2 _second;
201public:
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
245template <class T1, class T2>
246class compressed_pair_3 : T1, T2
247{
248public:
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
281template <class T1, class T2>
282class compressed_pair_4 : T1
283{
284public:
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   }
311private:
312   T2 m_second;
313};
314
315// T1 == T2, not empty
316template <class T1, class T2>
317class compressed_pair_5
318{
319private:
320   T1 _first;
321   T2 _second;
322public:
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
353template <bool e1, bool e2, bool same>
354struct 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
363template <>
364struct 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
373template <>
374struct 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
383template <>
384struct 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
393template <>
394struct 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
403template <>
404struct 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
413template <class T1, class T2>
414struct compressed_pair_traits
415{
416private:
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;
419public:
420   typedef typename bound_type::type type;
421};
422
423} // namespace detail
424
425template <class T1, class T2>
426class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
427{
428private:
429   typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
430public:
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
452template <class T1, class T2>
453inline 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
461template <class T1, class T2>
462class compressed_pair
463{
464private:
465   T1 _first;
466   T2 _second;
467public:
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
497template <class T1, class T2>
498inline 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
Note: See TracBrowser for help on using the repository browser.