// Copyright (C) 2011 Daniel James. // 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/unordered for documentation #ifndef BOOST_UNORDERED_EMPLACE_ARGS_HPP #define BOOST_UNORDERED_EMPLACE_ARGS_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include #include #include #include #include #include #include #include #include #include #if !defined(BOOST_NO_0X_HDR_TUPLE) #include #elif defined(BOOST_HAS_TR1_TUPLE) #include #endif #if defined(BOOST_MSVC) #pragma warning(push) #pragma warning(disable:4512) // assignment operator could not be generated. #pragma warning(disable:4345) // behavior change: an object of POD type // constructed with an initializer of the form () // will be default-initialized. #endif #define BOOST_UNORDERED_EMPLACE_LIMIT 10 #if 0 && !defined(BOOST_NO_RVALUE_REFERENCES) && \ !defined(BOOST_NO_VARIADIC_TEMPLATES) # if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) # elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) # elif defined(_LIBCPP_VERSION) # define BOOST_UNORDERED_STD_FORWARD_MOVE # elif defined(__GLIBCPP__) || defined(__GLIBCXX__) # if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804 # define BOOST_UNORDERED_STD_FORWARD_MOVE # endif # elif defined(__STL_CONFIG_H) # elif defined(__MSL_CPP__) # elif defined(__IBMCPP__) # elif defined(MSIPL_COMPILE_H) # elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) // Visual C++. A version check would be a good idea. # define BOOST_UNORDERED_STD_FORWARD_MOVE # endif #endif namespace boost { namespace unordered { namespace detail { #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE) #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args #define BOOST_UNORDERED_EMPLACE_ARGS Args&&... args #define BOOST_UNORDERED_EMPLACE_FORWARD std::forward(args)... #else #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args #define BOOST_UNORDERED_EMPLACE_ARGS Args const& args #define BOOST_UNORDERED_EMPLACE_FORWARD args #define BOOST_UNORDERED_FWD_PARAM(z, n, a) \ BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n) #define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \ boost::forward(BOOST_PP_CAT(a,i)) #define BOOST_UNORDERED_EARGS(z, n, _) \ template \ struct BOOST_PP_CAT(emplace_args, n) \ { \ BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \ BOOST_PP_CAT(emplace_args, n) ( \ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, B, a) \ ) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \ {} \ \ }; \ \ template \ inline BOOST_PP_CAT(emplace_args, n) < \ BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ > create_emplace_args( \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \ ) \ { \ BOOST_PP_CAT(emplace_args, n) < \ BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ > e(BOOST_PP_ENUM_PARAMS_Z(z, n, a)); \ return e; \ } #if defined(BOOST_NO_RVALUE_REFERENCES) #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \ typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(B, n); \ BOOST_PP_CAT(B, n) BOOST_PP_CAT(a, n); #define BOOST_UNORDERED_EARGS_INIT(z, n, _) \ BOOST_PP_CAT(a, n)( \ boost::forward(BOOST_PP_CAT(a, n))) #else #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \ typedef typename boost::add_lvalue_reference::type \ BOOST_PP_CAT(B, n); \ BOOST_PP_CAT(B, n) BOOST_PP_CAT(a, n); #define BOOST_UNORDERED_EARGS_INIT(z, n, _) \ BOOST_PP_CAT(a, n)(BOOST_PP_CAT(a, n)) #endif BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS, _) #undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS #undef BOOST_UNORDERED_EARGS_MEMBER #undef BOOST_UNORDERED_EARGS_INIT #endif //////////////////////////////////////////////////////////////////////////// // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter // e.g. for int #if !defined(BOOST_NO_RVALUE_REFERENCES) # define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T) #else struct please_ignore_this_overload { typedef please_ignore_this_overload type; }; template struct rv_ref_impl { typedef BOOST_RV_REF(T) type; }; template struct rv_ref : boost::detail::if_true< boost::is_class::value >::BOOST_NESTED_TEMPLATE then < rv_ref_impl, please_ignore_this_overload >::type {}; # define BOOST_UNORDERED_RV_REF(T) \ typename ::boost::unordered::detail::rv_ref::type #endif //////////////////////////////////////////////////////////////////////////// // // Value Construction #define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \ template \ void construct_from_tuple(T* ptr, namespace_::tuple<>) \ { \ new ((void*) ptr) T(); \ } \ \ BOOST_PP_REPEAT_FROM_TO(1, n, \ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_) #define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \ template \ void construct_from_tuple(T* ptr, \ namespace_::tuple const& x) \ { \ new ((void*) ptr) T( \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \ ); \ } #define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \ namespace_::get(x) BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost) #if !defined(BOOST_NO_0X_HDR_TUPLE) BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std) #elif defined(BOOST_HAS_TR1_TUPLE) BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::tr1) #endif #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL #undef BOOST_UNORDERED_GET_TUPLE_ARG #if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT) template struct emulation1 { static choice1::type check(choice1, std::pair const&); static choice2::type check(choice2, A const&); static choice3::type check(choice3, ...); enum { value = sizeof(check(choose(), make())) == sizeof(choice2::type) }; }; #endif #if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT) template struct check3_base { static choice1::type check(choice1, boost::unordered::piecewise_construct_t); static choice2::type check(choice2, A const&); static choice3::type check(choice3, ...); }; #else template struct check3_base { static choice1::type check(choice1, boost::unordered::piecewise_construct_t); static choice3::type check(choice3, ...); }; #endif template struct piecewise3 { enum { value = sizeof(check3_base::check(choose(), make())) == sizeof(choice1::type) }; }; template struct emulation3 { enum { value = sizeof(check3_base::check(choose(), make())) == sizeof(choice2::type) }; }; template struct normal3 { enum { value = sizeof(check3_base::check(choose(), make())) == sizeof(choice3::type) }; }; template struct pair_construct1 {}; template struct normal_construct1 { typedef void type; }; #if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT) template struct pair_construct1, A0> : enable_if, void> {}; template struct normal_construct1, A0> : disable_if, void> {}; #endif template struct piecewise_construct3 {}; template struct piecewise_construct3, A0> : enable_if, void> {}; template struct pair_construct3 {}; template struct pair_construct3, A0> : enable_if, void> {}; template struct normal_construct3 { typedef void type; }; template struct normal_construct3, A0> : enable_if, void> {}; template struct pair_construct_n {}; template struct normal_construct_n { typedef void type; }; #if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT) template struct pair_construct_n > { typedef void type; }; template struct normal_construct_n > {}; #endif template inline typename normal_construct1::type construct_impl2(void* address, BOOST_FWD_REF(A0) a0) { new(address) T( boost::forward(a0) ); } #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE) //////////////////////////////////////////////////////////////////////////////// // Construct from variadic parameters template inline void construct_impl(void* address) { new(address) T(); } template inline typename normal_construct1::type construct_impl(void* address, A0&& a0) { new(address) T( boost::forward(a0) ); } template inline typename pair_construct1::type construct_impl(void* address, A0&& a0) { new((void*)(&static_cast(address)->first)) typename T::first_type( boost::forward(a0)); new((void*)(&static_cast(address)->second)) typename T::second_type(); } template inline void construct_impl(void* address, A0&& a0, A1&& a1) { new(address) T( boost::forward(a0), boost::forward(a1)); } template inline typename piecewise_construct3::type construct_impl(void* address, A0&&, A1&& a1, A2&& a2) { construct_from_tuple( boost::addressof(static_cast(address)->first), a1); construct_from_tuple( boost::addressof(static_cast(address)->second), a2); } template inline typename pair_construct3::type construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2) { new((void*)(&static_cast(address)->first)) typename T::first_type( boost::forward(a0)); new((void*)(&static_cast(address)->second)) typename T::second_type( boost::forward(a1), boost::forward(a2)); } template inline typename normal_construct3::type construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2) { new(address) T( boost::forward(a0), boost::forward(a1), boost::forward(a2)); } template inline typename normal_construct_n::type construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2, A3&& a3, Args&&... args) { new(address) T( std::forward(a0), std::forward(a1), std::forward(a2), std::forward(a3), std::forward(args)...); } template inline typename pair_construct_n::type construct_impl(void* address, A0&& a0, A1&& a1, A2&& a2, A3&& a3, Args&&... args) { new((void*)(&static_cast(address)->first)) typename T::first_type( std::forward(a0)); new((void*)(&static_cast(address)->second)) typename T::second_type( std::forward(a1), std::forward(a2), std::forward(a3), std::forward(args)...); } #else //////////////////////////////////////////////////////////////////////////////// // Construct with emplace_args template inline typename normal_construct1::type construct_impl(void* address, ::boost::unordered::detail::emplace_args1 const& args) { new(address) T( boost::forward(args.a0) ); } template inline typename pair_construct1::type construct_impl(void* address, A0 const& a0) { new((void*)(&static_cast(address)->first)) typename T::first_type( boost::forward(a0)); new((void*)(&static_cast(address)->second)) typename T::second_type(); } template inline typename pair_construct1::type construct_impl(void* address, ::boost::unordered::detail::emplace_args1 const& args) { new((void*)(&static_cast(address)->first)) typename T::first_type( boost::forward(args.a0)); new((void*)(&static_cast(address)->second)) typename T::second_type(); } template inline void construct_impl(void* address, ::boost::unordered::detail::emplace_args2 const& args) { new(address) T( boost::forward(args.a0), boost::forward(args.a1)); } template inline typename piecewise_construct3::type construct_impl(void* address, ::boost::unordered::detail::emplace_args3 const& args) { construct_from_tuple( boost::addressof(static_cast(address)->first), args.a1); construct_from_tuple( boost::addressof(static_cast(address)->second), args.a2); } template inline typename pair_construct3::type construct_impl(void* address, ::boost::unordered::detail::emplace_args3 const& args) { new((void*)(&static_cast(address)->first)) typename T::first_type( boost::forward(args.a0)); new((void*)(&static_cast(address)->second)) typename T::second_type( boost::forward(args.a1), boost::forward(args.a2)); } template inline typename normal_construct3::type construct_impl(void* address, ::boost::unordered::detail::emplace_args3 const& args) { new(address) T( boost::forward(args.a0), boost::forward(args.a1), boost::forward(args.a2)); } #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \ template < \ typename T, \ BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \ > \ inline typename normal_construct_n::type \ construct_impl(void* address, \ ::boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \ BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \ > const& args) \ { \ new(address) T( \ BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \ args.a)); \ } BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_CONSTRUCT_IMPL, _) #define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \ template \ inline typename pair_construct_n::type \ construct_impl(void* address, \ ::boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \ BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \ > const& args) \ { \ new((void*)(&static_cast(address)->first)) \ typename T::first_type( \ boost::forward(args.a0)); \ new((void*)(&static_cast(address)->second)) \ typename T::second_type( \ BOOST_PP_ENUM_SHIFTED_##z(num_params, \ BOOST_UNORDERED_CALL_FORWARD, args.a)); \ } BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _) #undef BOOST_UNORDERED_CONSTRUCT_IMPL #undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL #endif }}} #if defined(BOOST_MSVC) #pragma warning(pop) #endif #endif