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 | namespace boost { |
37 | namespace container { |
38 | namespace container_detail { |
39 | |
40 | template <class T1, class T2> |
41 | struct pair; |
42 | |
43 | template <class T> |
44 | struct is_pair |
45 | { |
46 | static const bool value = false; |
47 | }; |
48 | |
49 | template <class T1, class T2> |
50 | struct is_pair< pair<T1, T2> > |
51 | { |
52 | static const bool value = true; |
53 | }; |
54 | |
55 | template <class T1, class T2> |
56 | struct is_pair< std::pair<T1, T2> > |
57 | { |
58 | static const bool value = true; |
59 | }; |
60 | |
61 | struct pair_nat; |
62 | |
63 | struct piecewise_construct_t { }; |
64 | static const piecewise_construct_t piecewise_construct = piecewise_construct_t(); |
65 | |
66 | /* |
67 | template <class T1, class T2> |
68 | struct pair |
69 | { |
70 | template <class U, class V> pair(pair<U, V>&& p); |
71 | template <class... Args1, class... Args2> |
72 | pair(piecewise_construct_t, tuple<Args1...> first_args, |
73 | tuple<Args2...> second_args); |
74 | |
75 | template <class U, class V> pair& operator=(const pair<U, V>& p); |
76 | pair& operator=(pair&& p) noexcept(is_nothrow_move_assignable<T1>::value && |
77 | is_nothrow_move_assignable<T2>::value); |
78 | template <class U, class V> pair& operator=(pair<U, V>&& p); |
79 | |
80 | void swap(pair& p) noexcept(noexcept(swap(first, p.first)) && |
81 | noexcept(swap(second, p.second))); |
82 | }; |
83 | |
84 | template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); |
85 | template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); |
86 | template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); |
87 | template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&); |
88 | template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); |
89 | template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); |
90 | */ |
91 | |
92 | |
93 | template <class T1, class T2> |
94 | struct pair |
95 | { |
96 | private: |
97 | BOOST_COPYABLE_AND_MOVABLE(pair) |
98 | |
99 | public: |
100 | typedef T1 first_type; |
101 | typedef T2 second_type; |
102 | |
103 | T1 first; |
104 | T2 second; |
105 | |
106 | //Default constructor |
107 | pair() |
108 | : first(), second() |
109 | {} |
110 | |
111 | //pair copy assignment |
112 | pair(const pair& x) |
113 | : first(x.first), second(x.second) |
114 | {} |
115 | |
116 | //pair move constructor |
117 | pair(BOOST_RV_REF(pair) p) |
118 | : first(::boost::move(p.first)), second(::boost::move(p.second)) |
119 | {} |
120 | |
121 | template <class D, class S> |
122 | pair(const pair<D, S> &p) |
123 | : first(p.first), second(p.second) |
124 | {} |
125 | |
126 | template <class D, class S> |
127 | pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p) |
128 | : first(::boost::move(p.first)), second(::boost::move(p.second)) |
129 | {} |
130 | |
131 | //pair from two values |
132 | pair(const T1 &t1, const T2 &t2) |
133 | : first(t1) |
134 | , second(t2) |
135 | {} |
136 | |
137 | template<class U, class V> |
138 | pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v) |
139 | : first(::boost::forward<U>(u)) |
140 | , second(::boost::forward<V>(v)) |
141 | {} |
142 | |
143 | //And now compatibility with std::pair |
144 | pair(const std::pair<T1, T2>& x) |
145 | : first(x.first), second(x.second) |
146 | {} |
147 | |
148 | template <class D, class S> |
149 | pair(const std::pair<D, S>& p) |
150 | : first(p.first), second(p.second) |
151 | {} |
152 | |
153 | pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p) |
154 | : first(::boost::move(p.first)), second(::boost::move(p.second)) |
155 | {} |
156 | |
157 | template <class D, class S> |
158 | pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p) |
159 | : first(::boost::move(p.first)), second(::boost::move(p.second)) |
160 | {} |
161 | |
162 | //piecewise_construct missing |
163 | //template <class U, class V> pair(pair<U, V>&& p); |
164 | //template <class... Args1, class... Args2> |
165 | // pair(piecewise_construct_t, tuple<Args1...> first_args, |
166 | // tuple<Args2...> second_args); |
167 | |
168 | //pair copy assignment |
169 | pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p) |
170 | { |
171 | first = p.first; |
172 | second = p.second; |
173 | return *this; |
174 | } |
175 | |
176 | //pair move assignment |
177 | pair& operator=(BOOST_RV_REF(pair) p) |
178 | { |
179 | first = ::boost::move(p.first); |
180 | second = ::boost::move(p.second); |
181 | return *this; |
182 | } |
183 | |
184 | template <class D, class S> |
185 | typename ::boost::container::container_detail::enable_if_c |
186 | < !(::boost::container::container_detail::is_same<T1, D>::value && |
187 | ::boost::container::container_detail::is_same<T2, S>::value) |
188 | , pair &>::type |
189 | operator=(const pair<D, S>&p) |
190 | { |
191 | first = p.first; |
192 | second = p.second; |
193 | return *this; |
194 | } |
195 | |
196 | template <class D, class S> |
197 | typename ::boost::container::container_detail::enable_if_c |
198 | < !(::boost::container::container_detail::is_same<T1, D>::value && |
199 | ::boost::container::container_detail::is_same<T2, S>::value) |
200 | , pair &>::type |
201 | operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p) |
202 | { |
203 | first = ::boost::move(p.first); |
204 | second = ::boost::move(p.second); |
205 | return *this; |
206 | } |
207 | |
208 | //std::pair copy assignment |
209 | pair& operator=(const std::pair<T1, T2> &p) |
210 | { |
211 | first = p.first; |
212 | second = p.second; |
213 | return *this; |
214 | } |
215 | |
216 | template <class D, class S> |
217 | pair& operator=(const std::pair<D, S> &p) |
218 | { |
219 | first = ::boost::move(p.first); |
220 | second = ::boost::move(p.second); |
221 | return *this; |
222 | } |
223 | |
224 | //std::pair move assignment |
225 | pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p) |
226 | { |
227 | first = ::boost::move(p.first); |
228 | second = ::boost::move(p.second); |
229 | return *this; |
230 | } |
231 | |
232 | template <class D, class S> |
233 | pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p) |
234 | { |
235 | first = ::boost::move(p.first); |
236 | second = ::boost::move(p.second); |
237 | return *this; |
238 | } |
239 | |
240 | //swap |
241 | void swap(pair& p) |
242 | { |
243 | ::boost::adl_move_swap(this->first, p.first); |
244 | ::boost::adl_move_swap(this->second, p.second); |
245 | } |
246 | }; |
247 | |
248 | template <class T1, class T2> |
249 | inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y) |
250 | { return static_cast<bool>(x.first == y.first && x.second == y.second); } |
251 | |
252 | template <class T1, class T2> |
253 | inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y) |
254 | { return static_cast<bool>(x.first < y.first || |
255 | (!(y.first < x.first) && x.second < y.second)); } |
256 | |
257 | template <class T1, class T2> |
258 | inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y) |
259 | { return static_cast<bool>(!(x == y)); } |
260 | |
261 | template <class T1, class T2> |
262 | inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y) |
263 | { return y < x; } |
264 | |
265 | template <class T1, class T2> |
266 | inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y) |
267 | { return static_cast<bool>(!(x < y)); } |
268 | |
269 | template <class T1, class T2> |
270 | inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y) |
271 | { return static_cast<bool>(!(y < x)); } |
272 | |
273 | template <class T1, class T2> |
274 | inline pair<T1, T2> make_pair(T1 x, T2 y) |
275 | { return pair<T1, T2>(x, y); } |
276 | |
277 | template <class T1, class T2> |
278 | inline void swap(pair<T1, T2>& x, pair<T1, T2>& y) |
279 | { x.swap(y); } |
280 | |
281 | } //namespace container_detail { |
282 | } //namespace container { |
283 | |
284 | |
285 | //Without this specialization recursive flat_(multi)map instantiation fails |
286 | //because is_enum needs to instantiate the recursive pair, leading to a compilation error). |
287 | //This breaks the cycle clearly stating that pair is not an enum avoiding any instantiation. |
288 | template<class T> |
289 | struct is_enum; |
290 | |
291 | template<class T, class U> |
292 | struct is_enum< ::boost::container::container_detail::pair<T, U> > |
293 | { |
294 | static const bool value = false; |
295 | }; |
296 | |
297 | template <class T> |
298 | struct is_class; |
299 | |
300 | //This specialization is needed to avoid instantiation of pair in |
301 | //is_class, and allow recursive maps. |
302 | template <class T1, class T2> |
303 | struct is_class< ::boost::container::container_detail::pair<T1, T2> > |
304 | { |
305 | static const bool value = true; |
306 | }; |
307 | |
308 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
309 | |
310 | template<class T1, class T2> |
311 | struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> > |
312 | { |
313 | static const bool value = true; |
314 | }; |
315 | |
316 | #endif |
317 | |
318 | namespace move_detail{ |
319 | |
320 | template<class T> |
321 | struct is_class_or_union; |
322 | |
323 | template <class T1, class T2> |
324 | struct is_class_or_union< ::boost::container::container_detail::pair<T1, T2> > |
325 | //This specialization is needed to avoid instantiation of pair in |
326 | //is_class, and allow recursive maps. |
327 | { |
328 | static const bool value = true; |
329 | }; |
330 | |
331 | |
332 | } //namespace move_detail{ |
333 | |
334 | } //namespace boost { |
335 | |
336 | #include <boost/container/detail/config_end.hpp> |
337 | |
338 | #endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP |
339 | |