1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
12 #define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
14 #if defined (_MSC_VER)
18 #include <boost/container/detail/config_begin.hpp>
19 #include <boost/container/detail/workaround.hpp>
21 #include <boost/container/allocator_traits.hpp>
22 #include <boost/container/uses_allocator.hpp>
24 #include <boost/container/detail/addressof.hpp>
25 #include <boost/container/detail/mpl.hpp>
26 #include <boost/container/detail/is_pair.hpp>
27 #include <boost/container/detail/type_traits.hpp>
29 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
30 #include <boost/move/detail/fwd_macros.hpp>
32 #include <boost/container/detail/variadic_templates_tools.hpp>
34 #include <boost/move/utility_core.hpp>
36 #include <boost/core/no_exceptions_support.hpp>
38 namespace boost { namespace container {
43 // Check if we can detect is_convertible using advanced SFINAE expressions
44 #if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
46 //! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
47 //! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
50 //With variadic templates, we need a single class to implement the trait
51 template<class T, class ...Args>
52 struct is_constructible
54 typedef char yes_type;
58 template<std::size_t N>
62 static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
65 static no_type test(...);
67 static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
70 template <class T, class InnerAlloc, class ...Args>
71 struct is_constructible_with_allocator_prefix
72 : is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
75 #else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
77 //Without advanced SFINAE expressions, we can't use is_constructible
78 //so backup to constructible_with_allocator_xxx
80 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
82 template <class T, class InnerAlloc, class ...Args>
83 struct is_constructible_with_allocator_prefix
84 : constructible_with_allocator_prefix<T>
87 template <class T, class InnerAlloc, class ...Args>
88 struct is_constructible_with_allocator_suffix
89 : constructible_with_allocator_suffix<T>
92 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
94 template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
95 struct is_constructible_with_allocator_prefix
96 : constructible_with_allocator_prefix<T>
99 template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
100 struct is_constructible_with_allocator_suffix
101 : constructible_with_allocator_suffix<T>
104 #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
106 #endif // #if !defined(BOOST_NO_SFINAE_EXPR)
108 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
110 template < typename ConstructAlloc
115 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
117 , dtl::is_not_pair<T>
118 , dtl::not_< uses_allocator<T, typename remove_cvref<ArgAlloc>::type > >
119 >::type dispatch_uses_allocator
120 ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
123 allocator_traits<ConstructAlloc>::construct(construct_alloc, p, ::boost::forward<Args>(args)...);
127 template < typename ConstructAlloc
132 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
134 , dtl::is_not_pair<T>
135 , uses_allocator<T, typename remove_cvref<ArgAlloc>::type>
136 , is_constructible_with_allocator_prefix<T, ArgAlloc, Args...>
137 >::type dispatch_uses_allocator
138 ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args) ...args)
140 allocator_traits<ConstructAlloc>::construct
141 ( construct_alloc, p, allocator_arg
142 , ::boost::forward<ArgAlloc>(arg_alloc), ::boost::forward<Args>(args)...);
146 template < typename ConstructAlloc
151 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
153 , dtl::is_not_pair<T>
154 , uses_allocator<T, typename remove_cvref<ArgAlloc>::type>
155 , dtl::not_<is_constructible_with_allocator_prefix<T, ArgAlloc, Args...> >
156 >::type dispatch_uses_allocator
157 ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
159 allocator_traits<ConstructAlloc>::construct
160 (construct_alloc, p, ::boost::forward<Args>(args)..., ::boost::forward<ArgAlloc>(arg_alloc));
163 #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
165 #define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
166 template <typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
167 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and\
169 , dtl::is_not_pair<T>\
170 , dtl::not_<uses_allocator<T, typename remove_cvref<ArgAlloc>::type> >\
172 dispatch_uses_allocator\
173 (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
176 allocator_traits<ConstructAlloc>::construct(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
179 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
180 #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
182 #define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
183 template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
184 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and\
186 , dtl::is_not_pair<T>\
187 , uses_allocator<T, typename remove_cvref<ArgAlloc>::type>\
188 , is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>\
190 dispatch_uses_allocator\
191 (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
193 allocator_traits<ConstructAlloc>::construct\
194 (construct_alloc, p, allocator_arg, ::boost::forward<ArgAlloc>(arg_alloc) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
197 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
198 #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
200 #define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
201 template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
202 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and\
204 , dtl::is_not_pair<T>\
205 , uses_allocator<T, typename remove_cvref<ArgAlloc>::type>\
206 , dtl::not_<is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N> >\
208 dispatch_uses_allocator\
209 (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
211 allocator_traits<ConstructAlloc>::construct\
212 (construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, ::boost::forward<ArgAlloc>(arg_alloc));\
215 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
216 #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
218 #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
220 template < typename ConstructAlloc
224 BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if<dtl::is_pair<Pair> BOOST_MOVE_I void >::type)
225 dispatch_uses_allocator
226 ( ConstructAlloc & construct_alloc
227 , BOOST_FWD_REF(ArgAlloc) arg_alloc
230 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->first));
232 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second));
235 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
242 template < typename ConstructAlloc
244 , class Pair, class U, class V>
245 BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if<dtl::is_pair<Pair> BOOST_MOVE_I void>::type)
246 dispatch_uses_allocator
247 ( ConstructAlloc & construct_alloc
248 , BOOST_FWD_REF(ArgAlloc) arg_alloc
249 , Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
251 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<U>(x));
253 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<V>(y));
256 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
262 template < typename ConstructAlloc
264 , class Pair, class Pair2>
265 BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void >::type)
266 dispatch_uses_allocator
267 (ConstructAlloc & construct_alloc
268 , BOOST_FWD_REF(ArgAlloc) arg_alloc
270 { dispatch_uses_allocator(construct_alloc, arg_alloc, p, x.first, x.second); }
272 template < typename ConstructAlloc
274 , class Pair, class Pair2>
275 typename dtl::enable_if_and
278 , dtl::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
279 dispatch_uses_allocator
280 (ConstructAlloc & construct_alloc
281 , BOOST_FWD_REF(ArgAlloc) arg_alloc
282 , Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
283 { dispatch_uses_allocator(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
286 //piecewise construction from boost::tuple
287 #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
288 template< typename ConstructAlloc, typename ArgAlloc, class Pair \
289 , template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
290 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 > \
291 typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::type\
292 dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
293 , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
294 , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
297 dispatch_uses_allocator\
298 (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\
300 dispatch_uses_allocator\
301 (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\
304 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
310 BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
311 #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
313 //piecewise construction from Std Tuple
314 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
316 template< typename ConstructAlloc, typename ArgAlloc, class Pair
317 , template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
318 void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair
319 , Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
322 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(pair->first), ::boost::forward<Args1>(get<Indexes1>(t1))...);
324 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(pair->second), ::boost::forward<Args2>(get<Indexes2>(t2))...);
327 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));
333 template< typename ConstructAlloc, typename ArgAlloc, class Pair
334 , template<class ...> class Tuple, class... Args1, class... Args2>
335 typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
336 dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t
337 , Tuple<Args1...> t1, Tuple<Args2...> t2)
339 (dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2
340 , typename build_number_seq<sizeof...(Args1)>::type()
341 , typename build_number_seq<sizeof...(Args2)>::type());
344 #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
346 //MSVC 2010 tuple implementation
347 #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
348 template< typename ConstructAlloc, typename ArgAlloc, class Pair\
349 , template<class, class, class, class, class, class, class, class, class, class> class StdTuple\
350 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 > \
351 typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::type\
352 dispatch_uses_allocator(ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
353 , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
354 , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
357 dispatch_uses_allocator\
358 (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
360 dispatch_uses_allocator\
361 (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
364 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
370 BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
371 #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
373 #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
374 #if _VARIADIC_MAX >= 9
375 #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
377 #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
380 //MSVC 2012 tuple implementation
381 #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
382 template< typename ConstructAlloc, typename ArgAlloc, class Pair\
383 , template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
384 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 > \
385 typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::type\
386 dispatch_uses_allocator\
387 ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
388 , 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\
389 , 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)\
392 dispatch_uses_allocator\
393 (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
395 dispatch_uses_allocator\
396 (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
399 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
405 BOOST_MOVE_ITER2D_0TOMAX(BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
406 #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
407 #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
409 #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
411 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
413 template < typename ConstructAlloc
415 , class Pair, class KeyType, class ... Args>
416 typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
417 dispatch_uses_allocator
418 (ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
420 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<KeyType>(k));
422 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<Args>(args)...);
425 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
433 #define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE(N) \
434 template <typename ConstructAlloc, typename ArgAlloc, class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
435 inline typename dtl::enable_if\
436 < dtl::is_pair<Pair> BOOST_MOVE_I void >::type\
437 dispatch_uses_allocator\
438 (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, \
439 BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
441 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
443 dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
446 allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));\
452 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE)
453 #undef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE
455 #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
459 }} // namespace boost { namespace container {
461 #include <boost/container/detail/config_end.hpp>
463 #endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP