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