$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r81392 - in trunk: boost/unordered/detail libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2012-11-17 07:03:32
Author: danieljames
Date: 2012-11-17 07:03:32 EST (Sat, 17 Nov 2012)
New Revision: 81392
URL: http://svn.boost.org/trac/boost/changeset/81392
Log:
Unordered: Try to make the piecewise_construct emulation a little more readable.
Text files modified: 
   trunk/boost/unordered/detail/allocate.hpp            |    69 ++++++++++++++++++++------------------- 
   trunk/libs/unordered/test/unordered/insert_tests.cpp |    14 +++++++                                 
   2 files changed, 48 insertions(+), 35 deletions(-)
Modified: trunk/boost/unordered/detail/allocate.hpp
==============================================================================
--- trunk/boost/unordered/detail/allocate.hpp	(original)
+++ trunk/boost/unordered/detail/allocate.hpp	2012-11-17 07:03:32 EST (Sat, 17 Nov 2012)
@@ -921,37 +921,26 @@
 #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 <typename A, typename B, typename A0>
-    struct check3_base {
+    template <typename A0>
+    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<A0>())) };
     };
 
-    template <typename A, typename B, typename A0>
-    struct piecewise3 {
-        enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
-    };
-
-// TODO: Full construct?
 #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
 
     ////////////////////////////////////////////////////////////////////////////
     // Construct from variadic parameters
 
+    // For the standard pair constructor.
+
     template <typename Alloc, typename T, typename... Args>
     inline void construct_value_impl(Alloc& alloc, T* address,
         BOOST_FWD_REF(Args)... args)
@@ -960,9 +949,14 @@
             address, boost::forward<Args>(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 <typename Alloc, typename A, typename B,
         typename A0, typename A1, typename A2>
-    inline typename enable_if<piecewise3<A, B, A0>, void>::type
+    inline typename enable_if<use_piecewise<A0>, void>::type
         construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
             BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
     {
@@ -977,20 +971,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 // 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 <typename Alloc, typename T, typename A0>
     inline void construct_value_impl(Alloc&, T* address,
@@ -1020,16 +1002,35 @@
         );
     }
 
+    // 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 <typename Alloc, typename A, typename B,
         typename A0, typename A1, typename A2>
     inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
             boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
-            typename enable_if<piecewise3<A, B, A0>, void*>::type = 0)
+            typename enable_if<use_piecewise<A0>, void*>::type = 0)
     {
         boost::unordered::detail::construct_from_tuple(alloc,
             boost::addressof(address->first), args.a1);
Modified: trunk/libs/unordered/test/unordered/insert_tests.cpp
==============================================================================
--- trunk/libs/unordered/test/unordered/insert_tests.cpp	(original)
+++ trunk/libs/unordered/test/unordered/insert_tests.cpp	2012-11-17 07:03:32 EST (Sat, 17 Nov 2012)
@@ -691,6 +691,13 @@
     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<overloaded_constructor, overloaded_constructor> x;
@@ -703,9 +710,14 @@
     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)