1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2005-2013.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// See http://www.boost.org/libs/container for documentation.
10//
11//////////////////////////////////////////////////////////////////////////////
12
13#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
14#define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
15
16#ifndef BOOST_CONFIG_HPP
17# include <boost/config.hpp>
18#endif
19
20#if defined(BOOST_HAS_PRAGMA_ONCE)
21# pragma once
22#endif
23
24#include <boost/container/detail/config_begin.hpp>
25#include <boost/container/detail/workaround.hpp>
26
27#include <boost/container/detail/mpl.hpp>
28#include <boost/container/detail/type_traits.hpp>
29#include <boost/container/detail/mpl.hpp>
30#include <boost/container/detail/std_fwd.hpp>
31#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
32# include <boost/container/detail/variadic_templates_tools.hpp>
33#endif
34#include <boost/move/adl_move_swap.hpp> //swap
35
36#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
37#include <boost/move/utility_core.hpp>
38#include <boost/move/detail/fwd_macros.hpp>
39
40namespace boost {
41namespace tuples {
42
43struct null_type;
44
45template <
46 class T0, class T1, class T2,
47 class T3, class T4, class T5,
48 class T6, class T7, class T8,
49 class T9>
50class tuple;
51
52} //namespace tuples {
53} //namespace boost {
54
55namespace boost {
56namespace container {
57namespace pair_impl {
58
59template <class TupleClass>
60struct is_boost_tuple
61{
62 static const bool value = false;
63};
64
65template <
66 class T0, class T1, class T2,
67 class T3, class T4, class T5,
68 class T6, class T7, class T8,
69 class T9>
70struct is_boost_tuple< boost::tuples::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
71{
72 static const bool value = true;
73};
74
75template<class Tuple>
76struct disable_if_boost_tuple
77 : boost::container::container_detail::disable_if< is_boost_tuple<Tuple> >
78{};
79
80template<class T>
81struct is_tuple_null
82{
83 static const bool value = false;
84};
85
86template<>
87struct is_tuple_null<boost::tuples::null_type>
88{
89 static const bool value = true;
90};
91
92}}}
93
94#if defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
95//MSVC 2010 tuple marker
96namespace std { namespace tr1 { struct _Nil; }}
97#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
98//MSVC 2012 tuple marker
99namespace std { struct _Nil; }
100#endif
101
102
103namespace boost {
104namespace container {
105
106#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
107
108 template <int Dummy = 0>
109 struct std_piecewise_construct_holder
110 {
111 static ::std::piecewise_construct_t *dummy;
112 };
113
114 template <int Dummy>
115 ::std::piecewise_construct_t *std_piecewise_construct_holder<Dummy>::dummy =
116 reinterpret_cast< ::std::piecewise_construct_t *>(0x01234); //Avoid sanitizer errors on references to null pointers
117
118typedef const std::piecewise_construct_t & piecewise_construct_t;
119
120struct try_emplace_t{};
121
122#else
123
124//! The piecewise_construct_t struct is an empty structure type used as a unique type to
125//! disambiguate used to disambiguate between different functions that take two tuple arguments.
126typedef unspecified piecewise_construct_t;
127
128#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
129
130//! A instance of type
131//! piecewise_construct_t
132static piecewise_construct_t piecewise_construct = BOOST_CONTAINER_DOC1ST(unspecified, *std_piecewise_construct_holder<>::dummy);
133
134///@cond
135
136namespace container_detail {
137
138struct piecewise_construct_use
139{
140 //Avoid warnings of unused "piecewise_construct"
141 piecewise_construct_use()
142 { (void)&::boost::container::piecewise_construct; }
143};
144
145template <class T1, class T2>
146struct pair;
147
148template <class T>
149struct is_pair
150{
151 static const bool value = false;
152};
153
154template <class T1, class T2>
155struct is_pair< pair<T1, T2> >
156{
157 static const bool value = true;
158};
159
160template <class T1, class T2>
161struct is_pair< std::pair<T1, T2> >
162{
163 static const bool value = true;
164};
165
166template <class T>
167struct is_not_pair
168{
169 static const bool value = !is_pair<T>::value;
170};
171
172template <class T>
173struct is_std_pair
174{
175 static const bool value = false;
176};
177
178template <class T1, class T2>
179struct is_std_pair< std::pair<T1, T2> >
180{
181 static const bool value = true;
182};
183
184struct pair_nat;
185
186template<typename T, typename U, typename V>
187void get(T); //to enable ADL
188
189///@endcond
190
191template <class T1, class T2>
192struct pair
193{
194 private:
195 BOOST_COPYABLE_AND_MOVABLE(pair)
196
197 public:
198 typedef T1 first_type;
199 typedef T2 second_type;
200
201 T1 first;
202 T2 second;
203
204 //Default constructor
205 pair()
206 : first(), second()
207 {}
208
209 //pair copy assignment
210 pair(const pair& x)
211 : first(x.first), second(x.second)
212 {}
213
214 //pair move constructor
215 pair(BOOST_RV_REF(pair) p)
216 : first(::boost::move(p.first)), second(::boost::move(p.second))
217 {}
218
219 template <class D, class S>
220 pair(const pair<D, S> &p)
221 : first(p.first), second(p.second)
222 {}
223
224 template <class D, class S>
225 pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
226 : first(::boost::move(p.first)), second(::boost::move(p.second))
227 {}
228
229 //pair from two values
230 pair(const T1 &t1, const T2 &t2)
231 : first(t1)
232 , second(t2)
233 {}
234
235 template<class U, class V>
236 pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
237 : first(::boost::forward<U>(u))
238 , second(::boost::forward<V>(v))
239 {}
240
241 //And now compatibility with std::pair
242 pair(const std::pair<T1, T2>& x)
243 : first(x.first), second(x.second)
244 {}
245
246 template <class D, class S>
247 pair(const std::pair<D, S>& p)
248 : first(p.first), second(p.second)
249 {}
250
251 pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
252 : first(::boost::move(p.first)), second(::boost::move(p.second))
253 {}
254
255 template <class D, class S>
256 pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
257 : first(::boost::move(p.first)), second(::boost::move(p.second))
258 {}
259
260 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
261 template< class KeyType, class ...Args>
262 pair(try_emplace_t, BOOST_FWD_REF(KeyType) k, Args && ...args)
263 : first(boost::forward<KeyType>(k)), second(::boost::forward<Args>(args)...)\
264 {}
265 #else
266
267 //piecewise construction from boost::tuple
268 #define BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE(N)\
269 template< class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
270 pair( try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
271 : first(boost::forward<KeyType>(k)), second(BOOST_MOVE_FWD##N)\
272 {}\
273 //
274 BOOST_MOVE_ITERATE_0TO9(BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE)
275 #undef BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE
276
277 #endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
278
279 //piecewise construction from boost::tuple
280 #define BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
281 template< template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
282 BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
283 pair( piecewise_construct_t\
284 , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
285 , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q\
286 , typename container_detail::enable_if_c\
287 < pair_impl::is_boost_tuple< BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> >::value &&\
288 !(pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARG##N>::value || pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARGQ##M>::value) \
289 >::type* = 0\
290 )\
291 : first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\
292 { (void)p; (void)q; }\
293 //
294 BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
295 #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
296
297 //piecewise construction from variadic tuple (with delegating constructors)
298 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
299 # if !defined(BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS)
300 private:
301 template<template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
302 pair(Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
303 : first (::boost::forward<Args1>(get<Indexes1>(t1))...)
304 , second(::boost::forward<Args2>(get<Indexes2>(t2))...)
305 { (void) t1; (void)t2; }
306
307 public:
308 template< template<class ...> class Tuple, class... Args1, class... Args2
309 , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
310 pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
311 : pair(t1, t2, typename build_number_seq<sizeof...(Args1)>::type(), typename build_number_seq<sizeof...(Args2)>::type())
312 {}
313 # else
314 //piecewise construction from variadic tuple (suboptimal, without delegating constructors)
315 private:
316 template<typename T, template<class ...> class Tuple, typename... Args>
317 static T build_from_args(Tuple<Args...>&& t)
318 { return do_build_from_args<T>(::boost::move(t), typename build_number_seq<sizeof...(Args)>::type()); }
319
320 template<typename T, template<class ...> class Tuple, typename... Args, std::size_t... Indexes>
321 static T do_build_from_args(Tuple<Args...> && t, const index_tuple<Indexes...>&)
322 { (void)t; return T(::boost::forward<Args>(get<Indexes>(t))...); }
323
324 public:
325 template< template<class ...> class Tuple, class... Args1, class... Args2
326 , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
327 pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
328 : first (build_from_args<first_type> (::boost::move(t1)))
329 , second (build_from_args<second_type>(::boost::move(t2)))
330 {}
331 # endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
332 #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
333 //MSVC 2010 tuple implementation
334 #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
335 template< template<class, class, class, class, class, class, class, class, class, class> class StdTuple \
336 BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
337 pair( piecewise_construct_t\
338 , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
339 , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
340 : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
341 { (void)p; (void)q; }\
342 //
343 BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
344 #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
345 #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
346 #if _VARIADIC_MAX >= 9
347 #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
348 #else
349 #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
350 #endif
351
352 //MSVC 2012 tuple implementation
353 #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
354 template< template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
355 BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
356 pair( piecewise_construct_t\
357 , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
358 , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
359 : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
360 { (void)p; (void)q; }\
361 //
362 BOOST_MOVE_ITER2D_0TOMAX(BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
363 #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
364 #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
365 #endif
366
367 //pair copy assignment
368 pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p)
369 {
370 first = p.first;
371 second = p.second;
372 return *this;
373 }
374
375 //pair move assignment
376 pair& operator=(BOOST_RV_REF(pair) p)
377 {
378 first = ::boost::move(p.first);
379 second = ::boost::move(p.second);
380 return *this;
381 }
382
383 template <class D, class S>
384 typename ::boost::container::container_detail::disable_if_or
385 < pair &
386 , ::boost::container::container_detail::is_same<T1, D>
387 , ::boost::container::container_detail::is_same<T2, S>
388 >::type
389 operator=(const pair<D, S>&p)
390 {
391 first = p.first;
392 second = p.second;
393 return *this;
394 }
395
396 template <class D, class S>
397 typename ::boost::container::container_detail::disable_if_or
398 < pair &
399 , ::boost::container::container_detail::is_same<T1, D>
400 , ::boost::container::container_detail::is_same<T2, S>
401 >::type
402 operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
403 {
404 first = ::boost::move(p.first);
405 second = ::boost::move(p.second);
406 return *this;
407 }
408//std::pair copy assignment
409 pair& operator=(const std::pair<T1, T2> &p)
410 {
411 first = p.first;
412 second = p.second;
413 return *this;
414 }
415
416 template <class D, class S>
417 pair& operator=(const std::pair<D, S> &p)
418 {
419 first = ::boost::move(p.first);
420 second = ::boost::move(p.second);
421 return *this;
422 }
423
424 //std::pair move assignment
425 pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
426 {
427 first = ::boost::move(p.first);
428 second = ::boost::move(p.second);
429 return *this;
430 }
431
432 template <class D, class S>
433 pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
434 {
435 first = ::boost::move(p.first);
436 second = ::boost::move(p.second);
437 return *this;
438 }
439
440 //swap
441 void swap(pair& p)
442 {
443 ::boost::adl_move_swap(this->first, p.first);
444 ::boost::adl_move_swap(this->second, p.second);
445 }
446};
447
448template <class T1, class T2>
449inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
450{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
451
452template <class T1, class T2>
453inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
454{ return static_cast<bool>(x.first < y.first ||
455 (!(y.first < x.first) && x.second < y.second)); }
456
457template <class T1, class T2>
458inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
459{ return static_cast<bool>(!(x == y)); }
460
461template <class T1, class T2>
462inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
463{ return y < x; }
464
465template <class T1, class T2>
466inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
467{ return static_cast<bool>(!(x < y)); }
468
469template <class T1, class T2>
470inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
471{ return static_cast<bool>(!(y < x)); }
472
473template <class T1, class T2>
474inline pair<T1, T2> make_pair(T1 x, T2 y)
475{ return pair<T1, T2>(x, y); }
476
477template <class T1, class T2>
478inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
479{ x.swap(y); }
480
481} //namespace container_detail {
482} //namespace container {
483
484#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
485
486template<class T1, class T2>
487struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> >
488{
489 static const bool value = true;
490};
491
492#endif
493
494namespace move_detail{
495
496template<class T>
497struct is_class_or_union;
498
499template <class T1, class T2>
500struct is_class_or_union< ::boost::container::container_detail::pair<T1, T2> >
501//This specialization is needed to avoid instantiation of pair in
502//is_class, and allow recursive maps.
503{
504 static const bool value = true;
505};
506
507template <class T1, class T2>
508struct is_class_or_union< std::pair<T1, T2> >
509//This specialization is needed to avoid instantiation of pair in
510//is_class, and allow recursive maps.
511{
512 static const bool value = true;
513};
514
515template<class T>
516struct is_union;
517
518template <class T1, class T2>
519struct is_union< ::boost::container::container_detail::pair<T1, T2> >
520//This specialization is needed to avoid instantiation of pair in
521//is_class, and allow recursive maps.
522{
523 static const bool value = false;
524};
525
526template <class T1, class T2>
527struct is_union< std::pair<T1, T2> >
528//This specialization is needed to avoid instantiation of pair in
529//is_class, and allow recursive maps.
530{
531 static const bool value = false;
532};
533
534template<class T>
535struct is_class;
536
537template <class T1, class T2>
538struct is_class< ::boost::container::container_detail::pair<T1, T2> >
539//This specialization is needed to avoid instantiation of pair in
540//is_class, and allow recursive maps.
541{
542 static const bool value = true;
543};
544
545template <class T1, class T2>
546struct is_class< std::pair<T1, T2> >
547//This specialization is needed to avoid instantiation of pair in
548//is_class, and allow recursive maps.
549{
550 static const bool value = true;
551};
552
553} //namespace move_detail{
554
555} //namespace boost {
556
557#include <boost/container/detail/config_end.hpp>
558
559#endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP
560