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