1 // (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
\r
2 // Use, modification and distribution are subject to the Boost Software License,
\r
3 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
\r
4 // http://www.boost.org/LICENSE_1_0.txt).
\r
6 // See http://www.boost.org/libs/utility for most recent version including documentation.
\r
8 // compressed_pair: pair that "compresses" empty members
\r
9 // (see libs/utility/compressed_pair.htm)
\r
11 // JM changes 25 Jan 2004:
\r
12 // For the case where T1 == T2 and both are empty, then first() and second()
\r
13 // should return different objects.
\r
14 // JM changes 25 Jan 2000:
\r
15 // Removed default arguments from compressed_pair_switch to get
\r
16 // C++ Builder 4 to accept them
\r
17 // rewriten swap to get gcc and C++ builder to compile.
\r
18 // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
\r
20 #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
\r
21 #define BOOST_DETAIL_COMPRESSED_PAIR_HPP
\r
23 #include <algorithm>
\r
25 #include <boost/type_traits/remove_cv.hpp>
\r
26 #include <boost/type_traits/is_empty.hpp>
\r
27 #include <boost/type_traits/is_same.hpp>
\r
28 #include <boost/call_traits.hpp>
\r
31 # pragma warning(push)
\r
32 # pragma warning(disable:4512)
\r
37 template <class T1, class T2>
\r
38 class compressed_pair;
\r
45 // JM altered 26 Jan 2000:
\r
46 template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
\r
47 struct compressed_pair_switch;
\r
49 template <class T1, class T2>
\r
50 struct compressed_pair_switch<T1, T2, false, false, false>
\r
51 {static const int value = 0;};
\r
53 template <class T1, class T2>
\r
54 struct compressed_pair_switch<T1, T2, false, true, true>
\r
55 {static const int value = 3;};
\r
57 template <class T1, class T2>
\r
58 struct compressed_pair_switch<T1, T2, false, true, false>
\r
59 {static const int value = 1;};
\r
61 template <class T1, class T2>
\r
62 struct compressed_pair_switch<T1, T2, false, false, true>
\r
63 {static const int value = 2;};
\r
65 template <class T1, class T2>
\r
66 struct compressed_pair_switch<T1, T2, true, true, true>
\r
67 {static const int value = 4;};
\r
69 template <class T1, class T2>
\r
70 struct compressed_pair_switch<T1, T2, true, false, false>
\r
71 {static const int value = 5;};
\r
73 template <class T1, class T2, int Version> class compressed_pair_imp;
\r
76 // workaround for GCC (JM):
\r
80 // can't call unqualified swap from within classname::swap
\r
81 // as Koenig lookup rules will find only the classname::swap
\r
82 // member function not the global declaration, so use cp_swap
\r
83 // as a forwarding function (JM):
\r
84 template <typename T>
\r
85 inline void cp_swap(T& t1, T& t2)
\r
93 // 0 derive from neither
\r
95 template <class T1, class T2>
\r
96 class compressed_pair_imp<T1, T2, 0>
\r
99 typedef T1 first_type;
\r
100 typedef T2 second_type;
\r
101 typedef typename call_traits<first_type>::param_type first_param_type;
\r
102 typedef typename call_traits<second_type>::param_type second_param_type;
\r
103 typedef typename call_traits<first_type>::reference first_reference;
\r
104 typedef typename call_traits<second_type>::reference second_reference;
\r
105 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
106 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
108 compressed_pair_imp() {}
\r
110 compressed_pair_imp(first_param_type x, second_param_type y)
\r
111 : first_(x), second_(y) {}
\r
113 compressed_pair_imp(first_param_type x)
\r
116 compressed_pair_imp(second_param_type y)
\r
119 first_reference first() {return first_;}
\r
120 first_const_reference first() const {return first_;}
\r
122 second_reference second() {return second_;}
\r
123 second_const_reference second() const {return second_;}
\r
125 void swap(::boost::compressed_pair<T1, T2>& y)
\r
127 cp_swap(first_, y.first());
\r
128 cp_swap(second_, y.second());
\r
132 second_type second_;
\r
135 // 1 derive from T1
\r
137 template <class T1, class T2>
\r
138 class compressed_pair_imp<T1, T2, 1>
\r
139 : protected ::boost::remove_cv<T1>::type
\r
142 typedef T1 first_type;
\r
143 typedef T2 second_type;
\r
144 typedef typename call_traits<first_type>::param_type first_param_type;
\r
145 typedef typename call_traits<second_type>::param_type second_param_type;
\r
146 typedef typename call_traits<first_type>::reference first_reference;
\r
147 typedef typename call_traits<second_type>::reference second_reference;
\r
148 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
149 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
151 compressed_pair_imp() {}
\r
153 compressed_pair_imp(first_param_type x, second_param_type y)
\r
154 : first_type(x), second_(y) {}
\r
156 compressed_pair_imp(first_param_type x)
\r
159 compressed_pair_imp(second_param_type y)
\r
162 first_reference first() {return *this;}
\r
163 first_const_reference first() const {return *this;}
\r
165 second_reference second() {return second_;}
\r
166 second_const_reference second() const {return second_;}
\r
168 void swap(::boost::compressed_pair<T1,T2>& y)
\r
170 // no need to swap empty base class:
\r
171 cp_swap(second_, y.second());
\r
174 second_type second_;
\r
177 // 2 derive from T2
\r
179 template <class T1, class T2>
\r
180 class compressed_pair_imp<T1, T2, 2>
\r
181 : protected ::boost::remove_cv<T2>::type
\r
184 typedef T1 first_type;
\r
185 typedef T2 second_type;
\r
186 typedef typename call_traits<first_type>::param_type first_param_type;
\r
187 typedef typename call_traits<second_type>::param_type second_param_type;
\r
188 typedef typename call_traits<first_type>::reference first_reference;
\r
189 typedef typename call_traits<second_type>::reference second_reference;
\r
190 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
191 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
193 compressed_pair_imp() {}
\r
195 compressed_pair_imp(first_param_type x, second_param_type y)
\r
196 : second_type(y), first_(x) {}
\r
198 compressed_pair_imp(first_param_type x)
\r
201 compressed_pair_imp(second_param_type y)
\r
202 : second_type(y) {}
\r
204 first_reference first() {return first_;}
\r
205 first_const_reference first() const {return first_;}
\r
207 second_reference second() {return *this;}
\r
208 second_const_reference second() const {return *this;}
\r
210 void swap(::boost::compressed_pair<T1,T2>& y)
\r
212 // no need to swap empty base class:
\r
213 cp_swap(first_, y.first());
\r
220 // 3 derive from T1 and T2
\r
222 template <class T1, class T2>
\r
223 class compressed_pair_imp<T1, T2, 3>
\r
224 : protected ::boost::remove_cv<T1>::type,
\r
225 protected ::boost::remove_cv<T2>::type
\r
228 typedef T1 first_type;
\r
229 typedef T2 second_type;
\r
230 typedef typename call_traits<first_type>::param_type first_param_type;
\r
231 typedef typename call_traits<second_type>::param_type second_param_type;
\r
232 typedef typename call_traits<first_type>::reference first_reference;
\r
233 typedef typename call_traits<second_type>::reference second_reference;
\r
234 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
235 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
237 compressed_pair_imp() {}
\r
239 compressed_pair_imp(first_param_type x, second_param_type y)
\r
240 : first_type(x), second_type(y) {}
\r
242 compressed_pair_imp(first_param_type x)
\r
245 compressed_pair_imp(second_param_type y)
\r
246 : second_type(y) {}
\r
248 first_reference first() {return *this;}
\r
249 first_const_reference first() const {return *this;}
\r
251 second_reference second() {return *this;}
\r
252 second_const_reference second() const {return *this;}
\r
254 // no need to swap empty bases:
\r
255 void swap(::boost::compressed_pair<T1,T2>&) {}
\r
259 // 4 T1 == T2, T1 and T2 both empty
\r
260 // Originally this did not store an instance of T2 at all
\r
261 // but that led to problems beause it meant &x.first() == &x.second()
\r
262 // which is not true for any other kind of pair, so now we store an instance
\r
263 // of T2 just in case the user is relying on first() and second() returning
\r
264 // different objects (albeit both empty).
\r
265 template <class T1, class T2>
\r
266 class compressed_pair_imp<T1, T2, 4>
\r
267 : protected ::boost::remove_cv<T1>::type
\r
270 typedef T1 first_type;
\r
271 typedef T2 second_type;
\r
272 typedef typename call_traits<first_type>::param_type first_param_type;
\r
273 typedef typename call_traits<second_type>::param_type second_param_type;
\r
274 typedef typename call_traits<first_type>::reference first_reference;
\r
275 typedef typename call_traits<second_type>::reference second_reference;
\r
276 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
277 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
279 compressed_pair_imp() {}
\r
281 compressed_pair_imp(first_param_type x, second_param_type y)
\r
282 : first_type(x), m_second(y) {}
\r
284 compressed_pair_imp(first_param_type x)
\r
285 : first_type(x), m_second(x) {}
\r
287 first_reference first() {return *this;}
\r
288 first_const_reference first() const {return *this;}
\r
290 second_reference second() {return m_second;}
\r
291 second_const_reference second() const {return m_second;}
\r
293 void swap(::boost::compressed_pair<T1,T2>&) {}
\r
298 // 5 T1 == T2 and are not empty: //JM
\r
300 template <class T1, class T2>
\r
301 class compressed_pair_imp<T1, T2, 5>
\r
304 typedef T1 first_type;
\r
305 typedef T2 second_type;
\r
306 typedef typename call_traits<first_type>::param_type first_param_type;
\r
307 typedef typename call_traits<second_type>::param_type second_param_type;
\r
308 typedef typename call_traits<first_type>::reference first_reference;
\r
309 typedef typename call_traits<second_type>::reference second_reference;
\r
310 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
311 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
313 compressed_pair_imp() {}
\r
315 compressed_pair_imp(first_param_type x, second_param_type y)
\r
316 : first_(x), second_(y) {}
\r
318 compressed_pair_imp(first_param_type x)
\r
319 : first_(x), second_(x) {}
\r
321 first_reference first() {return first_;}
\r
322 first_const_reference first() const {return first_;}
\r
324 second_reference second() {return second_;}
\r
325 second_const_reference second() const {return second_;}
\r
327 void swap(::boost::compressed_pair<T1, T2>& y)
\r
329 cp_swap(first_, y.first());
\r
330 cp_swap(second_, y.second());
\r
334 second_type second_;
\r
339 template <class T1, class T2>
\r
340 class compressed_pair
\r
341 : private ::boost::details::compressed_pair_imp<T1, T2,
\r
342 ::boost::details::compressed_pair_switch<
\r
345 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
\r
346 ::boost::is_empty<T1>::value,
\r
347 ::boost::is_empty<T2>::value>::value>
\r
350 typedef details::compressed_pair_imp<T1, T2,
\r
351 ::boost::details::compressed_pair_switch<
\r
354 ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
\r
355 ::boost::is_empty<T1>::value,
\r
356 ::boost::is_empty<T2>::value>::value> base;
\r
358 typedef T1 first_type;
\r
359 typedef T2 second_type;
\r
360 typedef typename call_traits<first_type>::param_type first_param_type;
\r
361 typedef typename call_traits<second_type>::param_type second_param_type;
\r
362 typedef typename call_traits<first_type>::reference first_reference;
\r
363 typedef typename call_traits<second_type>::reference second_reference;
\r
364 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
365 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
367 compressed_pair() : base() {}
\r
368 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
\r
369 explicit compressed_pair(first_param_type x) : base(x) {}
\r
370 explicit compressed_pair(second_param_type y) : base(y) {}
\r
372 first_reference first() {return base::first();}
\r
373 first_const_reference first() const {return base::first();}
\r
375 second_reference second() {return base::second();}
\r
376 second_const_reference second() const {return base::second();}
\r
378 void swap(compressed_pair& y) { base::swap(y); }
\r
382 // Partial specialisation for case where T1 == T2:
\r
385 class compressed_pair<T, T>
\r
386 : private details::compressed_pair_imp<T, T,
\r
387 ::boost::details::compressed_pair_switch<
\r
390 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
\r
391 ::boost::is_empty<T>::value,
\r
392 ::boost::is_empty<T>::value>::value>
\r
395 typedef details::compressed_pair_imp<T, T,
\r
396 ::boost::details::compressed_pair_switch<
\r
399 ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
\r
400 ::boost::is_empty<T>::value,
\r
401 ::boost::is_empty<T>::value>::value> base;
\r
403 typedef T first_type;
\r
404 typedef T second_type;
\r
405 typedef typename call_traits<first_type>::param_type first_param_type;
\r
406 typedef typename call_traits<second_type>::param_type second_param_type;
\r
407 typedef typename call_traits<first_type>::reference first_reference;
\r
408 typedef typename call_traits<second_type>::reference second_reference;
\r
409 typedef typename call_traits<first_type>::const_reference first_const_reference;
\r
410 typedef typename call_traits<second_type>::const_reference second_const_reference;
\r
412 compressed_pair() : base() {}
\r
413 compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
\r
414 #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
\r
417 compressed_pair(first_param_type x) : base(x) {}
\r
419 first_reference first() {return base::first();}
\r
420 first_const_reference first() const {return base::first();}
\r
422 second_reference second() {return base::second();}
\r
423 second_const_reference second() const {return base::second();}
\r
425 void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
\r
428 template <class T1, class T2>
\r
431 swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
\r
439 # pragma warning(pop)
\r
442 #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
\r