]>
Commit | Line | Data |
---|---|---|
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 | first_reference first() { return _first; } | |
171 | first_const_reference first() const { return _first; } | |
172 | ||
173 | second_reference second() { return *this; } | |
174 | second_const_reference second() const { return *this; } | |
175 | ||
176 | void swap(compressed_pair_1& y) | |
177 | { | |
178 | // no need to swap empty base class: | |
179 | using std::swap; | |
180 | swap(_first, y._first); | |
181 | } | |
182 | }; | |
183 | ||
184 | // T1 != T2, T1 empty | |
185 | template <class T1, class T2> | |
186 | class compressed_pair_2 : T1 | |
187 | { | |
188 | private: | |
189 | T2 _second; | |
190 | public: | |
191 | typedef T1 first_type; | |
192 | typedef T2 second_type; | |
193 | typedef typename call_traits<first_type>::param_type first_param_type; | |
194 | typedef typename call_traits<second_type>::param_type second_param_type; | |
195 | typedef typename call_traits<first_type>::reference first_reference; | |
196 | typedef typename call_traits<second_type>::reference second_reference; | |
197 | typedef typename call_traits<first_type>::const_reference first_const_reference; | |
198 | typedef typename call_traits<second_type>::const_reference second_const_reference; | |
199 | ||
200 | compressed_pair_2() : T1(), _second() {} | |
201 | compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} | |
202 | template <class A> | |
203 | explicit compressed_pair_2(const A& val) | |
204 | { | |
205 | init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second); | |
206 | } | |
207 | compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x) | |
208 | : T1(x.first()), _second(x.second()) {} | |
209 | ||
210 | #if 0 | |
211 | compressed_pair_2& operator=(const compressed_pair_2& x) { | |
212 | cout << "assigning compressed pair 2" << endl; | |
213 | T1::operator=(x); | |
214 | _second = x._second; | |
215 | cout << "finished assigning compressed pair 2" << endl; | |
216 | return *this; | |
217 | } | |
218 | #endif | |
219 | first_reference first() { return *this; } | |
220 | first_const_reference first() const { return *this; } | |
221 | ||
222 | second_reference second() { return _second; } | |
223 | second_const_reference second() const { return _second; } | |
224 | ||
225 | void swap(compressed_pair_2& y) | |
226 | { | |
227 | // no need to swap empty base class: | |
228 | using std::swap; | |
229 | swap(_second, y._second); | |
230 | } | |
231 | }; | |
232 | ||
233 | // T1 != T2, both empty | |
234 | template <class T1, class T2> | |
235 | class compressed_pair_3 : T1, T2 | |
236 | { | |
237 | public: | |
238 | typedef T1 first_type; | |
239 | typedef T2 second_type; | |
240 | typedef typename call_traits<first_type>::param_type first_param_type; | |
241 | typedef typename call_traits<second_type>::param_type second_param_type; | |
242 | typedef typename call_traits<first_type>::reference first_reference; | |
243 | typedef typename call_traits<second_type>::reference second_reference; | |
244 | typedef typename call_traits<first_type>::const_reference first_const_reference; | |
245 | typedef typename call_traits<second_type>::const_reference second_const_reference; | |
246 | ||
247 | compressed_pair_3() : T1(), T2() {} | |
248 | compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} | |
249 | template <class A> | |
250 | explicit compressed_pair_3(const A& val) | |
251 | { | |
252 | init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this)); | |
253 | } | |
254 | compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x) | |
255 | : T1(x.first()), T2(x.second()) {} | |
256 | ||
257 | first_reference first() { return *this; } | |
258 | first_const_reference first() const { return *this; } | |
259 | ||
260 | second_reference second() { return *this; } | |
261 | second_const_reference second() const { return *this; } | |
262 | ||
263 | void swap(compressed_pair_3& y) | |
264 | { | |
265 | // no need to swap empty base classes: | |
266 | } | |
267 | }; | |
268 | ||
269 | // T1 == T2, and empty | |
270 | template <class T1, class T2> | |
271 | class compressed_pair_4 : T1 | |
272 | { | |
273 | public: | |
274 | typedef T1 first_type; | |
275 | typedef T2 second_type; | |
276 | typedef typename call_traits<first_type>::param_type first_param_type; | |
277 | typedef typename call_traits<second_type>::param_type second_param_type; | |
278 | typedef typename call_traits<first_type>::reference first_reference; | |
279 | typedef typename call_traits<second_type>::reference second_reference; | |
280 | typedef typename call_traits<first_type>::const_reference first_const_reference; | |
281 | typedef typename call_traits<second_type>::const_reference second_const_reference; | |
282 | ||
283 | compressed_pair_4() : T1() {} | |
284 | compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {} | |
285 | // only one single argument constructor since T1 == T2 | |
286 | explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {} | |
287 | compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x) | |
288 | : T1(x.first()), m_second(x.second()) {} | |
289 | ||
290 | first_reference first() { return *this; } | |
291 | first_const_reference first() const { return *this; } | |
292 | ||
293 | second_reference second() { return m_second; } | |
294 | second_const_reference second() const { return m_second; } | |
295 | ||
296 | void swap(compressed_pair_4& y) | |
297 | { | |
298 | // no need to swap empty base classes: | |
299 | } | |
300 | private: | |
301 | T2 m_second; | |
302 | }; | |
303 | ||
304 | // T1 == T2, not empty | |
305 | template <class T1, class T2> | |
306 | class compressed_pair_5 | |
307 | { | |
308 | private: | |
309 | T1 _first; | |
310 | T2 _second; | |
311 | public: | |
312 | typedef T1 first_type; | |
313 | typedef T2 second_type; | |
314 | typedef typename call_traits<first_type>::param_type first_param_type; | |
315 | typedef typename call_traits<second_type>::param_type second_param_type; | |
316 | typedef typename call_traits<first_type>::reference first_reference; | |
317 | typedef typename call_traits<second_type>::reference second_reference; | |
318 | typedef typename call_traits<first_type>::const_reference first_const_reference; | |
319 | typedef typename call_traits<second_type>::const_reference second_const_reference; | |
320 | ||
321 | compressed_pair_5() : _first(), _second() {} | |
322 | compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} | |
323 | // only one single argument constructor since T1 == T2 | |
324 | explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} | |
325 | compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c) | |
326 | : _first(c.first()), _second(c.second()) {} | |
327 | ||
328 | first_reference first() { return _first; } | |
329 | first_const_reference first() const { return _first; } | |
330 | ||
331 | second_reference second() { return _second; } | |
332 | second_const_reference second() const { return _second; } | |
333 | ||
334 | void swap(compressed_pair_5& y) | |
335 | { | |
336 | using std::swap; | |
337 | swap(_first, y._first); | |
338 | swap(_second, y._second); | |
339 | } | |
340 | }; | |
341 | ||
342 | template <bool e1, bool e2, bool same> | |
343 | struct compressed_pair_chooser | |
344 | { | |
345 | template <class T1, class T2> | |
346 | struct rebind | |
347 | { | |
348 | typedef compressed_pair_0<T1, T2> type; | |
349 | }; | |
350 | }; | |
351 | ||
352 | template <> | |
353 | struct compressed_pair_chooser<false, true, false> | |
354 | { | |
355 | template <class T1, class T2> | |
356 | struct rebind | |
357 | { | |
358 | typedef compressed_pair_1<T1, T2> type; | |
359 | }; | |
360 | }; | |
361 | ||
362 | template <> | |
363 | struct compressed_pair_chooser<true, false, false> | |
364 | { | |
365 | template <class T1, class T2> | |
366 | struct rebind | |
367 | { | |
368 | typedef compressed_pair_2<T1, T2> type; | |
369 | }; | |
370 | }; | |
371 | ||
372 | template <> | |
373 | struct compressed_pair_chooser<true, true, false> | |
374 | { | |
375 | template <class T1, class T2> | |
376 | struct rebind | |
377 | { | |
378 | typedef compressed_pair_3<T1, T2> type; | |
379 | }; | |
380 | }; | |
381 | ||
382 | template <> | |
383 | struct compressed_pair_chooser<true, true, true> | |
384 | { | |
385 | template <class T1, class T2> | |
386 | struct rebind | |
387 | { | |
388 | typedef compressed_pair_4<T1, T2> type; | |
389 | }; | |
390 | }; | |
391 | ||
392 | template <> | |
393 | struct compressed_pair_chooser<false, false, true> | |
394 | { | |
395 | template <class T1, class T2> | |
396 | struct rebind | |
397 | { | |
398 | typedef compressed_pair_5<T1, T2> type; | |
399 | }; | |
400 | }; | |
401 | ||
402 | template <class T1, class T2> | |
403 | struct compressed_pair_traits | |
404 | { | |
405 | private: | |
406 | typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser; | |
407 | typedef typename chooser::template rebind<T1, T2> bound_type; | |
408 | public: | |
409 | typedef typename bound_type::type type; | |
410 | }; | |
411 | ||
412 | } // namespace detail | |
413 | ||
414 | template <class T1, class T2> | |
415 | class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type | |
416 | { | |
417 | private: | |
418 | typedef typename detail::compressed_pair_traits<T1, T2>::type base_type; | |
419 | public: | |
420 | typedef T1 first_type; | |
421 | typedef T2 second_type; | |
422 | typedef typename call_traits<first_type>::param_type first_param_type; | |
423 | typedef typename call_traits<second_type>::param_type second_param_type; | |
424 | typedef typename call_traits<first_type>::reference first_reference; | |
425 | typedef typename call_traits<second_type>::reference second_reference; | |
426 | typedef typename call_traits<first_type>::const_reference first_const_reference; | |
427 | typedef typename call_traits<second_type>::const_reference second_const_reference; | |
428 | ||
429 | compressed_pair() : base_type() {} | |
430 | compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} | |
431 | template <class A> | |
432 | explicit compressed_pair(const A& x) : base_type(x){} | |
433 | ||
434 | first_reference first() { return base_type::first(); } | |
435 | first_const_reference first() const { return base_type::first(); } | |
436 | ||
437 | second_reference second() { return base_type::second(); } | |
438 | second_const_reference second() const { return base_type::second(); } | |
439 | }; | |
440 | ||
441 | template <class T1, class T2> | |
442 | inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | |
443 | { | |
444 | x.swap(y); | |
445 | } | |
446 | ||
447 | #else | |
448 | // no partial specialisation, no member templates: | |
449 | ||
450 | template <class T1, class T2> | |
451 | class compressed_pair | |
452 | { | |
453 | private: | |
454 | T1 _first; | |
455 | T2 _second; | |
456 | public: | |
457 | typedef T1 first_type; | |
458 | typedef T2 second_type; | |
459 | typedef typename call_traits<first_type>::param_type first_param_type; | |
460 | typedef typename call_traits<second_type>::param_type second_param_type; | |
461 | typedef typename call_traits<first_type>::reference first_reference; | |
462 | typedef typename call_traits<second_type>::reference second_reference; | |
463 | typedef typename call_traits<first_type>::const_reference first_const_reference; | |
464 | typedef typename call_traits<second_type>::const_reference second_const_reference; | |
465 | ||
466 | compressed_pair() : _first(), _second() {} | |
467 | compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {} | |
468 | explicit compressed_pair(first_param_type x) : _first(x), _second() {} | |
469 | // can't define this in case T1 == T2: | |
470 | // explicit compressed_pair(second_param_type y) : _first(), _second(y) {} | |
471 | ||
472 | first_reference first() { return _first; } | |
473 | first_const_reference first() const { return _first; } | |
474 | ||
475 | second_reference second() { return _second; } | |
476 | second_const_reference second() const { return _second; } | |
477 | ||
478 | void swap(compressed_pair& y) | |
479 | { | |
480 | using std::swap; | |
481 | swap(_first, y._first); | |
482 | swap(_second, y._second); | |
483 | } | |
484 | }; | |
485 | ||
486 | template <class T1, class T2> | |
487 | inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | |
488 | { | |
489 | x.swap(y); | |
490 | } | |
491 | ||
492 | #endif | |
493 | ||
494 | } // boost | |
495 | ||
496 | #endif // BOOST_OB_COMPRESSED_PAIR_HPP | |
497 | ||
498 | ||
499 |