Merge branch 'feature/standards-checking-and-cleanup' into develop

Rearrange the definitions to be a closer match to the standard, this
should make it easier to check how standards compliant it is. Also, some
minor code clean-ups that I noticed while doing this.
This commit is contained in:
Daniel James
2017-04-20 23:01:09 +01:00
6 changed files with 1049 additions and 890 deletions

View File

@@ -168,17 +168,16 @@ namespace detail {
template <typename Types> struct table;
template <typename NodePointer> struct bucket;
struct ptr_bucket;
template <typename Types> struct table_unique;
template <typename Types> struct table_equiv;
template <typename A, typename T> struct unique_node;
template <typename T> struct ptr_node;
template <typename Types> struct table_unique;
template <typename N> struct node_algo;
template <typename A, typename T> struct grouped_node;
template <typename T> struct grouped_ptr_node;
template <typename Types> struct table_equiv;
template <typename N> struct node_algo;
template <typename N> struct grouped_node_algo;
static const float minimum_max_load_factor = 1e-3f;

File diff suppressed because it is too large Load Diff

View File

@@ -83,59 +83,53 @@ template <class T, class H, class P, class A> class unordered_set
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_set(size_type, const allocator_type&);
explicit unordered_set(size_type, const hasher&, const 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&);
template <class InputIt>
unordered_set(
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
template <class InputIt>
unordered_set(InputIt, InputIt, size_type, const allocator_type&);
// copy/move constructors
unordered_set(InputIt, InputIt,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(), const key_equal& = key_equal(),
const allocator_type& = allocator_type());
unordered_set(unordered_set const&);
unordered_set(unordered_set const&, allocator_type const&);
unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(BOOST_RV_REF(unordered_set) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
explicit unordered_set(allocator_type const&);
unordered_set(unordered_set const&, allocator_type const&);
unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
#if !defined(BOOST_NO_CXX11_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());
unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
const allocator_type&);
#endif
explicit unordered_set(size_type, const allocator_type&);
explicit unordered_set(size_type, const hasher&, const allocator_type&);
template <class InputIt>
unordered_set(InputIt, InputIt, size_type, const allocator_type&);
template <class InputIt>
unordered_set(
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set(
std::initializer_list<value_type>, size_type, const allocator_type&);
unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
const allocator_type&);
#endif
// Destructor
@@ -152,6 +146,10 @@ template <class T, class H, class P, class A> class unordered_set
}
unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
{
table_.move_assign(x.table_);
return *this;
@@ -165,6 +163,10 @@ template <class T, class H, class P, class A> class unordered_set
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set& operator=(unordered_set&& x)
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
{
table_.move_assign(x.table_);
return *this;
@@ -181,14 +183,6 @@ template <class T, class H, class P, class A> class unordered_set
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
size_type size() const BOOST_NOEXCEPT { return table_.size_; }
size_type max_size() const BOOST_NOEXCEPT;
// iterators
iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
@@ -209,33 +203,24 @@ template <class T, class H, class P, class A> class unordered_set
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
// extract
// size and capacity
node_type extract(const_iterator position)
{
return node_type(
table_.extract_by_iterator(position), table_.node_alloc());
}
bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
node_type extract(const key_type& k)
{
return node_type(table_.extract_by_key(k), table_.node_alloc());
}
size_type size() const BOOST_NOEXCEPT { return table_.size_; }
size_type max_size() const BOOST_NOEXCEPT;
// emplace
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
@@ -252,6 +237,46 @@ template <class T, class H, class P, class A> class unordered_set
return this->emplace(boost::move(v));
}
#endif
template <typename A0>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename A0, typename A1>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
#endif
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace =
boost::unordered::detail::empty_emplace(),
@@ -262,13 +287,6 @@ template <class T, class H, class P, class A> class unordered_set
#endif
template <typename A0>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
@@ -277,14 +295,6 @@ template <class T, class H, class P, class A> class unordered_set
boost::forward<A0>(a0)));
}
template <typename A0, typename A1>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1>
iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
@@ -294,15 +304,6 @@ template <class T, class H, class P, class A> class unordered_set
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
@@ -313,6 +314,10 @@ template <class T, class H, class P, class A> class unordered_set
boost::forward<A2>(a2)));
}
#endif
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
std::pair<iterator, bool> emplace( \
@@ -364,6 +369,19 @@ template <class T, class H, class P, class A> class unordered_set
void insert(std::initializer_list<value_type>);
#endif
// extract
node_type extract(const_iterator position)
{
return node_type(
table_.extract_by_iterator(position), table_.node_alloc());
}
node_type extract(const key_type& k)
{
return node_type(table_.extract_by_key(k), table_.node_alloc());
}
insert_return_type insert(BOOST_RV_REF(node_type) np)
{
insert_return_type result;
@@ -393,8 +411,12 @@ template <class T, class H, class P, class A> class unordered_set
BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
void clear();
void swap(unordered_set&);
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
void clear() BOOST_NOEXCEPT;
template <typename H2, typename P2>
void merge(boost::unordered_set<T, H2, P2, A>& source);
@@ -541,60 +563,54 @@ template <class T, class H, class P, class A> class unordered_multiset
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_multiset(size_type, const allocator_type&);
explicit unordered_multiset(
size_type, const hasher&, const 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&);
template <class InputIt>
unordered_multiset(
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
template <class InputIt>
unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
// copy/move constructors
unordered_multiset(InputIt, InputIt,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(), const key_equal& = key_equal(),
const allocator_type& = allocator_type());
unordered_multiset(unordered_multiset const&);
unordered_multiset(unordered_multiset const&, allocator_type const&);
unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
explicit unordered_multiset(allocator_type const&);
unordered_multiset(unordered_multiset const&, allocator_type const&);
unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&);
#if !defined(BOOST_NO_CXX11_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());
unordered_multiset(std::initializer_list<value_type>, size_type,
const hasher&, const allocator_type&);
#endif
explicit unordered_multiset(size_type, const allocator_type&);
explicit unordered_multiset(
size_type, const hasher&, const allocator_type&);
template <class InputIt>
unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
template <class InputIt>
unordered_multiset(
InputIt, InputIt, size_type, const hasher&, const allocator_type&);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset(
std::initializer_list<value_type>, size_type, const allocator_type&);
unordered_multiset(std::initializer_list<value_type>, size_type,
const hasher&, const allocator_type&);
#endif
// Destructor
@@ -611,6 +627,10 @@ template <class T, class H, class P, class A> class unordered_multiset
}
unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
{
table_.move_assign(x.table_);
return *this;
@@ -624,6 +644,10 @@ template <class T, class H, class P, class A> class unordered_multiset
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset& operator=(unordered_multiset&& x)
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
{
table_.move_assign(x.table_);
return *this;
@@ -640,14 +664,6 @@ template <class T, class H, class P, class A> class unordered_multiset
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
size_type size() const BOOST_NOEXCEPT { return table_.size_; }
size_type max_size() const BOOST_NOEXCEPT;
// iterators
iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
@@ -668,18 +684,13 @@ template <class T, class H, class P, class A> class unordered_multiset
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
// extract
// size and capacity
node_type extract(const_iterator position)
{
return node_type(
table_.extract_by_iterator(position), table_.node_alloc());
}
bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
node_type extract(const key_type& k)
{
return node_type(table_.extract_by_key(k), table_.node_alloc());
}
size_type size() const BOOST_NOEXCEPT { return table_.size_; }
size_type max_size() const BOOST_NOEXCEPT;
// emplace
@@ -689,11 +700,6 @@ template <class T, class H, class P, class A> class unordered_multiset
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
@@ -709,6 +715,44 @@ template <class T, class H, class P, class A> class unordered_multiset
return this->emplace(boost::move(v));
}
#endif
template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename A0, typename A1>
iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
iterator emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
#endif
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace =
boost::unordered::detail::empty_emplace(),
@@ -719,12 +763,6 @@ template <class T, class H, class P, class A> class unordered_multiset
#endif
template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
@@ -733,13 +771,6 @@ template <class T, class H, class P, class A> class unordered_multiset
boost::forward<A0>(a0)));
}
template <typename A0, typename A1>
iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1>
iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
@@ -749,15 +780,6 @@ template <class T, class H, class P, class A> class unordered_multiset
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
iterator emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.emplace(boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
@@ -768,6 +790,10 @@ template <class T, class H, class P, class A> class unordered_multiset
boost::forward<A2>(a2)));
}
#endif
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#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)) \
@@ -815,6 +841,19 @@ template <class T, class H, class P, class A> class unordered_multiset
void insert(std::initializer_list<value_type>);
#endif
// extract
node_type extract(const_iterator position)
{
return node_type(
table_.extract_by_iterator(position), table_.node_alloc());
}
node_type extract(const key_type& k)
{
return node_type(table_.extract_by_key(k), table_.node_alloc());
}
iterator insert(BOOST_RV_REF(node_type) np)
{
return table_.move_insert_node_type(np);
@@ -842,8 +881,12 @@ template <class T, class H, class P, class A> class unordered_multiset
BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
void clear();
void swap(unordered_multiset&);
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
void clear() BOOST_NOEXCEPT;
template <typename H2, typename P2>
void merge(boost::unordered_multiset<T, H2, P2, A>& source);
@@ -943,7 +986,6 @@ template <class T, class H, class P, class A> class unordered_multiset
}; // class template unordered_multiset
////////////////////////////////////////////////////////////////////////////////
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
@@ -959,15 +1001,17 @@ unordered_set<T, H, P, A>::unordered_set(size_type n, const hasher& hf,
}
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set(size_type n, const allocator_type& a)
: table_(n, hasher(), key_equal(), 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(
size_type n, const hasher& hf, const allocator_type& a)
: table_(n, hf, key_equal(), a)
unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
: table_(other.table_)
{
}
@@ -985,65 +1029,6 @@ unordered_set<T, H, P, A>::unordered_set(
{
}
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>
template <class InputIt>
unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
const hasher& hf, const allocator_type& a)
: table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
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 allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::~unordered_set() BOOST_NOEXCEPT
{
}
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
: table_(other.table_)
{
}
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set(
BOOST_RV_REF(unordered_set) other, allocator_type const& a)
@@ -1064,16 +1049,43 @@ unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
table_.insert_range(list.begin(), list.end());
}
#endif
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 allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
unordered_set<T, H, P, A>::unordered_set(size_type n, const allocator_type& a)
: table_(n, hasher(), key_equal(), 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(
size_type n, const hasher& hf, const allocator_type& a)
: table_(n, hf, key_equal(), 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, size_type n, const allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
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 allocator_type& a)
: table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
table_.insert_range(f, l);
}
#if !defined(BOOST_NO_CXX11_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 allocator_type& a)
@@ -1084,6 +1096,25 @@ unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
table_.insert_range(list.begin(), list.end());
}
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 allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
#endif
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::~unordered_set() BOOST_NOEXCEPT
{
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
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)
@@ -1142,15 +1173,25 @@ typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase(
}
template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::clear()
void unordered_set<T, H, P, A>::swap(unordered_set& other)
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
{
table_.swap(other.table_);
}
template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::clear() BOOST_NOEXCEPT
{
table_.clear();
}
template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::swap(unordered_set& other)
void unordered_multiset<T, H, P, A>::clear() BOOST_NOEXCEPT
{
table_.swap(other.table_);
table_.clear();
}
// observers
@@ -1329,16 +1370,19 @@ unordered_multiset<T, H, P, A>::unordered_multiset(size_type n,
}
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::unordered_multiset(
size_type n, const allocator_type& a)
: table_(n, hasher(), key_equal(), 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(
size_type n, const hasher& hf, const allocator_type& a)
: table_(n, hf, key_equal(), a)
unordered_multiset const& other)
: table_(other.table_)
{
}
@@ -1356,67 +1400,6 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
{
}
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>
template <class InputIt>
unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
size_type n, const hasher& hf, const allocator_type& a)
: table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
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 allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::~unordered_multiset() BOOST_NOEXCEPT
{
}
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::unordered_multiset(
unordered_multiset const& other)
: table_(other.table_)
{
}
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::unordered_multiset(
BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
@@ -1437,17 +1420,44 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
table_.insert_range(list.begin(), list.end());
}
#endif
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 allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
size_type n, const allocator_type& a)
: table_(n, hasher(), key_equal(), 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(
size_type n, const hasher& hf, const allocator_type& a)
: table_(n, hf, key_equal(), 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, size_type n, const allocator_type& a)
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
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 allocator_type& a)
: table_(
boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
table_.insert_range(f, l);
}
#if !defined(BOOST_NO_CXX11_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,
@@ -1459,6 +1469,26 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
table_.insert_range(list.begin(), list.end());
}
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 allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
#endif
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::~unordered_multiset() BOOST_NOEXCEPT
{
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
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)
@@ -1517,14 +1547,12 @@ unordered_multiset<T, H, P, A>::erase(const_iterator first, const_iterator last)
return table_.erase_range(first, last);
}
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)
// C++17 support: BOOST_NOEXCEPT_IF(
// value_allocator_traits::is_always_equal::value &&
// is_nothrow_move_assignable_v<H> &&
// is_nothrow_move_assignable_v<P>)
{
table_.swap(other.table_);
}

