Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r74119 - in trunk: boost/unordered/detail libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2011-08-29 05:40:42


Author: danieljames
Date: 2011-08-29 05:40:41 EDT (Mon, 29 Aug 2011)
New Revision: 74119
URL: http://svn.boost.org/trac/boost/changeset/74119

Log:
Unordered: Support piecewise pair construction.

Will need to deprecate the old variadic style pair construction, also
should look into extract_key, was written for compatibility with older
compilers that are no longer supported.
Text files modified:
   trunk/boost/unordered/detail/buckets.hpp | 54 +++++++++++++++++++++++++++++-
   trunk/boost/unordered/detail/extract_key.hpp | 70 ++++++++++++++++++++++++++++++++++++++-
   trunk/boost/unordered/detail/fwd.hpp | 3 +
   trunk/boost/unordered/detail/util.hpp | 13 +++++-
   trunk/libs/unordered/test/unordered/insert_tests.cpp | 33 +++++++++++++++++-
   trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp | 48 ++++++++++++++++++++++++++
   6 files changed, 211 insertions(+), 10 deletions(-)

Modified: trunk/boost/unordered/detail/buckets.hpp
==============================================================================
--- trunk/boost/unordered/detail/buckets.hpp (original)
+++ trunk/boost/unordered/detail/buckets.hpp 2011-08-29 05:40:41 EDT (Mon, 29 Aug 2011)
@@ -515,7 +515,39 @@
     };
 
     ////////////////////////////////////////////////////////////////////////////
- // Node Constructors
+ //
+ // Value Construction
+
+#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
+ template<typename T> \
+ 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<typename T BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename Arg)>\
+ void construct_from_tuple(T* ptr, \
+ namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, Arg)> 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<n>(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
 
     template <typename T, typename Arg1 = void>
     struct emulated_pair_constructor
@@ -587,6 +619,15 @@
                 std::forward<Arg2>(arg2), std::forward<Args>(args)...));
     }
 
+ template <class T, class Tuple1, class Tuple2>
+ inline typename boost::enable_if<emulated_pair_constructor<T> >::type
+ construct_impl(void* address, boost::unordered::piecewise_construct_t,
+ Tuple1&& tuple1, Tuple2&& tuple2)
+ {
+ construct_from_tuple(&static_cast<T*>(address)->first, tuple1);
+ construct_from_tuple(&static_cast<T*>(address)->second, tuple2);
+ }
+
 #else
 
     template <class T, class Arg1>
@@ -612,7 +653,16 @@
     {
         new(address) T(boost::forward<Arg1>(a1), boost::forward<Arg2>(a2));
     }
-
+
+ template <class T, class Tuple1, class Tuple2>
+ inline typename boost::enable_if<emulated_pair_constructor<T> >::type
+ construct_impl(void* address, boost::unordered::piecewise_construct_t,
+ BOOST_FWD_REF(Tuple1) tuple1, BOOST_FWD_REF(Tuple2) tuple2)
+ {
+ construct_from_tuple(&static_cast<T*>(address)->first, tuple1);
+ construct_from_tuple(&static_cast<T*>(address)->second, tuple2);
+ }
+
 #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
     template < \
         class T, \

Modified: trunk/boost/unordered/detail/extract_key.hpp
==============================================================================
--- trunk/boost/unordered/detail/extract_key.hpp (original)
+++ trunk/boost/unordered/detail/extract_key.hpp 2011-08-29 05:40:41 EDT (Mon, 29 Aug 2011)
@@ -27,6 +27,19 @@
         template <class T> no_key(T const&) {}
     };
 
+ template <typename Key, typename T>
+ struct is_key {
+ template <typename T2>
+ static choice1::type test(T2 const&);
+ static choice2::type test(Key const&);
+
+ enum { value = sizeof(test(make<T>())) == sizeof(choice2::type) };
+
+ typedef BOOST_DEDUCED_TYPENAME
+ boost::detail::if_true<value>::
+ BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
+ };
+
     template <class ValueType>
     struct set_extractor
     {
@@ -64,8 +77,8 @@
             return no_key();
         }
 
- template <class Arg>
- static no_key extract(Arg const&, Arg const&)
+ template <class Arg1, class Arg2>
+ static no_key extract(Arg1 const&, Arg2 const&)
         {
             return no_key();
         }
@@ -127,6 +140,7 @@
             return no_key();
         }
 #else
+
         template <class Arg1>
         static key_type const& extract(key_type const& k, Arg1 const&)
         {
@@ -151,6 +165,58 @@
         }
 #endif
 
+ choice1::type is_key_test(key_type const&);
+ template <typename T>
+ choice2::type is_key_test(T const&);
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
+#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
+ template <typename T2> \
+ static no_key extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<> const&, T2&&) \
+ { \
+ return no_key(); \
+ } \
+ \
+ template <typename T, typename T2> \
+ static BOOST_DEDUCED_TYPENAME is_key<key_type, T>::type \
+ extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<T> const& k, T2&&) \
+ { \
+ return BOOST_DEDUCED_TYPENAME is_key<key_type, T>::type( \
+ namespace_::get<0>(k)); \
+ }
+
+#else
+
+#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
+ static no_key extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<> const&) \
+ { \
+ return no_key(); \
+ } \
+ \
+ template <typename T> \
+ static BOOST_DEDUCED_TYPENAME is_key<key_type, T>::type \
+ extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<T> const& k) \
+ { \
+ return BOOST_DEDUCED_TYPENAME is_key<key_type, T>::type( \
+ namespace_::get<0>(k)); \
+ }
+
+#endif
+
+BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
+
+#if !defined(BOOST_NO_0X_HDR_TUPLE)
+BOOST_UNORDERED_KEY_FROM_TUPLE(std)
+#elif defined(BOOST_HAS_TR1_TUPLE)
+BOOST_UNORDERED_KEY_FROM_TUPLE(std::tr1)
+#endif
+
+
         static bool compare_mapped(value_type const& x, value_type const& y)
         {
             return x.second == y.second;

Modified: trunk/boost/unordered/detail/fwd.hpp
==============================================================================
--- trunk/boost/unordered/detail/fwd.hpp (original)
+++ trunk/boost/unordered/detail/fwd.hpp 2011-08-29 05:40:41 EDT (Mon, 29 Aug 2011)
@@ -44,6 +44,9 @@
         class P = std::equal_to<T>,
         class A = std::allocator<T> >
     class unordered_multiset;
+
+ struct piecewise_construct_t {};
+ const piecewise_construct_t piecewise_construct = piecewise_construct_t();
 }
 }
 

