From a07e4c5810f258d0c135237a87c5117c9ec4ff8a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 14 Apr 2009 17:23:37 +0000 Subject: [PATCH] Implement full extract_key for compilers without SFINAE and variadic templates. [SVN r52393] --- include/boost/unordered/detail/hash_table.hpp | 10 +- .../unordered/detail/hash_table_impl.hpp | 100 ++++++++++++++---- test/unordered/unnecessary_copy_tests.cpp | 2 + 3 files changed, 82 insertions(+), 30 deletions(-) diff --git a/include/boost/unordered/detail/hash_table.hpp b/include/boost/unordered/detail/hash_table.hpp index c6ded509..26a0455a 100644 --- a/include/boost/unordered/detail/hash_table.hpp +++ b/include/boost/unordered/detail/hash_table.hpp @@ -28,20 +28,16 @@ #include #include #include +#include +#include #include #include +#include #include #include #include -#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL) -#include -#include -#include -#include -#endif - #if BOOST_WORKAROUND(__BORLANDC__, <= 0x0582) #define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x) #else diff --git a/include/boost/unordered/detail/hash_table_impl.hpp b/include/boost/unordered/detail/hash_table_impl.hpp index e7cdc5b9..65966127 100644 --- a/include/boost/unordered/detail/hash_table_impl.hpp +++ b/include/boost/unordered/detail/hash_table_impl.hpp @@ -1428,7 +1428,18 @@ namespace boost { // key extractors + struct no_key { + no_key() {} + template no_key(T const&) {} + }; + // no throw + + static no_key extract_key() + { + return no_key(); + } + static key_type const& extract_key(value_type const& v) { return extract(v, (type_wrapper*)0); @@ -1445,40 +1456,46 @@ namespace boost { { return v.first; } - -#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL) - struct no_key {}; - - template - static typename boost::enable_if< - boost::mpl::and_< - boost::mpl::not_ >, - boost::is_same - >, - key_type>::type const& extract_key(Arg1 const& k, Args const&...) + + template + static BOOST_DEDUCED_TYPENAME + boost::mpl::if_, key_type const&, no_key>::type + extract_key(Arg const& k) { return k; } template - static typename boost::enable_if< - boost::mpl::and_< - boost::mpl::not_ >, - boost::is_same::type - >::type> - >, - key_type>::type const& extract_key(std::pair const& v) + static BOOST_DEDUCED_TYPENAME + boost::mpl::if_< + boost::mpl::and_< + boost::mpl::not_ >, + boost::is_same::type + >::type> + >, + key_type const&, no_key + >::type extract_key(std::pair const& v) { return v.first; } - template - static no_key extract_key(Args const&...) +#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL) + + template + static BOOST_DEDUCED_TYPENAME + boost::mpl::if_< + boost::mpl::and_< + boost::mpl::not_ >, + boost::is_same + >, + key_type const&, no_key + >::type extract_key(Arg const& k, Args const&...) { - return no_key(); + return k; } + #endif public: @@ -1963,6 +1980,13 @@ namespace boost { // strong otherwise template void insert_range(InputIterator i, InputIterator j) + { + if(i != j) + return insert_range_impl(extract_key(*i), i, j); + } + + template + void insert_range_impl(key_type const&, InputIterator i, InputIterator j) { node_constructor a(data_.allocators_); @@ -1992,6 +2016,36 @@ namespace boost { } } } + + template + void insert_range_impl(no_key, InputIterator i, InputIterator j) + { + node_constructor a(data_.allocators_); + + for (; i != j; ++i) { + // No side effects in this initial code + a.construct(*i); + key_type const& k = extract_key(a.get()->value()); + size_type hash_value = hash_function()(extract_key(k)); + bucket_ptr bucket = data_.bucket_ptr_from_hash(hash_value); + link_ptr pos = find_iterator(bucket, k); + + if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) { + // Doesn't already exist, add to bucket. + // Side effects only in this block. + + // reserve has basic exception safety if the hash function + // throws, strong otherwise. + if(size() + 1 >= max_load_) { + reserve_for_insert(size() + insert_size(i, j)); + bucket = data_.bucket_ptr_from_hash(hash_value); + } + + // Nothing after this point can throw. + data_.link_node_in_bucket(a, bucket); + } + } + } #endif public: diff --git a/test/unordered/unnecessary_copy_tests.cpp b/test/unordered/unnecessary_copy_tests.cpp index df4baf3c..d2ab8629 100644 --- a/test/unordered/unnecessary_copy_tests.cpp +++ b/test/unordered/unnecessary_copy_tests.cpp @@ -192,6 +192,8 @@ namespace unnecessary_copy_tests // The container will have to create b copy in order to compare with // the existing element. + // + // Note to self: If copy_count == 0 it's an error not an optimization. reset(); x.emplace(b, b);