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/type_traits.hpp>
31 #include <boost/move/adl_move_swap.hpp> //swap
32 
33 #include <boost/intrusive/detail/minimal_pair_header.hpp>      //pair
34 #include <boost/move/utility_core.hpp>
35 
36 /*
37 namespace boost{
38 
39 template<class T1, class T2>
40 inline rv< std::pair<T1, T2> > &move(std::pair<T1, T2> &r)
41 {
42    return reinterpret_cast< rv< std::pair<T1, T2> > &>(r);
43 }
44 
45 template<class T1, class T2>
46 inline rv< std::pair<T1, T2> > &move(rv< std::pair<T1, T2> > &r)
47 {
48    return r;
49 }
50 
51 template <class T>
52 inline typename ::boost::move_detail::enable_if_and
53    < T &
54    , boost::container::container_detail::is_std_pair<T>
55    , ::boost::move_detail::is_rv<T>
56    >::type
57       forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
58 {
59    return const_cast<T&>(x);
60 }
61 
62 template <class T>
63 inline typename ::boost::move_detail::enable_if_and
64    < const T &
65    , boost::container::container_detail::is_std_pair<T>
66    , ::boost::move_detail::is_not_rv<T>
67    >::type
68       forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
69 {
70    return x;
71 }
72 
73 }  //namespace boost {
74 */
75 
76 namespace boost {
77 namespace container {
78 namespace container_detail {
79 
80 template <class T1, class T2>
81 struct pair;
82 
83 template <class T>
84 struct is_pair
85 {
86    static const bool value = false;
87 };
88 
89 template <class T1, class T2>
90 struct is_pair< pair<T1, T2> >
91 {
92    static const bool value = true;
93 };
94 
95 template <class T1, class T2>
96 struct is_pair< std::pair<T1, T2> >
97 {
98    static const bool value = true;
99 };
100 
101 template <class T>
102 struct is_not_pair
103 {
104    static const bool value = !is_pair<T>::value;
105 };
106 
107 template <class T>
108 struct is_std_pair
109 {
110    static const bool value = false;
111 };
112 
113 template <class T1, class T2>
114 struct is_std_pair< std::pair<T1, T2> >
115 {
116    static const bool value = true;
117 };
118 
119 struct pair_nat;
120 
121 struct piecewise_construct_t { };
122 static const piecewise_construct_t piecewise_construct = piecewise_construct_t();
123 
124 /*
125 template <class T1, class T2>
126 struct pair
127 {
128     template <class U, class V> pair(pair<U, V>&& p);
129     template <class... Args1, class... Args2>
130         pair(piecewise_construct_t, tuple<Args1...> first_args,
131              tuple<Args2...> second_args);
132 
133     template <class U, class V> pair& operator=(const pair<U, V>& p);
134     pair& operator=(pair&& p) noexcept(is_nothrow_move_assignable<T1>::value &&
135                                        is_nothrow_move_assignable<T2>::value);
136     template <class U, class V> pair& operator=(pair<U, V>&& p);
137 
138     void swap(pair& p) noexcept(noexcept(swap(first, p.first)) &&
139                                 noexcept(swap(second, p.second)));
140 };
141 
142 template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&);
143 template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&);
144 template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&);
145 template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&);
146 template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&);
147 template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&);
148 */
149 
150 
151 template <class T1, class T2>
152 struct pair
153 {
154    private:
155    BOOST_COPYABLE_AND_MOVABLE(pair)
156 
157    public:
158    typedef T1 first_type;
159    typedef T2 second_type;
160 
161    T1 first;
162    T2 second;
163 
164    //Default constructor
pairboost::container::container_detail::pair165    pair()
166       : first(), second()
167    {}
168 
169    //pair copy assignment
pairboost::container::container_detail::pair170    pair(const pair& x)
171       : first(x.first), second(x.second)
172    {}
173 
174    //pair move constructor
pairboost::container::container_detail::pair175    pair(BOOST_RV_REF(pair) p)
176       : first(::boost::move(p.first)), second(::boost::move(p.second))
177    {}
178 
179    template <class D, class S>
pairboost::container::container_detail::pair180    pair(const pair<D, S> &p)
181       : first(p.first), second(p.second)
182    {}
183 
184    template <class D, class S>
pairboost::container::container_detail::pair185    pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
186       : first(::boost::move(p.first)), second(::boost::move(p.second))
187    {}
188 
189    //pair from two values
pairboost::container::container_detail::pair190    pair(const T1 &t1, const T2 &t2)
191       : first(t1)
192       , second(t2)
193    {}
194 
195    template<class U, class V>
pairboost::container::container_detail::pair196    pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
197       : first(::boost::forward<U>(u))
198       , second(::boost::forward<V>(v))
199    {}
200 
201    //And now compatibility with std::pair
pairboost::container::container_detail::pair202    pair(const std::pair<T1, T2>& x)
203       : first(x.first), second(x.second)
204    {}
205 
206    template <class D, class S>
pairboost::container::container_detail::pair207    pair(const std::pair<D, S>& p)
208       : first(p.first), second(p.second)
209    {}
210 
pairboost::container::container_detail::pair211    pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
212       : first(::boost::move(p.first)), second(::boost::move(p.second))
213    {}
214 
215    template <class D, class S>
pairboost::container::container_detail::pair216    pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
217       : first(::boost::move(p.first)), second(::boost::move(p.second))
218    {}
219 
220    //piecewise_construct missing
221    //template <class U, class V> pair(pair<U, V>&& p);
222    //template <class... Args1, class... Args2>
223    //   pair(piecewise_construct_t, tuple<Args1...> first_args,
224    //        tuple<Args2...> second_args);
225 
226    //pair copy assignment
operator =boost::container::container_detail::pair227    pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p)
228    {
229       first  = p.first;
230       second = p.second;
231       return *this;
232    }
233 
234    //pair move assignment
operator =boost::container::container_detail::pair235    pair& operator=(BOOST_RV_REF(pair) p)
236    {
237       first  = ::boost::move(p.first);
238       second = ::boost::move(p.second);
239       return *this;
240    }
241 
242    template <class D, class S>
243    typename ::boost::container::container_detail::disable_if_or
244       < pair &
245       , ::boost::container::container_detail::is_same<T1, D>
246       , ::boost::container::container_detail::is_same<T2, S>
247       >::type
operator =boost::container::container_detail::pair248       operator=(const pair<D, S>&p)
249    {
250       first  = p.first;
251       second = p.second;
252       return *this;
253    }
254 
255    template <class D, class S>
256    typename ::boost::container::container_detail::disable_if_or
257       < pair &
258       , ::boost::container::container_detail::is_same<T1, D>
259       , ::boost::container::container_detail::is_same<T2, S>
260       >::type
operator =boost::container::container_detail::pair261       operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
262    {
263       first  = ::boost::move(p.first);
264       second = ::boost::move(p.second);
265       return *this;
266    }
267 //std::pair copy assignment
operator =boost::container::container_detail::pair268    pair& operator=(const std::pair<T1, T2> &p)
269    {
270       first  = p.first;
271       second = p.second;
272       return *this;
273    }
274 
275    template <class D, class S>
operator =boost::container::container_detail::pair276    pair& operator=(const std::pair<D, S> &p)
277    {
278       first  = ::boost::move(p.first);
279       second = ::boost::move(p.second);
280       return *this;
281    }
282 
283    //std::pair move assignment
operator =boost::container::container_detail::pair284    pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
285    {
286       first  = ::boost::move(p.first);
287       second = ::boost::move(p.second);
288       return *this;
289    }
290 
291    template <class D, class S>
operator =boost::container::container_detail::pair292    pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
293    {
294       first  = ::boost::move(p.first);
295       second = ::boost::move(p.second);
296       return *this;
297    }
298 
299    //swap
swapboost::container::container_detail::pair300    void swap(pair& p)
301    {
302       ::boost::adl_move_swap(this->first, p.first);
303       ::boost::adl_move_swap(this->second, p.second);
304    }
305 };
306 
307 template <class T1, class T2>
operator ==(const pair<T1,T2> & x,const pair<T1,T2> & y)308 inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
309 {  return static_cast<bool>(x.first == y.first && x.second == y.second);  }
310 
311 template <class T1, class T2>
operator <(const pair<T1,T2> & x,const pair<T1,T2> & y)312 inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
313 {  return static_cast<bool>(x.first < y.first ||
314                          (!(y.first < x.first) && x.second < y.second)); }
315 
316 template <class T1, class T2>
operator !=(const pair<T1,T2> & x,const pair<T1,T2> & y)317 inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
318 {  return static_cast<bool>(!(x == y));  }
319 
320 template <class T1, class T2>
operator >(const pair<T1,T2> & x,const pair<T1,T2> & y)321 inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
322 {  return y < x;  }
323 
324 template <class T1, class T2>
operator >=(const pair<T1,T2> & x,const pair<T1,T2> & y)325 inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
326 {  return static_cast<bool>(!(x < y)); }
327 
328 template <class T1, class T2>
operator <=(const pair<T1,T2> & x,const pair<T1,T2> & y)329 inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
330 {  return static_cast<bool>(!(y < x)); }
331 
332 template <class T1, class T2>
make_pair(T1 x,T2 y)333 inline pair<T1, T2> make_pair(T1 x, T2 y)
334 {  return pair<T1, T2>(x, y); }
335 
336 template <class T1, class T2>
swap(pair<T1,T2> & x,pair<T1,T2> & y)337 inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
338 {  x.swap(y);  }
339 
340 }  //namespace container_detail {
341 }  //namespace container {
342 
343 
344 //Without this specialization recursive flat_(multi)map instantiation fails
345 //because is_enum needs to instantiate the recursive pair, leading to a compilation error).
346 //This breaks the cycle clearly stating that pair is not an enum avoiding any instantiation.
347 template<class T>
348 struct is_enum;
349 
350 template<class T, class U>
351 struct is_enum< ::boost::container::container_detail::pair<T, U> >
352 {
353    static const bool value = false;
354 };
355 
356 template <class T>
357 struct is_class;
358 
359 //This specialization is needed to avoid instantiation of pair in
360 //is_class, and allow recursive maps.
361 template <class T1, class T2>
362 struct is_class< ::boost::container::container_detail::pair<T1, T2> >
363 {
364    static const bool value = true;
365 };
366 
367 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
368 
369 template<class T1, class T2>
370 struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> >
371 {
372    static const bool value = true;
373 };
374 
375 #endif
376 
377 namespace move_detail{
378 
379 template<class T>
380 struct is_class_or_union;
381 
382 template <class T1, class T2>
383 struct is_class_or_union< ::boost::container::container_detail::pair<T1, T2> >
384 //This specialization is needed to avoid instantiation of pair in
385 //is_class, and allow recursive maps.
386 {
387    static const bool value = true;
388 };
389 
390 
391 }  //namespace move_detail{
392 
393 }  //namespace boost {
394 
395 #include <boost/container/detail/config_end.hpp>
396 
397 #endif   //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP
398