|
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 |
|
8 // compressed_pair: pair that "compresses" empty members |
|
9 // (see libs/utility/compressed_pair.htm) |
|
10 // |
|
11 // JM changes 25 Jan 2004: |
|
12 // For the case where T1 == T2 and both are empty, then first() and second() |
|
13 // should return different objects. |
|
14 // JM changes 25 Jan 2000: |
|
15 // Removed default arguments from compressed_pair_switch to get |
|
16 // C++ Builder 4 to accept them |
|
17 // rewriten swap to get gcc and C++ builder to compile. |
|
18 // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. |
|
19 |
|
20 #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP |
|
21 #define BOOST_DETAIL_COMPRESSED_PAIR_HPP |
|
22 |
|
23 #include <algorithm> |
|
24 |
|
25 #include <boost/type_traits/remove_cv.hpp> |
|
26 #include <boost/type_traits/is_empty.hpp> |
|
27 #include <boost/type_traits/is_same.hpp> |
|
28 #include <boost/call_traits.hpp> |
|
29 |
|
30 #ifdef BOOST_MSVC |
|
31 # pragma warning(push) |
|
32 # pragma warning(disable:4512) |
|
33 #endif |
|
34 namespace boost |
|
35 { |
|
36 |
|
37 template <class T1, class T2> |
|
38 class compressed_pair; |
|
39 |
|
40 |
|
41 // compressed_pair |
|
42 |
|
43 namespace details |
|
44 { |
|
45 // JM altered 26 Jan 2000: |
|
46 template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty> |
|
47 struct compressed_pair_switch; |
|
48 |
|
49 template <class T1, class T2> |
|
50 struct compressed_pair_switch<T1, T2, false, false, false> |
|
51 {static const int value = 0;}; |
|
52 |
|
53 template <class T1, class T2> |
|
54 struct compressed_pair_switch<T1, T2, false, true, true> |
|
55 {static const int value = 3;}; |
|
56 |
|
57 template <class T1, class T2> |
|
58 struct compressed_pair_switch<T1, T2, false, true, false> |
|
59 {static const int value = 1;}; |
|
60 |
|
61 template <class T1, class T2> |
|
62 struct compressed_pair_switch<T1, T2, false, false, true> |
|
63 {static const int value = 2;}; |
|
64 |
|
65 template <class T1, class T2> |
|
66 struct compressed_pair_switch<T1, T2, true, true, true> |
|
67 {static const int value = 4;}; |
|
68 |
|
69 template <class T1, class T2> |
|
70 struct compressed_pair_switch<T1, T2, true, false, false> |
|
71 {static const int value = 5;}; |
|
72 |
|
73 template <class T1, class T2, int Version> class compressed_pair_imp; |
|
74 |
|
75 #ifdef __GNUC__ |
|
76 // workaround for GCC (JM): |
|
77 using std::swap; |
|
78 #endif |
|
79 // |
|
80 // can't call unqualified swap from within classname::swap |
|
81 // as Koenig lookup rules will find only the classname::swap |
|
82 // member function not the global declaration, so use cp_swap |
|
83 // as a forwarding function (JM): |
|
84 template <typename T> |
|
85 inline void cp_swap(T& t1, T& t2) |
|
86 { |
|
87 #ifndef __GNUC__ |
|
88 using std::swap; |
|
89 #endif |
|
90 swap(t1, t2); |
|
91 } |
|
92 |
|
93 // 0 derive from neither |
|
94 |
|
95 template <class T1, class T2> |
|
96 class compressed_pair_imp<T1, T2, 0> |
|
97 { |
|
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_imp() {} |
|
109 |
|
110 compressed_pair_imp(first_param_type x, second_param_type y) |
|
111 : first_(x), second_(y) {} |
|
112 |
|
113 compressed_pair_imp(first_param_type x) |
|
114 : first_(x) {} |
|
115 |
|
116 compressed_pair_imp(second_param_type y) |
|
117 : second_(y) {} |
|
118 |
|
119 first_reference first() {return first_;} |
|
120 first_const_reference first() const {return first_;} |
|
121 |
|
122 second_reference second() {return second_;} |
|
123 second_const_reference second() const {return second_;} |
|
124 |
|
125 void swap(::boost::compressed_pair<T1, T2>& y) |
|
126 { |
|
127 cp_swap(first_, y.first()); |
|
128 cp_swap(second_, y.second()); |
|
129 } |
|
130 private: |
|
131 first_type first_; |
|
132 second_type second_; |
|
133 }; |
|
134 |
|
135 // 1 derive from T1 |
|
136 |
|
137 template <class T1, class T2> |
|
138 class compressed_pair_imp<T1, T2, 1> |
|
139 : protected ::boost::remove_cv<T1>::type |
|
140 { |
|
141 public: |
|
142 typedef T1 first_type; |
|
143 typedef T2 second_type; |
|
144 typedef typename call_traits<first_type>::param_type first_param_type; |
|
145 typedef typename call_traits<second_type>::param_type second_param_type; |
|
146 typedef typename call_traits<first_type>::reference first_reference; |
|
147 typedef typename call_traits<second_type>::reference second_reference; |
|
148 typedef typename call_traits<first_type>::const_reference first_const_reference; |
|
149 typedef typename call_traits<second_type>::const_reference second_const_reference; |
|
150 |
|
151 compressed_pair_imp() {} |
|
152 |
|
153 compressed_pair_imp(first_param_type x, second_param_type y) |
|
154 : first_type(x), second_(y) {} |
|
155 |
|
156 compressed_pair_imp(first_param_type x) |
|
157 : first_type(x) {} |
|
158 |
|
159 compressed_pair_imp(second_param_type y) |
|
160 : second_(y) {} |
|
161 |
|
162 first_reference first() {return *this;} |
|
163 first_const_reference first() const {return *this;} |
|
164 |
|
165 second_reference second() {return second_;} |
|
166 second_const_reference second() const {return second_;} |
|
167 |
|
168 void swap(::boost::compressed_pair<T1,T2>& y) |
|
169 { |
|
170 // no need to swap empty base class: |
|
171 cp_swap(second_, y.second()); |
|
172 } |
|
173 private: |
|
174 second_type second_; |
|
175 }; |
|
176 |
|
177 // 2 derive from T2 |
|
178 |
|
179 template <class T1, class T2> |
|
180 class compressed_pair_imp<T1, T2, 2> |
|
181 : protected ::boost::remove_cv<T2>::type |
|
182 { |
|
183 public: |
|
184 typedef T1 first_type; |
|
185 typedef T2 second_type; |
|
186 typedef typename call_traits<first_type>::param_type first_param_type; |
|
187 typedef typename call_traits<second_type>::param_type second_param_type; |
|
188 typedef typename call_traits<first_type>::reference first_reference; |
|
189 typedef typename call_traits<second_type>::reference second_reference; |
|
190 typedef typename call_traits<first_type>::const_reference first_const_reference; |
|
191 typedef typename call_traits<second_type>::const_reference second_const_reference; |
|
192 |
|
193 compressed_pair_imp() {} |
|
194 |
|
195 compressed_pair_imp(first_param_type x, second_param_type y) |
|
196 : second_type(y), first_(x) {} |
|
197 |
|
198 compressed_pair_imp(first_param_type x) |
|
199 : first_(x) {} |
|
200 |
|
201 compressed_pair_imp(second_param_type y) |
|
202 : second_type(y) {} |
|
203 |
|
204 first_reference first() {return first_;} |
|
205 first_const_reference first() const {return first_;} |
|
206 |
|
207 second_reference second() {return *this;} |
|
208 second_const_reference second() const {return *this;} |
|
209 |
|
210 void swap(::boost::compressed_pair<T1,T2>& y) |
|
211 { |
|
212 // no need to swap empty base class: |
|
213 cp_swap(first_, y.first()); |
|
214 } |
|
215 |
|
216 private: |
|
217 first_type first_; |
|
218 }; |
|
219 |
|
220 // 3 derive from T1 and T2 |
|
221 |
|
222 template <class T1, class T2> |
|
223 class compressed_pair_imp<T1, T2, 3> |
|
224 : protected ::boost::remove_cv<T1>::type, |
|
225 protected ::boost::remove_cv<T2>::type |
|
226 { |
|
227 public: |
|
228 typedef T1 first_type; |
|
229 typedef T2 second_type; |
|
230 typedef typename call_traits<first_type>::param_type first_param_type; |
|
231 typedef typename call_traits<second_type>::param_type second_param_type; |
|
232 typedef typename call_traits<first_type>::reference first_reference; |
|
233 typedef typename call_traits<second_type>::reference second_reference; |
|
234 typedef typename call_traits<first_type>::const_reference first_const_reference; |
|
235 typedef typename call_traits<second_type>::const_reference second_const_reference; |
|
236 |
|
237 compressed_pair_imp() {} |
|
238 |
|
239 compressed_pair_imp(first_param_type x, second_param_type y) |
|
240 : first_type(x), second_type(y) {} |
|
241 |
|
242 compressed_pair_imp(first_param_type x) |
|
243 : first_type(x) {} |
|
244 |
|
245 compressed_pair_imp(second_param_type y) |
|
246 : second_type(y) {} |
|
247 |
|
248 first_reference first() {return *this;} |
|
249 first_const_reference first() const {return *this;} |
|
250 |
|
251 second_reference second() {return *this;} |
|
252 second_const_reference second() const {return *this;} |
|
253 // |
|
254 // no need to swap empty bases: |
|
255 void swap(::boost::compressed_pair<T1,T2>&) {} |
|
256 }; |
|
257 |
|
258 // JM |
|
259 // 4 T1 == T2, T1 and T2 both empty |
|
260 // Originally this did not store an instance of T2 at all |
|
261 // but that led to problems beause it meant &x.first() == &x.second() |
|
262 // which is not true for any other kind of pair, so now we store an instance |
|
263 // of T2 just in case the user is relying on first() and second() returning |
|
264 // different objects (albeit both empty). |
|
265 template <class T1, class T2> |
|
266 class compressed_pair_imp<T1, T2, 4> |
|
267 : protected ::boost::remove_cv<T1>::type |
|
268 { |
|
269 public: |
|
270 typedef T1 first_type; |
|
271 typedef T2 second_type; |
|
272 typedef typename call_traits<first_type>::param_type first_param_type; |
|
273 typedef typename call_traits<second_type>::param_type second_param_type; |
|
274 typedef typename call_traits<first_type>::reference first_reference; |
|
275 typedef typename call_traits<second_type>::reference second_reference; |
|
276 typedef typename call_traits<first_type>::const_reference first_const_reference; |
|
277 typedef typename call_traits<second_type>::const_reference second_const_reference; |
|
278 |
|
279 compressed_pair_imp() {} |
|
280 |
|
281 compressed_pair_imp(first_param_type x, second_param_type y) |
|
282 : first_type(x), m_second(y) {} |
|
283 |
|
284 compressed_pair_imp(first_param_type x) |
|
285 : first_type(x), m_second(x) {} |
|
286 |
|
287 first_reference first() {return *this;} |
|
288 first_const_reference first() const {return *this;} |
|
289 |
|
290 second_reference second() {return m_second;} |
|
291 second_const_reference second() const {return m_second;} |
|
292 |
|
293 void swap(::boost::compressed_pair<T1,T2>&) {} |
|
294 private: |
|
295 T2 m_second; |
|
296 }; |
|
297 |
|
298 // 5 T1 == T2 and are not empty: //JM |
|
299 |
|
300 template <class T1, class T2> |
|
301 class compressed_pair_imp<T1, T2, 5> |
|
302 { |
|
303 public: |
|
304 typedef T1 first_type; |
|
305 typedef T2 second_type; |
|
306 typedef typename call_traits<first_type>::param_type first_param_type; |
|
307 typedef typename call_traits<second_type>::param_type second_param_type; |
|
308 typedef typename call_traits<first_type>::reference first_reference; |
|
309 typedef typename call_traits<second_type>::reference second_reference; |
|
310 typedef typename call_traits<first_type>::const_reference first_const_reference; |
|
311 typedef typename call_traits<second_type>::const_reference second_const_reference; |
|
312 |
|
313 compressed_pair_imp() {} |
|
314 |
|
315 compressed_pair_imp(first_param_type x, second_param_type y) |
|
316 : first_(x), second_(y) {} |
|
317 |
|
318 compressed_pair_imp(first_param_type x) |
|
319 : first_(x), second_(x) {} |
|
320 |
|
321 first_reference first() {return first_;} |
|
322 first_const_reference first() const {return first_;} |
|
323 |
|
324 second_reference second() {return second_;} |
|
325 second_const_reference second() const {return second_;} |
|
326 |
|
327 void swap(::boost::compressed_pair<T1, T2>& y) |
|
328 { |
|
329 cp_swap(first_, y.first()); |
|
330 cp_swap(second_, y.second()); |
|
331 } |
|
332 private: |
|
333 first_type first_; |
|
334 second_type second_; |
|
335 }; |
|
336 |
|
337 } // details |
|
338 |
|
339 template <class T1, class T2> |
|
340 class compressed_pair |
|
341 : private ::boost::details::compressed_pair_imp<T1, T2, |
|
342 ::boost::details::compressed_pair_switch< |
|
343 T1, |
|
344 T2, |
|
345 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, |
|
346 ::boost::is_empty<T1>::value, |
|
347 ::boost::is_empty<T2>::value>::value> |
|
348 { |
|
349 private: |
|
350 typedef details::compressed_pair_imp<T1, T2, |
|
351 ::boost::details::compressed_pair_switch< |
|
352 T1, |
|
353 T2, |
|
354 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, |
|
355 ::boost::is_empty<T1>::value, |
|
356 ::boost::is_empty<T2>::value>::value> base; |
|
357 public: |
|
358 typedef T1 first_type; |
|
359 typedef T2 second_type; |
|
360 typedef typename call_traits<first_type>::param_type first_param_type; |
|
361 typedef typename call_traits<second_type>::param_type second_param_type; |
|
362 typedef typename call_traits<first_type>::reference first_reference; |
|
363 typedef typename call_traits<second_type>::reference second_reference; |
|
364 typedef typename call_traits<first_type>::const_reference first_const_reference; |
|
365 typedef typename call_traits<second_type>::const_reference second_const_reference; |
|
366 |
|
367 compressed_pair() : base() {} |
|
368 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} |
|
369 explicit compressed_pair(first_param_type x) : base(x) {} |
|
370 explicit compressed_pair(second_param_type y) : base(y) {} |
|
371 |
|
372 first_reference first() {return base::first();} |
|
373 first_const_reference first() const {return base::first();} |
|
374 |
|
375 second_reference second() {return base::second();} |
|
376 second_const_reference second() const {return base::second();} |
|
377 |
|
378 void swap(compressed_pair& y) { base::swap(y); } |
|
379 }; |
|
380 |
|
381 // JM |
|
382 // Partial specialisation for case where T1 == T2: |
|
383 // |
|
384 template <class T> |
|
385 class compressed_pair<T, T> |
|
386 : private details::compressed_pair_imp<T, T, |
|
387 ::boost::details::compressed_pair_switch< |
|
388 T, |
|
389 T, |
|
390 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value, |
|
391 ::boost::is_empty<T>::value, |
|
392 ::boost::is_empty<T>::value>::value> |
|
393 { |
|
394 private: |
|
395 typedef details::compressed_pair_imp<T, T, |
|
396 ::boost::details::compressed_pair_switch< |
|
397 T, |
|
398 T, |
|
399 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value, |
|
400 ::boost::is_empty<T>::value, |
|
401 ::boost::is_empty<T>::value>::value> base; |
|
402 public: |
|
403 typedef T first_type; |
|
404 typedef T second_type; |
|
405 typedef typename call_traits<first_type>::param_type first_param_type; |
|
406 typedef typename call_traits<second_type>::param_type second_param_type; |
|
407 typedef typename call_traits<first_type>::reference first_reference; |
|
408 typedef typename call_traits<second_type>::reference second_reference; |
|
409 typedef typename call_traits<first_type>::const_reference first_const_reference; |
|
410 typedef typename call_traits<second_type>::const_reference second_const_reference; |
|
411 |
|
412 compressed_pair() : base() {} |
|
413 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} |
|
414 #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) |
|
415 explicit |
|
416 #endif |
|
417 compressed_pair(first_param_type x) : base(x) {} |
|
418 |
|
419 first_reference first() {return base::first();} |
|
420 first_const_reference first() const {return base::first();} |
|
421 |
|
422 second_reference second() {return base::second();} |
|
423 second_const_reference second() const {return base::second();} |
|
424 |
|
425 void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); } |
|
426 }; |
|
427 |
|
428 template <class T1, class T2> |
|
429 inline |
|
430 void |
|
431 swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) |
|
432 { |
|
433 x.swap(y); |
|
434 } |
|
435 |
|
436 } // boost |
|
437 |
|
438 #ifdef BOOST_MSVC |
|
439 # pragma warning(pop) |
|
440 #endif |
|
441 |
|
442 #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP |
|
443 |