Modified: trunk/boost/unordered/detail/util.hpp
==============================================================================
--- trunk/boost/unordered/detail/util.hpp (original)
+++ trunk/boost/unordered/detail/util.hpp 2011-08-29 05:40:41 EDT (Mon, 29 Aug 2011)
@@ -24,12 +24,19 @@
 #include <boost/type_traits/remove_const.hpp>
 #include <boost/type_traits/is_empty.hpp>
 #include <boost/throw_exception.hpp>
-#include <boost/unordered/detail/allocator_helpers.hpp>
+#include <boost/move/move.hpp>
+#include <boost/swap.hpp>
 #include <boost/preprocessor/seq/size.hpp>
 #include <boost/preprocessor/seq/enum.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/move/move.hpp>
-#include <boost/swap.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/tuple/tuple.hpp>
+#if !defined(BOOST_NO_0X_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
+#include <tuple>
+#endif
+#include <boost/unordered/detail/allocator_helpers.hpp>
 
 // Template parameters:
 //

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 2011-08-29 05:40:41 EDT (Mon, 29 Aug 2011)
@@ -537,8 +537,6 @@
     }
 };
 
-// This will actually be deprecated pretty soon.
-
 UNORDERED_AUTO_TEST(map_emplace_test)
 {
     boost::unordered_map<int, overloaded_constructor> x;
@@ -593,6 +591,37 @@
     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
 }
 
+UNORDERED_AUTO_TEST(map_emplace_test2)
+{
+ boost::unordered_map<overloaded_constructor, overloaded_constructor> x;
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(), boost::make_tuple());
+ BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1), boost::make_tuple());
+ 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));
+ BOOST_TEST(x.find(overloaded_constructor(2,3)) != x.end() &&
+ x.find(overloaded_constructor(2,3))->second == overloaded_constructor(4,5,6));
+}
+
+UNORDERED_AUTO_TEST(set_emplace_test2)
+{
+ boost::unordered_set<std::pair<overloaded_constructor, overloaded_constructor> > x;
+ std::pair<overloaded_constructor, overloaded_constructor> check;
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(), boost::make_tuple());
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+
+ x.clear();
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1), boost::make_tuple(2,3));
+ check = std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));;
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+}
+
 }
 
 RUN_TESTS()

Modified: trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp
==============================================================================
--- trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp (original)
+++ trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp 2011-08-29 05:40:41 EDT (Mon, 29 Aug 2011)
@@ -1,4 +1,4 @@
-
+#include <iostream>
 // Copyright 2006-2009 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)
@@ -327,6 +327,13 @@
         x.emplace();
         COPY_COUNT(2); MOVE_COUNT(0);
 
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ boost::make_tuple(),
+ boost::make_tuple());
+ COPY_COUNT(2); MOVE_COUNT(0);
+
+
         //
         // 1 argument
         //
@@ -345,19 +352,23 @@
     (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
     (defined(BOOST_MSVC) && BOOST_MSVC >= 1600 ) || \
     (!defined(__GNUC__) && !defined(BOOST_MSVC))
+
         count_copies part;
         reset();
         std::pair<count_copies const&, count_copies const&> a_ref(part, part);
         x.emplace(a_ref);
         COPY_COUNT(2); MOVE_COUNT(0);
+
 #endif
 
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
         // No move should take place.
         // (since a is already in the container)
         reset();
         x.emplace(std::move(a));
         COPY_COUNT(0); MOVE_COUNT(0);
+
 #endif
 
         //
@@ -382,6 +393,41 @@
         reset();
         x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
         COPY_COUNT(2); MOVE_COUNT(0);
+
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ boost::make_tuple(boost::ref(b.first)),
+ boost::make_tuple(boost::ref(b.second)));
+ COPY_COUNT(0); MOVE_COUNT(0);
+
+#if !defined(BOOST_NO_0X_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
+
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::make_tuple(std::ref(b.first)),
+ std::make_tuple(std::ref(b.second)));
+ COPY_COUNT(0); MOVE_COUNT(0);
+
+ // first is const so it is copied.
+ // second is not const so it is moved.
+ std::pair<count_copies const, count_copies> move_source;
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::make_tuple(std::move(move_source.first)),
+ std::make_tuple(std::move(move_source.second)));
+ COPY_COUNT(1); MOVE_COUNT(1);
+
+#if defined(__GNUC__) && __GNUC__ > 4 || \
+ defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::forward_as_tuple(b.first),
+ std::forward_as_tuple(b.second));
+ COPY_COUNT(0); MOVE_COUNT(0);
+#endif
+
+#endif
+
     }
 }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk