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 | |
40 | namespace boost { |
41 | namespace tuples { |
42 | |
43 | struct null_type; |
44 | |
45 | template < |
46 | class T0, class T1, class T2, |
47 | class T3, class T4, class T5, |
48 | class T6, class T7, class T8, |
49 | class T9> |
50 | class tuple; |
51 | |
52 | } //namespace tuples { |
53 | } //namespace boost { |
54 | |
55 | namespace boost { |
56 | namespace container { |
57 | namespace pair_impl { |
58 | |
59 | template <class TupleClass> |
60 | struct is_boost_tuple |
61 | { |
62 | static const bool value = false; |
63 | }; |
64 | |
65 | template < |
66 | class T0, class T1, class T2, |
67 | class T3, class T4, class T5, |
68 | class T6, class T7, class T8, |
69 | class T9> |
70 | struct 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 | |
75 | template<class Tuple> |
76 | struct disable_if_boost_tuple |
77 | : boost::container::container_detail::disable_if< is_boost_tuple<Tuple> > |
78 | {}; |
79 | |
80 | template<class T> |
81 | struct is_tuple_null |
82 | { |
83 | static const bool value = false; |
84 | }; |
85 | |
86 | template<> |
87 | struct 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 |
96 | namespace std { namespace tr1 { struct _Nil; }} |
97 | #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540) |
98 | //MSVC 2012 tuple marker |
99 | namespace std { struct _Nil; } |
100 | #endif |
101 | |
102 | |
103 | namespace boost { |
104 | namespace 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 | |
118 | typedef const std::piecewise_construct_t & piecewise_construct_t; |
119 | |
120 | struct 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. |
126 | typedef unspecified piecewise_construct_t; |
127 | |
128 | #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED |
129 | |
130 | //! A instance of type |
131 | //! piecewise_construct_t |
132 | static piecewise_construct_t piecewise_construct = BOOST_CONTAINER_DOC1ST(unspecified, *std_piecewise_construct_holder<>::dummy); |
133 | |
134 | ///@cond |
135 | |
136 | namespace container_detail { |
137 | |
138 | struct piecewise_construct_use |
139 | { |
140 | //Avoid warnings of unused "piecewise_construct" |
141 | piecewise_construct_use() |
142 | { (void)&::boost::container::piecewise_construct; } |
143 | }; |
144 | |
145 | template <class T1, class T2> |
146 | struct pair; |
147 | |
148 | template <class T> |
149 | struct is_pair |
150 | { |
151 | static const bool value = false; |
152 | }; |
153 | |
154 | template <class T1, class T2> |
155 | struct is_pair< pair<T1, T2> > |
156 | { |
157 | static const bool value = true; |
158 | }; |
159 | |
160 | template <class T1, class T2> |
161 | struct is_pair< std::pair<T1, T2> > |
162 | { |
163 | static const bool value = true; |
164 | }; |
165 | |
166 | template <class T> |
167 | struct is_not_pair |
168 | { |
169 | static const bool value = !is_pair<T>::value; |
170 | }; |
171 | |
172 | template <class T> |
173 | struct is_std_pair |
174 | { |
175 | static const bool value = false; |
176 | }; |
177 | |
178 | template <class T1, class T2> |
179 | struct is_std_pair< std::pair<T1, T2> > |
180 | { |
181 | static const bool value = true; |
182 | }; |
183 | |
184 | struct pair_nat; |
185 | |
186 | template<typename T, typename U, typename V> |
187 | void get(T); //to enable ADL |
188 | |
189 | ///@endcond |
190 | |
191 | template <class T1, class T2> |
192 | struct 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 | |
448 | template <class T1, class T2> |
449 | inline 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 | |
452 | template <class T1, class T2> |
453 | inline 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 | |
457 | template <class T1, class T2> |
458 | inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y) |
459 | { return static_cast<bool>(!(x == y)); } |
460 | |
461 | template <class T1, class T2> |
462 | inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y) |
463 | { return y < x; } |
464 | |
465 | template <class T1, class T2> |
466 | inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y) |
467 | { return static_cast<bool>(!(x < y)); } |
468 | |
469 | template <class T1, class T2> |
470 | inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y) |
471 | { return static_cast<bool>(!(y < x)); } |
472 | |
473 | template <class T1, class T2> |
474 | inline pair<T1, T2> make_pair(T1 x, T2 y) |
475 | { return pair<T1, T2>(x, y); } |
476 | |
477 | template <class T1, class T2> |
478 | inline 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 | |
486 | template<class T1, class T2> |
487 | struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> > |
488 | { |
489 | static const bool value = true; |
490 | }; |
491 | |
492 | #endif |
493 | |
494 | namespace move_detail{ |
495 | |
496 | template<class T> |
497 | struct is_class_or_union; |
498 | |
499 | template <class T1, class T2> |
500 | struct 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 | |
507 | template <class T1, class T2> |
508 | struct 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 | |
515 | template<class T> |
516 | struct is_union; |
517 | |
518 | template <class T1, class T2> |
519 | struct 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 | |
526 | template <class T1, class T2> |
527 | struct 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 | |
534 | template<class T> |
535 | struct is_class; |
536 | |
537 | template <class T1, class T2> |
538 | struct 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 | |
545 | template <class T1, class T2> |
546 | struct 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 | |