forked from boostorg/unordered
Anotehr overhaul. Can now use `void_pointer` for links between nodes, although it doesn't as I don't think `void_pointer` support is strong enough in existing allocators. Also no longer relies on using base pointers for custome pointer types. And scaled back member function detection to just detect if an allocator has a member, not what its signature is. I found that the trait could be confused by ambiguous overloads. This might be fixable. Better documentation of C++11 compliance to come. [SVN r74859]
1359 lines
40 KiB
C++
1359 lines
40 KiB
C++
|
|
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
|
// Copyright (C) 2005-2011 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)
|
|
|
|
// See http://www.boost.org/libs/unordered for documentation
|
|
|
|
#ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|
|
#define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
|
# pragma once
|
|
#endif
|
|
|
|
#include <boost/unordered/unordered_set_fwd.hpp>
|
|
#include <boost/unordered/detail/allocator_helpers.hpp>
|
|
#include <boost/unordered/detail/equivalent.hpp>
|
|
#include <boost/unordered/detail/unique.hpp>
|
|
#include <boost/unordered/detail/util.hpp>
|
|
#include <boost/functional/hash.hpp>
|
|
#include <boost/move/move.hpp>
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
#include <initializer_list>
|
|
#endif
|
|
|
|
#if defined(BOOST_MSVC)
|
|
#pragma warning(push)
|
|
#if BOOST_MSVC >= 1400
|
|
#pragma warning(disable:4396) //the inline specifier cannot be used when a
|
|
// friend declaration refers to a specialization
|
|
// of a function template
|
|
#endif
|
|
#endif
|
|
|
|
namespace boost
|
|
{
|
|
namespace unordered
|
|
{
|
|
template <class T, class H, class P, class A>
|
|
class unordered_set
|
|
{
|
|
BOOST_COPYABLE_AND_MOVABLE(unordered_set)
|
|
public:
|
|
|
|
typedef T key_type;
|
|
typedef T value_type;
|
|
typedef H hasher;
|
|
typedef P key_equal;
|
|
typedef A allocator_type;
|
|
|
|
private:
|
|
|
|
typedef typename boost::unordered::detail::rebind_wrap<
|
|
allocator_type, value_type>::type
|
|
value_allocator;
|
|
|
|
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
|
allocator_traits;
|
|
|
|
typedef boost::unordered::detail::set<value_allocator, H, P>
|
|
types;
|
|
typedef typename types::table table;
|
|
|
|
public:
|
|
|
|
typedef typename allocator_traits::pointer pointer;
|
|
typedef typename allocator_traits::const_pointer const_pointer;
|
|
|
|
typedef value_type& reference;
|
|
typedef value_type const& const_reference;
|
|
|
|
typedef std::size_t size_type;
|
|
typedef std::ptrdiff_t difference_type;
|
|
|
|
typedef typename table::cl_iterator const_local_iterator;
|
|
typedef typename table::cl_iterator local_iterator;
|
|
typedef typename table::c_iterator const_iterator;
|
|
typedef typename table::c_iterator iterator;
|
|
|
|
private:
|
|
|
|
table table_;
|
|
|
|
public:
|
|
|
|
// constructors
|
|
|
|
explicit unordered_set(
|
|
size_type = boost::unordered::detail::default_bucket_count,
|
|
const hasher& = hasher(),
|
|
const key_equal& = key_equal(),
|
|
const allocator_type& = allocator_type());
|
|
|
|
explicit unordered_set(allocator_type const&);
|
|
|
|
template <class InputIt>
|
|
unordered_set(InputIt, InputIt);
|
|
|
|
template <class InputIt>
|
|
unordered_set(
|
|
InputIt, InputIt,
|
|
size_type,
|
|
const hasher& = hasher(),
|
|
const key_equal& = key_equal());
|
|
|
|
template <class InputIt>
|
|
unordered_set(
|
|
InputIt, InputIt,
|
|
size_type,
|
|
const hasher&,
|
|
const key_equal&,
|
|
const allocator_type&);
|
|
|
|
// copy/move constructors
|
|
|
|
unordered_set(unordered_set const&);
|
|
|
|
unordered_set(unordered_set const&, allocator_type const&);
|
|
|
|
unordered_set(BOOST_RV_REF(unordered_set) other)
|
|
: table_(other.table_, boost::unordered::detail::move_tag())
|
|
{
|
|
}
|
|
|
|
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
|
unordered_set(unordered_set&&, allocator_type const&);
|
|
#endif
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
unordered_set(
|
|
std::initializer_list<value_type>,
|
|
size_type = boost::unordered::detail::default_bucket_count,
|
|
const hasher& = hasher(),
|
|
const key_equal&l = key_equal(),
|
|
const allocator_type& = allocator_type());
|
|
#endif
|
|
|
|
// Destructor
|
|
|
|
~unordered_set();
|
|
|
|
// Assign
|
|
|
|
unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
|
|
{
|
|
table_.assign(x.table_);
|
|
return *this;
|
|
}
|
|
|
|
unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
|
|
{
|
|
table_.move_assign(x.table_);
|
|
return *this;
|
|
}
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
unordered_set& operator=(std::initializer_list<value_type>);
|
|
#endif
|
|
|
|
allocator_type get_allocator() const
|
|
{
|
|
return table_.node_alloc();
|
|
}
|
|
|
|
// size and capacity
|
|
|
|
bool empty() const
|
|
{
|
|
return table_.size_ == 0;
|
|
}
|
|
|
|
size_type size() const
|
|
{
|
|
return table_.size_;
|
|
}
|
|
|
|
size_type max_size() const;
|
|
|
|
// iterators
|
|
|
|
iterator begin()
|
|
{
|
|
return iterator(table_.begin());
|
|
}
|
|
|
|
const_iterator begin() const
|
|
{
|
|
return const_iterator(table_.begin());
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return iterator();
|
|
}
|
|
|
|
const_iterator end() const
|
|
{
|
|
return const_iterator();
|
|
}
|
|
|
|
const_iterator cbegin() const
|
|
{
|
|
return const_iterator(table_.begin());
|
|
}
|
|
|
|
const_iterator cend() const
|
|
{
|
|
return const_iterator();
|
|
}
|
|
|
|
// emplace
|
|
|
|
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
|
template <class... Args>
|
|
std::pair<iterator, bool> emplace(Args&&... args)
|
|
{
|
|
return table_.emplace(std::forward<Args>(args)...);
|
|
}
|
|
|
|
template <class... Args>
|
|
iterator emplace_hint(const_iterator, Args&&... args)
|
|
{
|
|
return iterator(table_.emplace(std::forward<Args>(args)...).first);
|
|
}
|
|
#else
|
|
|
|
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
|
template < \
|
|
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
|
> \
|
|
std::pair<iterator, bool> emplace( \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
|
) \
|
|
{ \
|
|
return table_.emplace( \
|
|
boost::unordered::detail::create_emplace_args( \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
|
a) \
|
|
)); \
|
|
} \
|
|
\
|
|
template < \
|
|
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
|
> \
|
|
iterator emplace_hint( \
|
|
const_iterator, \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
|
) \
|
|
{ \
|
|
return iterator(table_.emplace( \
|
|
boost::unordered::detail::create_emplace_args( \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
|
a) \
|
|
)).first); \
|
|
}
|
|
|
|
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
|
BOOST_UNORDERED_EMPLACE, _)
|
|
|
|
#undef BOOST_UNORDERED_EMPLACE
|
|
|
|
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
|
|
|
std::pair<iterator, bool> emplace(
|
|
boost::unordered::detail::empty_emplace
|
|
= boost::unordered::detail::empty_emplace(),
|
|
value_type v = value_type())
|
|
{
|
|
return this->emplace(boost::move(v));
|
|
}
|
|
|
|
iterator emplace_hint(const_iterator hint,
|
|
boost::unordered::detail::empty_emplace
|
|
= boost::unordered::detail::empty_emplace(),
|
|
value_type v = value_type()
|
|
)
|
|
{
|
|
return iterator(this->emplace_hint(hint, boost::move(v)));
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
std::pair<iterator, bool> insert(value_type const& x)
|
|
{
|
|
return this->emplace(x);
|
|
}
|
|
|
|
std::pair<iterator, bool> insert(BOOST_UNORDERED_RV_REF(value_type) x)
|
|
{
|
|
return this->emplace(boost::move(x));
|
|
}
|
|
|
|
iterator insert(const_iterator hint, value_type const& x)
|
|
{
|
|
return this->emplace_hint(hint, x);
|
|
}
|
|
|
|
iterator insert(const_iterator hint,
|
|
BOOST_UNORDERED_RV_REF(value_type) x)
|
|
{
|
|
return this->emplace_hint(hint, boost::move(x));
|
|
}
|
|
|
|
template <class InputIt> void insert(InputIt, InputIt);
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
void insert(std::initializer_list<value_type>);
|
|
#endif
|
|
|
|
iterator erase(const_iterator);
|
|
size_type erase(const key_type&);
|
|
iterator erase(const_iterator, const_iterator);
|
|
void quick_erase(const_iterator it) { erase(it); }
|
|
void erase_return_void(const_iterator it) { erase(it); }
|
|
|
|
void clear();
|
|
void swap(unordered_set&);
|
|
|
|
// observers
|
|
|
|
hasher hash_function() const;
|
|
key_equal key_eq() const;
|
|
|
|
// lookup
|
|
|
|
const_iterator find(const key_type&) const;
|
|
|
|
template <class CompatibleKey, class CompatibleHash,
|
|
class CompatiblePredicate>
|
|
const_iterator find(
|
|
CompatibleKey const&,
|
|
CompatibleHash const&,
|
|
CompatiblePredicate const&) const;
|
|
|
|
size_type count(const key_type&) const;
|
|
|
|
std::pair<const_iterator, const_iterator>
|
|
equal_range(const key_type&) const;
|
|
|
|
// bucket interface
|
|
|
|
size_type bucket_count() const
|
|
{
|
|
return table_.bucket_count_;
|
|
}
|
|
|
|
size_type max_bucket_count() const
|
|
{
|
|
return table_.max_bucket_count();
|
|
}
|
|
|
|
size_type bucket_size(size_type) const;
|
|
|
|
size_type bucket(const key_type& k) const
|
|
{
|
|
return table_.hash_function()(k) % table_.bucket_count_;
|
|
}
|
|
|
|
local_iterator begin(size_type n)
|
|
{
|
|
return table_.size_ ? local_iterator(
|
|
table_.get_start(n), n, table_.bucket_count_) :
|
|
local_iterator();
|
|
}
|
|
|
|
const_local_iterator begin(size_type n) const
|
|
{
|
|
return table_.size_ ? const_local_iterator(
|
|
table_.get_start(n), n, table_.bucket_count_) :
|
|
const_local_iterator();
|
|
}
|
|
|
|
local_iterator end(size_type)
|
|
{
|
|
return local_iterator();
|
|
}
|
|
|
|
const_local_iterator end(size_type) const
|
|
{
|
|
return const_local_iterator();
|
|
}
|
|
|
|
const_local_iterator cbegin(size_type n) const
|
|
{
|
|
return table_.size_ ? const_local_iterator(
|
|
table_.get_start(n), n, table_.bucket_count_) :
|
|
const_local_iterator();
|
|
}
|
|
|
|
const_local_iterator cend(size_type) const
|
|
{
|
|
return const_local_iterator();
|
|
}
|
|
|
|
// hash policy
|
|
|
|
float max_load_factor() const
|
|
{
|
|
return table_.mlf_;
|
|
}
|
|
|
|
float load_factor() const;
|
|
void max_load_factor(float);
|
|
void rehash(size_type);
|
|
|
|
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
|
friend bool operator==<T,H,P,A>(
|
|
unordered_set const&, unordered_set const&);
|
|
friend bool operator!=<T,H,P,A>(
|
|
unordered_set const&, unordered_set const&);
|
|
#endif
|
|
}; // class template unordered_set
|
|
|
|
template <class T, class H, class P, class A>
|
|
class unordered_multiset
|
|
{
|
|
BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
|
|
public:
|
|
|
|
typedef T key_type;
|
|
typedef T value_type;
|
|
typedef H hasher;
|
|
typedef P key_equal;
|
|
typedef A allocator_type;
|
|
|
|
private:
|
|
|
|
typedef typename boost::unordered::detail::rebind_wrap<
|
|
allocator_type, value_type>::type
|
|
value_allocator;
|
|
|
|
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
|
allocator_traits;
|
|
|
|
typedef boost::unordered::detail::multiset<value_allocator, H, P>
|
|
types;
|
|
typedef typename types::table table;
|
|
|
|
public:
|
|
|
|
typedef typename allocator_traits::pointer pointer;
|
|
typedef typename allocator_traits::const_pointer const_pointer;
|
|
|
|
typedef value_type& reference;
|
|
typedef value_type const& const_reference;
|
|
|
|
typedef std::size_t size_type;
|
|
typedef std::ptrdiff_t difference_type;
|
|
|
|
typedef typename table::cl_iterator const_local_iterator;
|
|
typedef typename table::cl_iterator local_iterator;
|
|
typedef typename table::c_iterator const_iterator;
|
|
typedef typename table::c_iterator iterator;
|
|
|
|
private:
|
|
|
|
table table_;
|
|
|
|
public:
|
|
|
|
// constructors
|
|
|
|
explicit unordered_multiset(
|
|
size_type = boost::unordered::detail::default_bucket_count,
|
|
const hasher& = hasher(),
|
|
const key_equal& = key_equal(),
|
|
const allocator_type& = allocator_type());
|
|
|
|
explicit unordered_multiset(allocator_type const&);
|
|
|
|
template <class InputIt>
|
|
unordered_multiset(InputIt, InputIt);
|
|
|
|
template <class InputIt>
|
|
unordered_multiset(
|
|
InputIt, InputIt,
|
|
size_type,
|
|
const hasher& = hasher(),
|
|
const key_equal& = key_equal());
|
|
|
|
template <class InputIt>
|
|
unordered_multiset(
|
|
InputIt, InputIt,
|
|
size_type,
|
|
const hasher&,
|
|
const key_equal&,
|
|
const allocator_type&);
|
|
|
|
// copy/move constructors
|
|
|
|
unordered_multiset(unordered_multiset const&);
|
|
|
|
unordered_multiset(unordered_multiset const&, allocator_type const&);
|
|
|
|
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
|
|
: table_(other.table_, boost::unordered::detail::move_tag())
|
|
{
|
|
}
|
|
|
|
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
|
unordered_multiset(unordered_multiset&&, allocator_type const&);
|
|
#endif
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
unordered_multiset(
|
|
std::initializer_list<value_type>,
|
|
size_type = boost::unordered::detail::default_bucket_count,
|
|
const hasher& = hasher(),
|
|
const key_equal&l = key_equal(),
|
|
const allocator_type& = allocator_type());
|
|
#endif
|
|
|
|
// Destructor
|
|
|
|
~unordered_multiset();
|
|
|
|
// Assign
|
|
|
|
unordered_multiset& operator=(
|
|
BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
|
|
{
|
|
table_.assign(x.table_);
|
|
return *this;
|
|
}
|
|
|
|
unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
|
|
{
|
|
table_.move_assign(x.table_);
|
|
return *this;
|
|
}
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
unordered_multiset& operator=(std::initializer_list<value_type>);
|
|
#endif
|
|
|
|
allocator_type get_allocator() const
|
|
{
|
|
return table_.node_alloc();
|
|
}
|
|
|
|
// size and capacity
|
|
|
|
bool empty() const
|
|
{
|
|
return table_.size_ == 0;
|
|
}
|
|
|
|
size_type size() const
|
|
{
|
|
return table_.size_;
|
|
}
|
|
|
|
size_type max_size() const;
|
|
|
|
// iterators
|
|
|
|
iterator begin()
|
|
{
|
|
return iterator(table_.begin());
|
|
}
|
|
|
|
const_iterator begin() const
|
|
{
|
|
return const_iterator(table_.begin());
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return iterator();
|
|
}
|
|
|
|
const_iterator end() const
|
|
{
|
|
return const_iterator();
|
|
}
|
|
|
|
const_iterator cbegin() const
|
|
{
|
|
return const_iterator(table_.begin());
|
|
}
|
|
|
|
const_iterator cend() const
|
|
{
|
|
return const_iterator();
|
|
}
|
|
|
|
// emplace
|
|
|
|
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
|
template <class... Args>
|
|
iterator emplace(Args&&... args)
|
|
{
|
|
return iterator(table_.emplace(std::forward<Args>(args)...));
|
|
}
|
|
|
|
template <class... Args>
|
|
iterator emplace_hint(const_iterator, Args&&... args)
|
|
{
|
|
return iterator(table_.emplace(std::forward<Args>(args)...));
|
|
}
|
|
#else
|
|
|
|
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
|
template < \
|
|
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
|
> \
|
|
iterator emplace( \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
|
) \
|
|
{ \
|
|
return iterator(table_.emplace( \
|
|
boost::unordered::detail::create_emplace_args( \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
|
a) \
|
|
))); \
|
|
} \
|
|
\
|
|
template < \
|
|
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
|
|
> \
|
|
iterator emplace_hint( \
|
|
const_iterator, \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
|
|
) \
|
|
{ \
|
|
return iterator(table_.emplace( \
|
|
boost::unordered::detail::create_emplace_args( \
|
|
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
|
|
a) \
|
|
))); \
|
|
}
|
|
|
|
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
|
BOOST_UNORDERED_EMPLACE, _)
|
|
|
|
#undef BOOST_UNORDERED_EMPLACE
|
|
|
|
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
|
|
|
iterator emplace(
|
|
boost::unordered::detail::empty_emplace
|
|
= boost::unordered::detail::empty_emplace(),
|
|
value_type v = value_type())
|
|
{
|
|
return this->emplace(boost::move(v));
|
|
}
|
|
|
|
iterator emplace_hint(const_iterator hint,
|
|
boost::unordered::detail::empty_emplace
|
|
= boost::unordered::detail::empty_emplace(),
|
|
value_type v = value_type()
|
|
)
|
|
{
|
|
return this->emplace_hint(hint, boost::move(v));
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
iterator insert(value_type const& x)
|
|
{
|
|
return this->emplace(x);
|
|
}
|
|
|
|
iterator insert(BOOST_UNORDERED_RV_REF(value_type) x)
|
|
{
|
|
return this->emplace(boost::move(x));
|
|
}
|
|
|
|
iterator insert(const_iterator hint, value_type const& x)
|
|
{
|
|
return this->emplace_hint(hint, x);
|
|
}
|
|
|
|
iterator insert(const_iterator hint,
|
|
BOOST_UNORDERED_RV_REF(value_type) x)
|
|
{
|
|
return this->emplace_hint(hint, boost::move(x));
|
|
}
|
|
|
|
template <class InputIt> void insert(InputIt, InputIt);
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
void insert(std::initializer_list<value_type>);
|
|
#endif
|
|
|
|
iterator erase(const_iterator);
|
|
size_type erase(const key_type&);
|
|
iterator erase(const_iterator, const_iterator);
|
|
void quick_erase(const_iterator it) { erase(it); }
|
|
void erase_return_void(const_iterator it) { erase(it); }
|
|
|
|
void clear();
|
|
void swap(unordered_multiset&);
|
|
|
|
// observers
|
|
|
|
hasher hash_function() const;
|
|
key_equal key_eq() const;
|
|
|
|
// lookup
|
|
|
|
const_iterator find(const key_type&) const;
|
|
|
|
template <class CompatibleKey, class CompatibleHash,
|
|
class CompatiblePredicate>
|
|
const_iterator find(
|
|
CompatibleKey const&,
|
|
CompatibleHash const&,
|
|
CompatiblePredicate const&) const;
|
|
|
|
size_type count(const key_type&) const;
|
|
|
|
std::pair<const_iterator, const_iterator>
|
|
equal_range(const key_type&) const;
|
|
|
|
// bucket interface
|
|
|
|
size_type bucket_count() const
|
|
{
|
|
return table_.bucket_count_;
|
|
}
|
|
|
|
size_type max_bucket_count() const
|
|
{
|
|
return table_.max_bucket_count();
|
|
}
|
|
|
|
size_type bucket_size(size_type) const;
|
|
|
|
size_type bucket(const key_type& k) const
|
|
{
|
|
return table_.hash_function()(k) % table_.bucket_count_;
|
|
}
|
|
|
|
local_iterator begin(size_type n)
|
|
{
|
|
return table_.size_ ? local_iterator(
|
|
table_.get_start(n), n, table_.bucket_count_) :
|
|
local_iterator();
|
|
}
|
|
|
|
const_local_iterator begin(size_type n) const
|
|
{
|
|
return table_.size_ ? const_local_iterator(
|
|
table_.get_start(n), n, table_.bucket_count_) :
|
|
const_local_iterator();
|
|
}
|
|
|
|
local_iterator end(size_type)
|
|
{
|
|
return local_iterator();
|
|
}
|
|
|
|
const_local_iterator end(size_type) const
|
|
{
|
|
return const_local_iterator();
|
|
}
|
|
|
|
const_local_iterator cbegin(size_type n) const
|
|
{
|
|
return table_.size_ ? const_local_iterator(
|
|
table_.get_start(n), n, table_.bucket_count_) :
|
|
const_local_iterator();
|
|
}
|
|
|
|
const_local_iterator cend(size_type) const
|
|
{
|
|
return const_local_iterator();
|
|
}
|
|
|
|
// hash policy
|
|
|
|
float max_load_factor() const
|
|
{
|
|
return table_.mlf_;
|
|
}
|
|
|
|
float load_factor() const;
|
|
void max_load_factor(float);
|
|
void rehash(size_type);
|
|
|
|
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
|
friend bool operator==<T,H,P,A>(
|
|
unordered_multiset const&, unordered_multiset const&);
|
|
friend bool operator!=<T,H,P,A>(
|
|
unordered_multiset const&, unordered_multiset const&);
|
|
#endif
|
|
}; // class template unordered_multiset
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>::unordered_set(
|
|
size_type n, const hasher &hf, const key_equal &eql,
|
|
const allocator_type &a)
|
|
: table_(n, hf, eql, a)
|
|
{
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
|
|
: table_(boost::unordered::detail::default_bucket_count,
|
|
hasher(), key_equal(), a)
|
|
{
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>::unordered_set(
|
|
unordered_set const& other, allocator_type const& a)
|
|
: table_(other.table_, a)
|
|
{
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
unordered_set<T,H,P,A>::unordered_set(InputIt f, InputIt l)
|
|
: table_(boost::unordered::detail::initial_size(f, l),
|
|
hasher(), key_equal(), allocator_type())
|
|
{
|
|
table_.insert_range(f, l);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
unordered_set<T,H,P,A>::unordered_set(
|
|
InputIt f, InputIt l,
|
|
size_type n,
|
|
const hasher &hf,
|
|
const key_equal &eql)
|
|
: table_(boost::unordered::detail::initial_size(f, l, n),
|
|
hf, eql, allocator_type())
|
|
{
|
|
table_.insert_range(f, l);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
unordered_set<T,H,P,A>::unordered_set(
|
|
InputIt f, InputIt l,
|
|
size_type n,
|
|
const hasher &hf,
|
|
const key_equal &eql,
|
|
const allocator_type &a)
|
|
: table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
|
|
{
|
|
table_.insert_range(f, l);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>::~unordered_set() {}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>::unordered_set(
|
|
unordered_set const& other)
|
|
: table_(other.table_)
|
|
{
|
|
}
|
|
|
|
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>::unordered_set(
|
|
unordered_set&& other, allocator_type const& a)
|
|
: table_(other.table_, a, boost::unordered::detail::move_tag())
|
|
{
|
|
}
|
|
|
|
#endif
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>::unordered_set(
|
|
std::initializer_list<value_type> list, size_type n,
|
|
const hasher &hf, const key_equal &eql, const allocator_type &a)
|
|
: table_(
|
|
boost::unordered::detail::initial_size(
|
|
list.begin(), list.end(), n),
|
|
hf, eql, a)
|
|
{
|
|
table_.insert_range(list.begin(), list.end());
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_set<T,H,P,A>& unordered_set<T,H,P,A>::operator=(
|
|
std::initializer_list<value_type> list)
|
|
{
|
|
table_.clear();
|
|
table_.insert_range(list.begin(), list.end());
|
|
return *this;
|
|
}
|
|
|
|
#endif
|
|
|
|
// size and capacity
|
|
|
|
template <class T, class H, class P, class A>
|
|
std::size_t unordered_set<T,H,P,A>::max_size() const
|
|
{
|
|
return table_.max_size();
|
|
}
|
|
|
|
// modifiers
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
void unordered_set<T,H,P,A>::insert(InputIt first, InputIt last)
|
|
{
|
|
table_.insert_range(first, last);
|
|
}
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
template <class T, class H, class P, class A>
|
|
void unordered_set<T,H,P,A>::insert(
|
|
std::initializer_list<value_type> list)
|
|
{
|
|
table_.insert_range(list.begin(), list.end());
|
|
}
|
|
#endif
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::iterator
|
|
unordered_set<T,H,P,A>::erase(const_iterator position)
|
|
{
|
|
return iterator(table_.erase(position.node_));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::size_type
|
|
unordered_set<T,H,P,A>::erase(const key_type& k)
|
|
{
|
|
return table_.erase_key(k);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::iterator
|
|
unordered_set<T,H,P,A>::erase(
|
|
const_iterator first, const_iterator last)
|
|
{
|
|
return iterator(table_.erase_range(first.node_, last.node_));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_set<T,H,P,A>::clear()
|
|
{
|
|
table_.clear();
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_set<T,H,P,A>::swap(unordered_set& other)
|
|
{
|
|
table_.swap(other.table_);
|
|
}
|
|
|
|
// observers
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::hasher
|
|
unordered_set<T,H,P,A>::hash_function() const
|
|
{
|
|
return table_.hash_function();
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::key_equal
|
|
unordered_set<T,H,P,A>::key_eq() const
|
|
{
|
|
return table_.key_eq();
|
|
}
|
|
|
|
// lookup
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::const_iterator
|
|
unordered_set<T,H,P,A>::find(const key_type& k) const
|
|
{
|
|
return const_iterator(table_.find_node(k));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class CompatibleKey, class CompatibleHash,
|
|
class CompatiblePredicate>
|
|
typename unordered_set<T,H,P,A>::const_iterator
|
|
unordered_set<T,H,P,A>::find(
|
|
CompatibleKey const& k,
|
|
CompatibleHash const& hash,
|
|
CompatiblePredicate const& eq) const
|
|
{
|
|
return const_iterator(table_.generic_find_node(k, hash, eq));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::size_type
|
|
unordered_set<T,H,P,A>::count(const key_type& k) const
|
|
{
|
|
return table_.count(k);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
std::pair<
|
|
typename unordered_set<T,H,P,A>::const_iterator,
|
|
typename unordered_set<T,H,P,A>::const_iterator>
|
|
unordered_set<T,H,P,A>::equal_range(const key_type& k) const
|
|
{
|
|
return table_.equal_range(k);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_set<T,H,P,A>::size_type
|
|
unordered_set<T,H,P,A>::bucket_size(size_type n) const
|
|
{
|
|
return table_.bucket_size(n);
|
|
}
|
|
|
|
// hash policy
|
|
|
|
template <class T, class H, class P, class A>
|
|
float unordered_set<T,H,P,A>::load_factor() const
|
|
{
|
|
return table_.load_factor();
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_set<T,H,P,A>::max_load_factor(float m)
|
|
{
|
|
table_.max_load_factor(m);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_set<T,H,P,A>::rehash(size_type n)
|
|
{
|
|
table_.rehash(n);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
inline bool operator==(
|
|
unordered_set<T,H,P,A> const& m1,
|
|
unordered_set<T,H,P,A> const& m2)
|
|
{
|
|
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
|
struct dummy { unordered_set<T,H,P,A> x; };
|
|
#endif
|
|
return m1.table_.equals(m2.table_);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
inline bool operator!=(
|
|
unordered_set<T,H,P,A> const& m1,
|
|
unordered_set<T,H,P,A> const& m2)
|
|
{
|
|
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
|
struct dummy { unordered_set<T,H,P,A> x; };
|
|
#endif
|
|
return !m1.table_.equals(m2.table_);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
inline void swap(
|
|
unordered_set<T,H,P,A> &m1,
|
|
unordered_set<T,H,P,A> &m2)
|
|
{
|
|
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
|
struct dummy { unordered_set<T,H,P,A> x; };
|
|
#endif
|
|
m1.swap(m2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(
|
|
size_type n, const hasher &hf, const key_equal &eql,
|
|
const allocator_type &a)
|
|
: table_(n, hf, eql, a)
|
|
{
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
|
|
: table_(boost::unordered::detail::default_bucket_count,
|
|
hasher(), key_equal(), a)
|
|
{
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(
|
|
unordered_multiset const& other, allocator_type const& a)
|
|
: table_(other.table_, a)
|
|
{
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(InputIt f, InputIt l)
|
|
: table_(boost::unordered::detail::initial_size(f, l),
|
|
hasher(), key_equal(), allocator_type())
|
|
{
|
|
table_.insert_range(f, l);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(
|
|
InputIt f, InputIt l,
|
|
size_type n,
|
|
const hasher &hf,
|
|
const key_equal &eql)
|
|
: table_(boost::unordered::detail::initial_size(f, l, n),
|
|
hf, eql, allocator_type())
|
|
{
|
|
table_.insert_range(f, l);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(
|
|
InputIt f, InputIt l,
|
|
size_type n,
|
|
const hasher &hf,
|
|
const key_equal &eql,
|
|
const allocator_type &a)
|
|
: table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
|
|
{
|
|
table_.insert_range(f, l);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>::~unordered_multiset() {}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(
|
|
unordered_multiset const& other)
|
|
: table_(other.table_)
|
|
{
|
|
}
|
|
|
|
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(
|
|
unordered_multiset&& other, allocator_type const& a)
|
|
: table_(other.table_, a, boost::unordered::detail::move_tag())
|
|
{
|
|
}
|
|
|
|
#endif
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>::unordered_multiset(
|
|
std::initializer_list<value_type> list, size_type n,
|
|
const hasher &hf, const key_equal &eql, const allocator_type &a)
|
|
: table_(
|
|
boost::unordered::detail::initial_size(
|
|
list.begin(), list.end(), n),
|
|
hf, eql, a)
|
|
{
|
|
table_.insert_range(list.begin(), list.end());
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
unordered_multiset<T,H,P,A>& unordered_multiset<T,H,P,A>::operator=(
|
|
std::initializer_list<value_type> list)
|
|
{
|
|
table_.clear();
|
|
table_.insert_range(list.begin(), list.end());
|
|
return *this;
|
|
}
|
|
|
|
#endif
|
|
|
|
// size and capacity
|
|
|
|
template <class T, class H, class P, class A>
|
|
std::size_t unordered_multiset<T,H,P,A>::max_size() const
|
|
{
|
|
return table_.max_size();
|
|
}
|
|
|
|
// modifiers
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class InputIt>
|
|
void unordered_multiset<T,H,P,A>::insert(InputIt first, InputIt last)
|
|
{
|
|
table_.insert_range(first, last);
|
|
}
|
|
|
|
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
|
template <class T, class H, class P, class A>
|
|
void unordered_multiset<T,H,P,A>::insert(
|
|
std::initializer_list<value_type> list)
|
|
{
|
|
table_.insert_range(list.begin(), list.end());
|
|
}
|
|
#endif
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::iterator
|
|
unordered_multiset<T,H,P,A>::erase(const_iterator position)
|
|
{
|
|
return iterator(table_.erase(position.node_));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::size_type
|
|
unordered_multiset<T,H,P,A>::erase(const key_type& k)
|
|
{
|
|
return table_.erase_key(k);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::iterator
|
|
unordered_multiset<T,H,P,A>::erase(
|
|
const_iterator first, const_iterator last)
|
|
{
|
|
return iterator(table_.erase_range(first.node_, last.node_));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_multiset<T,H,P,A>::clear()
|
|
{
|
|
table_.clear();
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_multiset<T,H,P,A>::swap(unordered_multiset& other)
|
|
{
|
|
table_.swap(other.table_);
|
|
}
|
|
|
|
// observers
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::hasher
|
|
unordered_multiset<T,H,P,A>::hash_function() const
|
|
{
|
|
return table_.hash_function();
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::key_equal
|
|
unordered_multiset<T,H,P,A>::key_eq() const
|
|
{
|
|
return table_.key_eq();
|
|
}
|
|
|
|
// lookup
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::const_iterator
|
|
unordered_multiset<T,H,P,A>::find(const key_type& k) const
|
|
{
|
|
return const_iterator(table_.find_node(k));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
template <class CompatibleKey, class CompatibleHash,
|
|
class CompatiblePredicate>
|
|
typename unordered_multiset<T,H,P,A>::const_iterator
|
|
unordered_multiset<T,H,P,A>::find(
|
|
CompatibleKey const& k,
|
|
CompatibleHash const& hash,
|
|
CompatiblePredicate const& eq) const
|
|
{
|
|
return const_iterator(table_.generic_find_node(k, hash, eq));
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::size_type
|
|
unordered_multiset<T,H,P,A>::count(const key_type& k) const
|
|
{
|
|
return table_.count(k);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
std::pair<
|
|
typename unordered_multiset<T,H,P,A>::const_iterator,
|
|
typename unordered_multiset<T,H,P,A>::const_iterator>
|
|
unordered_multiset<T,H,P,A>::equal_range(const key_type& k) const
|
|
{
|
|
return table_.equal_range(k);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
typename unordered_multiset<T,H,P,A>::size_type
|
|
unordered_multiset<T,H,P,A>::bucket_size(size_type n) const
|
|
{
|
|
return table_.bucket_size(n);
|
|
}
|
|
|
|
// hash policy
|
|
|
|
template <class T, class H, class P, class A>
|
|
float unordered_multiset<T,H,P,A>::load_factor() const
|
|
{
|
|
return table_.load_factor();
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_multiset<T,H,P,A>::max_load_factor(float m)
|
|
{
|
|
table_.max_load_factor(m);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
void unordered_multiset<T,H,P,A>::rehash(size_type n)
|
|
{
|
|
table_.rehash(n);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
inline bool operator==(
|
|
unordered_multiset<T,H,P,A> const& m1,
|
|
unordered_multiset<T,H,P,A> const& m2)
|
|
{
|
|
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
|
struct dummy { unordered_multiset<T,H,P,A> x; };
|
|
#endif
|
|
return m1.table_.equals(m2.table_);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
inline bool operator!=(
|
|
unordered_multiset<T,H,P,A> const& m1,
|
|
unordered_multiset<T,H,P,A> const& m2)
|
|
{
|
|
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
|
struct dummy { unordered_multiset<T,H,P,A> x; };
|
|
#endif
|
|
return !m1.table_.equals(m2.table_);
|
|
}
|
|
|
|
template <class T, class H, class P, class A>
|
|
inline void swap(
|
|
unordered_multiset<T,H,P,A> &m1,
|
|
unordered_multiset<T,H,P,A> &m2)
|
|
{
|
|
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
|
struct dummy { unordered_multiset<T,H,P,A> x; };
|
|
#endif
|
|
m1.swap(m2);
|
|
}
|
|
} // namespace unordered
|
|
} // namespace boost
|
|
|
|
#if defined(BOOST_MSVC)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
#endif // BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
|