View File

@@ -227,4 +227,36 @@ UNORDERED_AUTO_TEST(test2)
unordered_map_member_test(multimap, map_value);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
{
int value;
template <typename T> lwg2059_key(T v) : value(v) {}
};
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
}
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(lwg2059)
{
{
boost::unordered_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
{
boost::unordered_multimap<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
}
RUN_TESTS()

View File

@@ -290,4 +290,36 @@ UNORDERED_AUTO_TEST(destructible_tests)
unordered_destructible_test(multiset);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
{
int value;
template <typename T> lwg2059_key(T v) : value(v) {}
};
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
}
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(lwg2059)
{
{
boost::unordered_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
{
boost::unordered_multiset<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
}
RUN_TESTS()

View File

@@ -422,6 +422,7 @@ void unordered_map_functions(X&, Key const& k, T const& v)
X a;
test::check_return_type<mapped_type>::equals_ref(a[k]);
test::check_return_type<mapped_type>::equals_ref(a[rvalue(k)]);
test::check_return_type<mapped_type>::equals_ref(a.at(k));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.try_emplace(k, v));
@@ -554,6 +555,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
const_iterator q1 = a.cbegin(), q2 = a.cend();
test::check_return_type<iterator>::equals(a.erase(q1, q2));
TEST_NOEXCEPT_EXPR(a.clear());
a.clear();
X const b;