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