|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r74068 - in trunk: boost/unordered/detail libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2011-08-26 04:12:11
Author: danieljames
Date: 2011-08-26 04:12:08 EDT (Fri, 26 Aug 2011)
New Revision: 74068
URL: http://svn.boost.org/trac/boost/changeset/74068
Log:
Unordered: More robust construct_impl.
Text files modified:
trunk/boost/unordered/detail/buckets.hpp | 152 ++++++++++++++++++++++++++++++++-------
trunk/libs/unordered/test/unordered/insert_tests.cpp | 40 ++++++++++
2 files changed, 162 insertions(+), 30 deletions(-)
Modified: trunk/boost/unordered/detail/buckets.hpp
==============================================================================
--- trunk/boost/unordered/detail/buckets.hpp (original)
+++ trunk/boost/unordered/detail/buckets.hpp 2011-08-26 04:12:08 EDT (Fri, 26 Aug 2011)
@@ -517,44 +517,137 @@
////////////////////////////////////////////////////////////////////////////
// Node Constructors
+ template <typename T, typename Arg1 = void>
+ struct emulated_pair_constructor
+ {
+ enum { value = false };
+ };
+
+ template <typename A, typename B>
+ struct emulated_pair_constructor<std::pair<A, B>, void>
+ {
+ enum { value = true };
+ };
+
+ template <typename A, typename B, typename Value>
+ struct emulated_pair_constructor<std::pair<A, B>, Value>
+ {
+ static choice1::type check(choice1, std::pair<A, B> const&);
+ static choice2::type check(choice2, A const&);
+
+ enum { value = sizeof(check(choose(), make<Value>())) - 1 };
+ };
+
+ template <class T>
+ inline void construct_impl(void* address)
+ {
+ new(address) T();
+ }
+
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
- template <class T, class... Args>
- inline void construct_impl(T*, void* address, Args&&... args)
+ template <class T, class Arg1>
+ inline void construct_impl(
+ typename boost::disable_if<emulated_pair_constructor<T, Arg1>,
+ void*>::type address,
+ Arg1&& a1)
+ {
+ new(address) T(boost::forward<Arg1>(a1));
+ }
+
+ template <class T, class Arg1>
+ inline void construct_impl(
+ typename boost::enable_if<emulated_pair_constructor<T, Arg1>,
+ void*>::type address,
+ Arg1&& a1)
+ {
+ new(address) T(boost::forward<Arg1>(a1), typename T::second_type());
+ }
+
+ template <class T, class Arg1, class Arg2>
+ inline void construct_impl(void* address, Arg1&& a1, Arg2&& a2)
{
- new(address) T(std::forward<Args>(args)...);
+ new(address) T(std::forward<Arg1, Arg2>(a1, a2));
+ }
+
+ template <class T, class Arg1, class Arg2, class... Args>
+ inline typename boost::disable_if<emulated_pair_constructor<T>, void>::type
+ construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
+ {
+ new(address) T(std::forward<Arg1, Arg2, Args>(arg1, arg2, args)...);
+ }
+
+ template <class T, class Arg1, class Arg2, class... Args>
+ inline typename boost::enable_if<emulated_pair_constructor<T>, void>::type
+ construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
+ {
+ new(address) T(std::forward<Arg1>(arg1),
+ typename T::second_type(std::forward<Arg2, Args>(arg2, args)...));
}
#else
-#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
- template < \
- class T, \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
- > \
- inline void construct_impl( \
- T*, void* address, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
- ) \
- { \
- new(address) T( \
- BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
- } \
- \
- template <class First, class Second, class Key, \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
- > \
- inline void construct_impl( \
- std::pair<First, Second>*, void* address, \
- Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
- { \
- new(address) std::pair<First, Second>(k, \
- Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
+ template <class T, class Arg1>
+ inline BOOST_DEDUCED_TYPENAME boost::disable_if<emulated_pair_constructor<T, Arg1>, void>::type
+ construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
+ {
+ new(address) T(boost::forward<Arg1>(a1));
+ }
+
+ template <class T, class Arg1>
+ inline BOOST_DEDUCED_TYPENAME boost::enable_if<emulated_pair_constructor<T, Arg1>, void>::type
+ construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
+ {
+ new(address) T(
+ boost::forward<Arg1>(a1),
+ BOOST_DEDUCED_TYPENAME T::second_type()
+ );
}
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ template <class T, class Arg1, class Arg2>
+ inline void construct_impl(void* address,
+ BOOST_FWD_REF(Arg1) a1, BOOST_FWD_REF(Arg2) a2)
+ {
+ new(address) T(boost::forward<Arg1>(a1), boost::forward<Arg2>(a2));
+ }
+
+#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
+ template < \
+ class T, \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
+ > \
+ inline void construct_impl( \
+ BOOST_DEDUCED_TYPENAME \
+ boost::disable_if<emulated_pair_constructor<T>, void*>::type \
+ 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_UNORDERED_CONSTRUCT_IMPL, _)
+#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
+ template <class T, class Key, \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
+ > \
+ inline void construct_impl( \
+ BOOST_DEDUCED_TYPENAME \
+ boost::enable_if<emulated_pair_constructor<T>, void*>::type \
+ address, \
+ Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
+ { \
+ new(address) T(k, \
+ BOOST_DEDUCED_TYPENAME \
+ T::second_type(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
+
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
#endif
@@ -594,7 +687,7 @@
void construct(Args&&... args)
{
construct_preamble();
- construct_impl((value_type*) 0, node_->address(),
+ construct_impl<value_type>(node_->address(),
std::forward<Args>(args)...);
value_constructed_ = true;
}
@@ -609,8 +702,7 @@
) \
{ \
construct_preamble(); \
- construct_impl( \
- (value_type*) 0, node_->address(), \
+ construct_impl<value_type>(node_->address(), \
BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
); \
value_constructed_ = true; \
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-26 04:12:08 EDT (Fri, 26 Aug 2011)
@@ -514,6 +514,46 @@
#endif
+struct overloaded_constructor
+{
+ overloaded_constructor(int x = 1, int y = 2, int z = 3)
+ : x(x), y(y), z(z) {}
+
+ int x, y, z;
+
+ bool operator==(overloaded_constructor const& rhs) const
+ {
+ return x == rhs.x && y == rhs.y && z == rhs.z;
+ }
+};
+
+// This will actually be deprecated pretty soon.
+
+UNORDERED_AUTO_TEST(map_emplace_test)
+{
+ boost::unordered_map<int, overloaded_constructor> x;
+
+ x.emplace();
+ BOOST_TEST(x.find(0) != x.end() &&
+ x.find(0)->second == overloaded_constructor());
+
+ x.emplace(1);
+ BOOST_TEST(x.find(1) != x.end() &&
+ x.find(1)->second == overloaded_constructor());
+
+ x.emplace(2, 3);
+ BOOST_TEST(x.find(2) != x.end() &&
+ x.find(2)->second == overloaded_constructor(3));
+
+ x.emplace(4, 5, 6);
+ BOOST_TEST(x.find(4) != x.end() &&
+ x.find(4)->second == overloaded_constructor(5, 6));
+
+ x.emplace(7, 8, 9, 10);
+ BOOST_TEST(x.find(7) != x.end() &&
+ x.find(7)->second == overloaded_constructor(8, 9, 10));
+}
+
}
RUN_TESTS()
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