From ceef4d6521244cadd4d9fe50938255c86372448e Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 30 Aug 2011 22:01:54 +0000 Subject: [PATCH] Unordered: Explicitly pick construct_impl overloads. Still getting ambiguous call errors for some older compilers, so use SFINAE to only enable a single overload for each arity. [SVN r74171] --- include/boost/unordered/detail/buckets.hpp | 276 +++++++++++++-------- 1 file changed, 168 insertions(+), 108 deletions(-) diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index 35a9332d..e5c754ec 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -549,156 +549,216 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std) BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::tr1) #endif - template - struct emulated_pair_constructor - { - enum { value = false }; - }; - - template - struct emulated_pair_constructor, void> - { - enum { value = true }; - }; - - template - struct emulated_pair_constructor, Value> - { + template + struct emulation1 { static choice1::type check(choice1, std::pair const&); static choice2::type check(choice2, A const&); - - enum { value = sizeof(check(choose(), make())) - 1 }; + + enum { value = sizeof(check(choose(), make())) == sizeof(choice2::type) }; }; + template + struct piecewise3 { + static choice1::type check(choice1, boost::unordered::piecewise_construct_t); + static choice2::type check(choice2, A const&); + static choice3::type check(choice3, ...); + + enum { value = sizeof(check(choose(), make())) == sizeof(choice1::type) }; + }; + + template + struct emulation3 { + static choice1::type check(choice1, boost::unordered::piecewise_construct_t); + static choice2::type check(choice2, A const&); + static choice3::type check(choice3, ...); + + enum { value = sizeof(check(choose(), make())) == sizeof(choice2::type) }; + }; + + template + struct normal3 { + static choice1::type check(choice1, boost::unordered::piecewise_construct_t); + static choice2::type check(choice2, A const&); + static choice3::type check(choice3, ...); + + enum { value = sizeof(check(choose(), make())) == sizeof(choice3::type) }; + }; + + template + struct pair_construct1 {}; + template + struct pair_construct1, Arg1> + : enable_if, void> {}; + + template + struct normal_construct1 { typedef void type; }; + template + struct normal_construct1, Arg1> + : disable_if, void> {}; + + template + struct piecewise_construct3 {}; + template + struct piecewise_construct3, Arg1> + : enable_if, void> {}; + + template + struct pair_construct3 {}; + template + struct pair_construct3, Arg1> + : enable_if, void> {}; + + template + struct normal_construct3 { typedef void type; }; + template + struct normal_construct3, Arg1> + : enable_if, void> {}; + + template + struct pair_construct_n {}; + template + struct pair_construct_n > { typedef void type; }; + + template + struct normal_construct_n { typedef void type; }; + template + struct normal_construct_n > {}; + template inline void construct_impl(void* address) { new(address) T(); } -#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE) - template - inline void construct_impl( - typename boost::disable_if, - void*>::type address, - Arg1&& a1) - { - new(address) T(std::forward(a1)); - } - - template - inline void construct_impl( - typename boost::enable_if, - void*>::type address, - Arg1&& a1) - { - new(address) T(std::forward(a1), typename T::second_type()); - } - - template - inline void construct_impl(void* address, Arg1&& a1, Arg2&& a2) - { - new(address) T(std::forward(a1), std::forward(a2)); - } - - template - inline typename boost::disable_if, void>::type - construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args) - { - new(address) T(std::forward(arg1), std::forward(arg2), - std::forward(args)...); - } - - template - inline typename boost::enable_if, void>::type - construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args) - { - new(address) T(std::forward(arg1), - typename T::second_type( - std::forward(arg2), std::forward(args)...)); - } - - template - inline typename boost::enable_if >::type - construct_impl(void* address, boost::unordered::piecewise_construct_t, - Tuple1&& tuple1, Tuple2&& tuple2) - { - construct_from_tuple(&static_cast(address)->first, tuple1); - construct_from_tuple(&static_cast(address)->second, tuple2); - } - -#else - - template - inline BOOST_DEDUCED_TYPENAME boost::disable_if, void>::type - construct_impl(void* address, BOOST_FWD_REF(Arg1) a1) - { - new(address) T(boost::forward(a1)); - } - - template - inline BOOST_DEDUCED_TYPENAME boost::enable_if, void>::type - construct_impl(void* address, BOOST_FWD_REF(Arg1) a1) + inline BOOST_DEDUCED_TYPENAME normal_construct1::type + construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1) { new(address) T( - boost::forward(a1), - BOOST_DEDUCED_TYPENAME T::second_type() + boost::forward(arg1) ); } - template - inline void construct_impl(void* address, - BOOST_FWD_REF(Arg1) a1, BOOST_FWD_REF(Arg2) a2) + template + inline BOOST_DEDUCED_TYPENAME pair_construct1::type + construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1) { - new(address) T(boost::forward(a1), boost::forward(a2)); + new((void*)(&static_cast(address)->first)) + BOOST_DEDUCED_TYPENAME T::first_type( + boost::forward(arg1)); + new((void*)(&static_cast(address)->second)) + BOOST_DEDUCED_TYPENAME T::second_type(); + } + + template + inline void construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2) + { + new(address) T( + boost::forward(arg1), + boost::forward(arg2)); } - template - inline typename boost::enable_if >::type - construct_impl(void* address, boost::unordered::piecewise_construct_t, - BOOST_FWD_REF(Tuple1) tuple1, BOOST_FWD_REF(Tuple2) tuple2) + template + inline BOOST_DEDUCED_TYPENAME piecewise_construct3::type + construct_impl(void* address, BOOST_FWD_REF(Arg1), + BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3) { - construct_from_tuple(&static_cast(address)->first, tuple1); - construct_from_tuple(&static_cast(address)->second, tuple2); + construct_from_tuple(&static_cast(address)->first, arg2); + construct_from_tuple(&static_cast(address)->second, arg3); } + template + inline BOOST_DEDUCED_TYPENAME pair_construct3::type + construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3) + { + new((void*)(&static_cast(address)->first)) + BOOST_DEDUCED_TYPENAME T::first_type( + boost::forward(arg1)); + new((void*)(&static_cast(address)->second)) + BOOST_DEDUCED_TYPENAME T::second_type( + boost::forward(arg2), + boost::forward(arg3)); + } + + template + inline BOOST_DEDUCED_TYPENAME normal_construct3::type + construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3) + { + new(address) T( + boost::forward(arg1), + boost::forward(arg2), + boost::forward(arg3)); + } + +#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE) + + template + inline BOOST_DEDUCED_TYPENAME normal_construct_n::type + construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, + Arg4&& arg4, Args&&... args) + { + new(address) T( + std::forward(arg1), + std::forward(arg2), + std::forward(arg3), + std::forward(arg4), + std::forward(args)...); + } + + template + inline BOOST_DEDUCED_TYPENAME pair_construct_n::type + construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, + Arg4&& arg4, Args&&... args) + { + new((void*)(&static_cast(address)->first)) + BOOST_DEDUCED_TYPENAME T::first_type( + std::forward(arg1)); + new((void*)(&static_cast(address)->second)) + BOOST_DEDUCED_TYPENAME T::second_type( + std::forward(arg2), + std::forward(arg3), + std::forward(arg4), + std::forward(args)...); + } + +#else + #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \ template < \ class T, \ BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \ > \ - inline BOOST_DEDUCED_TYPENAME \ - boost::disable_if >::type \ - construct_impl( \ - void* address, \ - BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \ - ) \ + inline BOOST_DEDUCED_TYPENAME normal_construct_n::type \ + construct_impl(void* address, \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ { \ new(address) T( \ BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ } - BOOST_PP_REPEAT_FROM_TO(3, BOOST_UNORDERED_EMPLACE_LIMIT, + 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 BOOST_DEDUCED_TYPENAME \ - boost::enable_if >::type \ - construct_impl( \ - void* address, \ - BOOST_FWD_REF(Key) k, \ + inline BOOST_DEDUCED_TYPENAME pair_construct_n::type \ + construct_impl(void* address, BOOST_FWD_REF(Key) key, \ BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ { \ - new(address) T(k, \ - BOOST_DEDUCED_TYPENAME \ - T::second_type(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \ + new((void*)(&static_cast(address)->first)) \ + BOOST_DEDUCED_TYPENAME T::first_type( \ + boost::forward(key)); \ + new((void*)(&static_cast(address)->second)) \ + BOOST_DEDUCED_TYPENAME T::second_type( \ + BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ } - BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT, + BOOST_PP_REPEAT_FROM_TO(3, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _) #undef BOOST_UNORDERED_CONSTRUCT_IMPL