From da455124d257c0de619f338af5463c2c91a0f5b9 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 17 Nov 2012 12:03:32 +0000 Subject: [PATCH] Unordered: Try to make the piecewise_construct emulation a little more readable. [SVN r81392] --- include/boost/unordered/detail/allocate.hpp | 69 +++++++++++---------- test/unordered/insert_tests.cpp | 14 ++++- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp index 42814d9f..dd47ce7a 100644 --- a/include/boost/unordered/detail/allocate.hpp +++ b/include/boost/unordered/detail/allocate.hpp @@ -921,37 +921,26 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) #endif //////////////////////////////////////////////////////////////////////////// - // SFINAE traits for construction. + // Trait to check for piecewise construction. - // Decide which construction method to use for a three argument - // call. Note that this is difficult to do using overloads because - // the arguments are packed into 'emplace_args3'. - // - // The decision is made on the first argument. - - - template - struct check3_base { + template + struct use_piecewise { static choice1::type test(choice1, boost::unordered::piecewise_construct_t); - static choice3::type test(choice3, ...); + static choice2::type test(choice2, ...); - enum { value = + enum { value = sizeof(choice1::type) == sizeof(test(choose(), boost::unordered::detail::make())) }; }; - template - struct piecewise3 { - enum { value = check3_base::value == sizeof(choice1::type) }; - }; - -// TODO: Full construct? #if !defined(BOOST_NO_VARIADIC_TEMPLATES) //////////////////////////////////////////////////////////////////////////// // Construct from variadic parameters + // For the standard pair constructor. + template inline void construct_value_impl(Alloc& alloc, T* address, BOOST_FWD_REF(Args)... args) @@ -960,9 +949,14 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) address, boost::forward(args)...); } + // Special case for piece_construct + // + // TODO: When possible, it might be better to use std::pair's + // constructor for std::piece_construct with std::tuple. + template - inline typename enable_if, void>::type + inline typename enable_if, void>::type construct_value_impl(Alloc& alloc, std::pair* address, BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { @@ -977,20 +971,8 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) //////////////////////////////////////////////////////////////////////////////// // Construct from emplace_args -#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \ - template < \ - typename Alloc, typename T, \ - BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \ - > \ - inline void construct_value_impl(Alloc&, T* address, \ - boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \ - BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \ - > const& args) \ - { \ - new((void*) address) T( \ - BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \ - args.a)); \ - } + // Explicitly write out first three overloads for the sake of sane + // error messages. template inline void construct_value_impl(Alloc&, T* address, @@ -1020,16 +1002,35 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) ); } + // Use a macro for the rest. + +#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \ + template < \ + typename Alloc, typename T, \ + BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \ + > \ + inline void construct_value_impl(Alloc&, T* address, \ + boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \ + BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \ + > const& args) \ + { \ + new((void*) 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, _) #undef BOOST_UNORDERED_CONSTRUCT_IMPL + // Construct with piece_construct + template inline void construct_value_impl(Alloc& alloc, std::pair* address, boost::unordered::detail::emplace_args3 const& args, - typename enable_if, void*>::type = 0) + typename enable_if, void*>::type = 0) { boost::unordered::detail::construct_from_tuple(alloc, boost::addressof(address->first), args.a1); diff --git a/test/unordered/insert_tests.cpp b/test/unordered/insert_tests.cpp index df0395fc..a789bf01 100644 --- a/test/unordered/insert_tests.cpp +++ b/test/unordered/insert_tests.cpp @@ -691,6 +691,13 @@ UNORDERED_AUTO_TEST(set_emplace_test) BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check); } +struct derived_from_piecewise_construct_t : + boost::unordered::piecewise_construct_t {}; + +derived_from_piecewise_construct_t piecewise_rvalue() { + return derived_from_piecewise_construct_t(); +} + UNORDERED_AUTO_TEST(map_emplace_test2) { boost::unordered_map x; @@ -703,9 +710,14 @@ UNORDERED_AUTO_TEST(map_emplace_test2) BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() && x.find(overloaded_constructor(1))->second == overloaded_constructor()); - x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(2,3), boost::make_tuple(4,5,6)); + x.emplace(piecewise_rvalue(), boost::make_tuple(2,3), boost::make_tuple(4,5,6)); BOOST_TEST(x.find(overloaded_constructor(2,3)) != x.end() && x.find(overloaded_constructor(2,3))->second == overloaded_constructor(4,5,6)); + + derived_from_piecewise_construct_t d; + x.emplace(d, boost::make_tuple(9,3,1), boost::make_tuple(10)); + BOOST_TEST(x.find(overloaded_constructor(9,3,1)) != x.end() && + x.find(overloaded_constructor(9,3,1))->second == overloaded_constructor(10)); } UNORDERED_AUTO_TEST(set_emplace_test2)