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