summaryrefslogtreecommitdiff
path: root/boost/container/detail/dispatch_uses_allocator.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container/detail/dispatch_uses_allocator.hpp')
-rw-r--r--boost/container/detail/dispatch_uses_allocator.hpp293
1 files changed, 293 insertions, 0 deletions
diff --git a/boost/container/detail/dispatch_uses_allocator.hpp b/boost/container/detail/dispatch_uses_allocator.hpp
new file mode 100644
index 0000000000..3000f7cb27
--- /dev/null
+++ b/boost/container/detail/dispatch_uses_allocator.hpp
@@ -0,0 +1,293 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
+#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/uses_allocator.hpp>
+
+#include <boost/container/detail/addressof.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/pair.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/move/utility_core.hpp>
+
+#include <boost/core/no_exceptions_support.hpp>
+
+namespace boost { namespace container {
+
+namespace container_detail {
+
+
+// Check if we can detect is_convertible using advanced SFINAE expressions
+#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ //! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
+ //! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
+ //! Thanks Mathias!
+
+ //With variadic templates, we need a single class to implement the trait
+ template<class T, class ...Args>
+ struct is_constructible
+ {
+ typedef char yes_type;
+ struct no_type
+ { char padding[2]; };
+
+ template<std::size_t N>
+ struct dummy;
+
+ template<class X>
+ static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
+
+ template<class X>
+ static no_type test(...);
+
+ static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
+ };
+
+ template <class T, class InnerAlloc, class ...Args>
+ struct is_constructible_with_allocator_prefix
+ : is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
+ {};
+
+#else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ //Without advanced SFINAE expressions, we can't use is_constructible
+ //so backup to constructible_with_allocator_xxx
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class T, class InnerAlloc, class ...Args>
+ struct is_constructible_with_allocator_prefix
+ : constructible_with_allocator_prefix<T>
+ {};
+
+ template <class T, class InnerAlloc, class ...Args>
+ struct is_constructible_with_allocator_suffix
+ : constructible_with_allocator_suffix<T>
+ {};
+
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
+ struct is_constructible_with_allocator_prefix
+ : constructible_with_allocator_prefix<T>
+ {};
+
+ template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
+ struct is_constructible_with_allocator_suffix
+ : constructible_with_allocator_suffix<T>
+ {};
+
+ #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#endif // #if !defined(BOOST_NO_SFINAE_EXPR)
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename T
+ , class ...Args
+ >
+inline typename container_detail::enable_if_and
+ < void
+ , container_detail::is_not_pair<T>
+ , container_detail::not_< uses_allocator<T, ArgAlloc> >
+ >::type dispatch_uses_allocator
+ ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
+{
+ (void)arg_alloc;
+ allocator_traits<ConstructAlloc>::construct(construct_alloc, p, ::boost::forward<Args>(args)...);
+}
+
+// allocator_arg_t
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename T
+ , class ...Args
+ >
+inline typename container_detail::enable_if_and
+ < void
+ , container_detail::is_not_pair<T>
+ , uses_allocator<T, ArgAlloc>
+ , is_constructible_with_allocator_prefix<T, ArgAlloc, Args...>
+ >::type dispatch_uses_allocator
+ ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args) ...args)
+{
+ allocator_traits<ConstructAlloc>::construct
+ ( construct_alloc, p, allocator_arg
+ , ::boost::forward<ArgAlloc>(arg_alloc), ::boost::forward<Args>(args)...);
+}
+
+// allocator suffix
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename T
+ , class ...Args
+ >
+inline typename container_detail::enable_if_and
+ < void
+ , container_detail::is_not_pair<T>
+ , uses_allocator<T, ArgAlloc>
+ , container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc, Args...> >
+ >::type dispatch_uses_allocator
+ ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
+{
+ allocator_traits<ConstructAlloc>::construct
+ (construct_alloc, p, ::boost::forward<Args>(args)..., ::boost::forward<ArgAlloc>(arg_alloc));
+}
+
+#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
+ template <typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename container_detail::enable_if_and\
+ < void\
+ , container_detail::is_not_pair<T>\
+ , container_detail::not_<uses_allocator<T, ArgAlloc> >\
+ >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ (void)arg_alloc;\
+ allocator_traits<ConstructAlloc>::construct(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+//
+BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
+#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
+
+#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
+ template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename container_detail::enable_if_and\
+ < void\
+ , container_detail::is_not_pair<T>\
+ , uses_allocator<T, ArgAlloc>\
+ , is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>\
+ >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ allocator_traits<ConstructAlloc>::construct\
+ (construct_alloc, p, allocator_arg, ::boost::forward<ArgAlloc>(arg_alloc) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+//
+BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
+#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
+
+#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
+ template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename container_detail::enable_if_and\
+ < void\
+ , container_detail::is_not_pair<T>\
+ , uses_allocator<T, ArgAlloc>\
+ , container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N> >\
+ >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ allocator_traits<ConstructAlloc>::construct\
+ (construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, ::boost::forward<ArgAlloc>(arg_alloc));\
+ }\
+//
+BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
+#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
+
+#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename Pair
+ > inline
+BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
+ dispatch_uses_allocator
+ ( ConstructAlloc & construct_alloc
+ , ArgAlloc & arg_alloc
+ , Pair* p)
+{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first));
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second));
+ }
+ BOOST_CATCH(...) {
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class U, class V>
+BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
+ dispatch_uses_allocator
+ ( ConstructAlloc & construct_alloc
+ , ArgAlloc & arg_alloc
+ , Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
+{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<U>(x));
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second), ::boost::forward<V>(y));
+ }
+ BOOST_CATCH(...){
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class Pair2>
+BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if< container_detail::is_pair<Pair> >::type)
+ dispatch_uses_allocator
+ (ConstructAlloc & construct_alloc
+ , ArgAlloc & arg_alloc
+ , Pair* p, Pair2& x)
+{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, x.first, x.second); }
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class Pair2>
+typename container_detail::enable_if_and
+ < void
+ , container_detail::is_pair<Pair>
+ , container_detail::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
+ dispatch_uses_allocator
+ (ConstructAlloc & construct_alloc
+ , ArgAlloc & arg_alloc
+ , Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
+{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
+
+//template <typename ConstructAlloc, typename ArgAlloc, class Pair, class Pair2>
+//void dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc
+// , pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
+
+} //namespace container_detail
+
+}} // namespace boost { namespace container {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP