mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Implement full extract_key for compilers without SFINAE and variadic
templates. [SVN r52393]
This commit is contained in:
@ -28,20 +28,16 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
|
||||
#include <boost/mpl/aux_/config/eti.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0582)
|
||||
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
|
||||
#else
|
||||
|
@ -1428,7 +1428,18 @@ namespace boost {
|
||||
|
||||
// key extractors
|
||||
|
||||
struct no_key {
|
||||
no_key() {}
|
||||
template <class T> 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<value_type>*)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 <typename Arg1, typename... Args>
|
||||
static typename boost::enable_if<
|
||||
boost::mpl::and_<
|
||||
boost::mpl::not_<boost::is_same<key_type, value_type> >,
|
||||
boost::is_same<Arg1, key_type>
|
||||
>,
|
||||
key_type>::type const& extract_key(Arg1 const& k, Args const&...)
|
||||
|
||||
template <typename Arg>
|
||||
static BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::if_<boost::is_same<Arg, key_type>, key_type const&, no_key>::type
|
||||
extract_key(Arg const& k)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
template <typename First, typename Second>
|
||||
static typename boost::enable_if<
|
||||
boost::mpl::and_<
|
||||
boost::mpl::not_<boost::is_same<key_type, value_type> >,
|
||||
boost::is_same<key_type,
|
||||
typename boost::remove_const<
|
||||
typename boost::remove_reference<First>::type
|
||||
>::type>
|
||||
>,
|
||||
key_type>::type const& extract_key(std::pair<First, Second> const& v)
|
||||
static BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::if_<
|
||||
boost::mpl::and_<
|
||||
boost::mpl::not_<boost::is_same<key_type, value_type> >,
|
||||
boost::is_same<key_type,
|
||||
typename boost::remove_const<
|
||||
typename boost::remove_reference<First>::type
|
||||
>::type>
|
||||
>,
|
||||
key_type const&, no_key
|
||||
>::type extract_key(std::pair<First, Second> const& v)
|
||||
{
|
||||
return v.first;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static no_key extract_key(Args const&...)
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
static BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::if_<
|
||||
boost::mpl::and_<
|
||||
boost::mpl::not_<boost::is_same<value_type, key_type> >,
|
||||
boost::is_same<Arg, key_type>
|
||||
>,
|
||||
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 <typename InputIterator>
|
||||
void insert_range(InputIterator i, InputIterator j)
|
||||
{
|
||||
if(i != j)
|
||||
return insert_range_impl(extract_key(*i), i, j);
|
||||
}
|
||||
|
||||
template <typename InputIterator>
|
||||
void insert_range_impl(key_type const&, InputIterator i, InputIterator j)
|
||||
{
|
||||
node_constructor a(data_.allocators_);
|
||||
|
||||
@ -1992,6 +2016,36 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputIterator>
|
||||
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:
|
||||
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user