fix doc example typo
[boost.git] / boost / detail / ob_compressed_pair.hpp
blob727acab6da498aa212c3c7d20057f9f661e7063d
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.
24 #ifndef BOOST_OB_COMPRESSED_PAIR_HPP
25 #define BOOST_OB_COMPRESSED_PAIR_HPP
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
38 namespace boost
40 #ifdef BOOST_MSVC6_MEMBER_TEMPLATES
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:
50 template <class T1, class T2>
51 class compressed_pair;
53 namespace detail{
55 template <class A, class T1, class T2>
56 struct best_conversion_traits
58 typedef char one;
59 typedef char (&two)[2];
60 static A a;
61 static one test(T1);
62 static two test(T2);
64 enum { value = sizeof(test(a)) };
67 template <int>
68 struct init_one;
70 template <>
71 struct init_one<1>
73 template <class A, class T1, class T2>
74 static void init(const A& a, T1* p1, T2*)
76 *p1 = a;
80 template <>
81 struct init_one<2>
83 template <class A, class T1, class T2>
84 static void init(const A& a, T1*, T2* p2)
86 *p2 = a;
91 // T1 != T2, both non-empty
92 template <class T1, class T2>
93 class compressed_pair_0
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;
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)
113 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
115 compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
116 : _first(x.first()), _second(x.second()) {}
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;
126 #endif
128 first_reference first() { return _first; }
129 first_const_reference first() const { return _first; }
131 second_reference second() { return _second; }
132 second_const_reference second() const { return _second; }
134 void swap(compressed_pair_0& y)
136 using std::swap;
137 swap(_first, y._first);
138 swap(_second, y._second);
142 // T1 != T2, T2 empty
143 template <class T1, class T2>
144 class compressed_pair_1 : T2
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;
158 compressed_pair_1() : T2(), _first() {}
159 compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
161 template <class A>
162 explicit compressed_pair_1(const A& val)
164 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
167 compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
168 : T2(x.second()), _first(x.first()) {}
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;
179 #endif
181 first_reference first() { return _first; }
182 first_const_reference first() const { return _first; }
184 second_reference second() { return *this; }
185 second_const_reference second() const { return *this; }
187 void swap(compressed_pair_1& y)
189 // no need to swap empty base class:
190 using std::swap;
191 swap(_first, y._first);
195 // T1 != T2, T1 empty
196 template <class T1, class T2>
197 class compressed_pair_2 : T1
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;
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)
216 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
218 compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
219 : T1(x.first()), _second(x.second()) {}
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;
229 #endif
230 first_reference first() { return *this; }
231 first_const_reference first() const { return *this; }
233 second_reference second() { return _second; }
234 second_const_reference second() const { return _second; }
236 void swap(compressed_pair_2& y)
238 // no need to swap empty base class:
239 using std::swap;
240 swap(_second, y._second);
244 // T1 != T2, both empty
245 template <class T1, class T2>
246 class compressed_pair_3 : T1, T2
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;
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)
263 init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
265 compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
266 : T1(x.first()), T2(x.second()) {}
268 first_reference first() { return *this; }
269 first_const_reference first() const { return *this; }
271 second_reference second() { return *this; }
272 second_const_reference second() const { return *this; }
274 void swap(compressed_pair_3& y)
276 // no need to swap empty base classes:
280 // T1 == T2, and empty
281 template <class T1, class T2>
282 class compressed_pair_4 : T1
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;
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()) {}
301 first_reference first() { return *this; }
302 first_const_reference first() const { return *this; }
304 second_reference second() { return m_second; }
305 second_const_reference second() const { return m_second; }
307 void swap(compressed_pair_4& y)
309 // no need to swap empty base classes:
311 private:
312 T2 m_second;
315 // T1 == T2, not empty
316 template <class T1, class T2>
317 class compressed_pair_5
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;
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()) {}
339 first_reference first() { return _first; }
340 first_const_reference first() const { return _first; }
342 second_reference second() { return _second; }
343 second_const_reference second() const { return _second; }
345 void swap(compressed_pair_5& y)
347 using std::swap;
348 swap(_first, y._first);
349 swap(_second, y._second);
353 template <bool e1, bool e2, bool same>
354 struct compressed_pair_chooser
356 template <class T1, class T2>
357 struct rebind
359 typedef compressed_pair_0<T1, T2> type;
363 template <>
364 struct compressed_pair_chooser<false, true, false>
366 template <class T1, class T2>
367 struct rebind
369 typedef compressed_pair_1<T1, T2> type;
373 template <>
374 struct compressed_pair_chooser<true, false, false>
376 template <class T1, class T2>
377 struct rebind
379 typedef compressed_pair_2<T1, T2> type;
383 template <>
384 struct compressed_pair_chooser<true, true, false>
386 template <class T1, class T2>
387 struct rebind
389 typedef compressed_pair_3<T1, T2> type;
393 template <>
394 struct compressed_pair_chooser<true, true, true>
396 template <class T1, class T2>
397 struct rebind
399 typedef compressed_pair_4<T1, T2> type;
403 template <>
404 struct compressed_pair_chooser<false, false, true>
406 template <class T1, class T2>
407 struct rebind
409 typedef compressed_pair_5<T1, T2> type;
413 template <class T1, class T2>
414 struct compressed_pair_traits
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;
423 } // namespace detail
425 template <class T1, class T2>
426 class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
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;
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){}
445 first_reference first() { return base_type::first(); }
446 first_const_reference first() const { return base_type::first(); }
448 second_reference second() { return base_type::second(); }
449 second_const_reference second() const { return base_type::second(); }
452 template <class T1, class T2>
453 inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
455 x.swap(y);
458 #else
459 // no partial specialisation, no member templates:
461 template <class T1, class T2>
462 class compressed_pair
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;
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) {}
483 first_reference first() { return _first; }
484 first_const_reference first() const { return _first; }
486 second_reference second() { return _second; }
487 second_const_reference second() const { return _second; }
489 void swap(compressed_pair& y)
491 using std::swap;
492 swap(_first, y._first);
493 swap(_second, y._second);
497 template <class T1, class T2>
498 inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
500 x.swap(y);
503 #endif
505 } // boost
507 #endif // BOOST_OB_COMPRESSED_PAIR_HPP