forked from boostorg/unordered
The new indentation made some of the code difficult to read, especially where macros were concerned, so move things around and add more explicit namespace declarations.
841 lines
26 KiB
C++
841 lines
26 KiB
C++
|
|
// Copyright 2005-2009 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)
|
|
|
|
#if defined(BOOST_MSVC)
|
|
#pragma warning(push)
|
|
#pragma warning(disable : 4100) // unreferenced formal parameter
|
|
#pragma warning(disable : 4610) // class can never be instantiated
|
|
#pragma warning(disable : 4510) // default constructor could not be generated
|
|
#endif
|
|
|
|
#include <boost/concept_check.hpp>
|
|
|
|
#if defined(BOOST_MSVC)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
#include "../helpers/check_return_type.hpp"
|
|
#include <boost/iterator/iterator_traits.hpp>
|
|
#include <boost/limits.hpp>
|
|
#include <boost/predef.h>
|
|
#include <boost/static_assert.hpp>
|
|
#include <boost/type_traits/cv_traits.hpp>
|
|
#include <boost/type_traits/is_convertible.hpp>
|
|
#include <boost/type_traits/is_same.hpp>
|
|
#include <boost/utility/swap.hpp>
|
|
|
|
typedef long double comparison_type;
|
|
|
|
template <class T> void sink(T const&) {}
|
|
template <class T> T rvalue(T const& v) { return v; }
|
|
template <class T> T rvalue_default() { return T(); }
|
|
|
|
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
template <class T> T implicit_construct() { return {}; }
|
|
#else
|
|
template <class T> int implicit_construct()
|
|
{
|
|
T x;
|
|
sink(x);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
|
|
#define TEST_NOEXCEPT_EXPR(x) BOOST_STATIC_ASSERT((BOOST_NOEXCEPT_EXPR(x)));
|
|
#else
|
|
#define TEST_NOEXCEPT_EXPR(x)
|
|
#endif
|
|
|
|
template <class X, class T> void container_test(X& r, T const&)
|
|
{
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::difference_type difference_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<iterator>::type
|
|
iterator_value_type;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<const_iterator>::type
|
|
const_iterator_value_type;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type
|
|
iterator_difference_type;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<
|
|
const_iterator>::type const_iterator_difference_type;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::reference reference;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_reference const_reference;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
|
|
|
// value_type
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
|
|
boost::function_requires<boost::CopyConstructibleConcept<X> >();
|
|
|
|
// reference_type / const_reference_type
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<T&, reference>::value));
|
|
BOOST_STATIC_ASSERT((boost::is_same<T const&, const_reference>::value));
|
|
|
|
// iterator
|
|
|
|
boost::function_requires<boost::InputIteratorConcept<iterator> >();
|
|
BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value));
|
|
BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value));
|
|
|
|
// const_iterator
|
|
|
|
boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
|
|
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
|
|
|
|
// node_type
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<allocator_type,
|
|
BOOST_DEDUCED_TYPENAME node_type::allocator_type>::value));
|
|
|
|
// difference_type
|
|
|
|
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed);
|
|
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_integer);
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<difference_type, iterator_difference_type>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<difference_type, const_iterator_difference_type>::value));
|
|
|
|
// size_type
|
|
|
|
BOOST_STATIC_ASSERT(!std::numeric_limits<size_type>::is_signed);
|
|
BOOST_STATIC_ASSERT(std::numeric_limits<size_type>::is_integer);
|
|
|
|
// size_type can represent any non-negative value type of difference_type
|
|
// I'm not sure about either of these tests...
|
|
size_type max_diff =
|
|
static_cast<size_type>((std::numeric_limits<difference_type>::max)());
|
|
difference_type converted_diff(static_cast<difference_type>(max_diff));
|
|
BOOST_TEST((std::numeric_limits<difference_type>::max)() == converted_diff);
|
|
|
|
BOOST_TEST(
|
|
static_cast<comparison_type>((std::numeric_limits<size_type>::max)()) >
|
|
static_cast<comparison_type>(
|
|
(std::numeric_limits<difference_type>::max)()));
|
|
|
|
// Constructors
|
|
|
|
// I don't test the runtime post-conditions here.
|
|
|
|
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
// It isn't specified in the container requirements that the no argument
|
|
// constructor is implicit, but it is defined that way in the concrete
|
|
// container specification.
|
|
X u_implicit = {};
|
|
sink(u_implicit);
|
|
#endif
|
|
|
|
X u;
|
|
BOOST_TEST(u.size() == 0);
|
|
BOOST_TEST(X().size() == 0);
|
|
|
|
X a, b;
|
|
X a_const;
|
|
|
|
sink(X(a));
|
|
X u2(a);
|
|
X u3 = a;
|
|
X u4(rvalue(a_const));
|
|
X u5 = rvalue(a_const);
|
|
|
|
a.swap(b);
|
|
boost::swap(a, b);
|
|
test::check_return_type<X>::equals_ref(r = a);
|
|
|
|
// Allocator
|
|
|
|
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
|
|
|
allocator_type m = a.get_allocator();
|
|
sink(X(m));
|
|
X c(m);
|
|
sink(X(a_const, m));
|
|
X c2(a_const, m);
|
|
sink(X(rvalue(a_const), m));
|
|
X c3(rvalue(a_const), m);
|
|
|
|
// node_type
|
|
|
|
implicit_construct<node_type const>();
|
|
#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
|
|
TEST_NOEXCEPT_EXPR(node_type());
|
|
#endif
|
|
|
|
node_type n1;
|
|
node_type n2(rvalue_default<node_type>());
|
|
#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
|
|
TEST_NOEXCEPT_EXPR(node_type(boost::move(n1)));
|
|
#endif
|
|
node_type n3;
|
|
n3 = boost::move(n2);
|
|
n1.swap(n3);
|
|
swap(n1, n3);
|
|
// TODO: noexcept for swap?
|
|
// value, key, mapped tests in map and set specific testing.
|
|
|
|
node_type const n_const;
|
|
BOOST_TEST(n_const ? 0 : 1);
|
|
TEST_NOEXCEPT_EXPR(n_const ? 0 : 1);
|
|
test::check_return_type<bool>::equals(!n_const);
|
|
test::check_return_type<bool>::equals(n_const.empty());
|
|
TEST_NOEXCEPT_EXPR(!n_const);
|
|
TEST_NOEXCEPT_EXPR(n_const.empty());
|
|
|
|
// Avoid unused variable warnings:
|
|
|
|
sink(u);
|
|
sink(u2);
|
|
sink(u3);
|
|
sink(u4);
|
|
sink(u5);
|
|
sink(c);
|
|
sink(c2);
|
|
sink(c3);
|
|
}
|
|
|
|
template <class X> void unordered_destructible_test(X&)
|
|
{
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
|
|
|
|
X x1;
|
|
|
|
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
|
X x2(rvalue_default<X>());
|
|
X x3 = rvalue_default<X>();
|
|
// This can only be done if propagate_on_container_move_assignment::value
|
|
// is true.
|
|
// x2 = rvalue_default<X>();
|
|
#endif
|
|
|
|
X* ptr = new X();
|
|
X& a1 = *ptr;
|
|
(&a1)->~X();
|
|
::operator delete((void*)(&a1));
|
|
|
|
X a, b;
|
|
X const a_const;
|
|
test::check_return_type<iterator>::equals(a.begin());
|
|
test::check_return_type<const_iterator>::equals(a_const.begin());
|
|
test::check_return_type<const_iterator>::equals(a.cbegin());
|
|
test::check_return_type<const_iterator>::equals(a_const.cbegin());
|
|
test::check_return_type<iterator>::equals(a.end());
|
|
test::check_return_type<const_iterator>::equals(a_const.end());
|
|
test::check_return_type<const_iterator>::equals(a.cend());
|
|
test::check_return_type<const_iterator>::equals(a_const.cend());
|
|
|
|
a.swap(b);
|
|
boost::swap(a, b);
|
|
|
|
test::check_return_type<size_type>::equals(a.size());
|
|
test::check_return_type<size_type>::equals(a.max_size());
|
|
test::check_return_type<bool>::convertible(a.empty());
|
|
|
|
// Allocator
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
|
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
|
}
|
|
|
|
template <class X, class Key> void unordered_set_test(X& r, Key const&)
|
|
{
|
|
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
|
|
|
|
// iterator pointer / const_pointer_type
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type
|
|
iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type
|
|
const_iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type
|
|
local_iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<
|
|
const_local_iterator>::type const_local_iterator_pointer;
|
|
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type const*, iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type const*, const_iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type const*, local_iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type const*, const_local_iterator_pointer>::value));
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
|
typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type;
|
|
BOOST_STATIC_ASSERT((boost::is_same<value_type, node_value_type>::value));
|
|
|
|
// Call node_type functions.
|
|
|
|
test::minimal::constructor_param v;
|
|
Key k_lvalue(v);
|
|
r.emplace(boost::move(k_lvalue));
|
|
node_type n1 = r.extract(r.begin());
|
|
test::check_return_type<value_type>::equals_ref(n1.value());
|
|
}
|
|
|
|
template <class X, class Key, class T>
|
|
void unordered_map_test(X& r, Key const& k, T const& v)
|
|
{
|
|
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
|
|
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type, std::pair<key_type const, T> >::value));
|
|
|
|
// iterator pointer / const_pointer_type
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type
|
|
iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type
|
|
const_iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type
|
|
local_iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<
|
|
const_local_iterator>::type const_local_iterator_pointer;
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type const*, const_iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type*, local_iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<value_type const*, const_local_iterator_pointer>::value));
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
|
typedef BOOST_DEDUCED_TYPENAME node_type::key_type node_key_type;
|
|
typedef BOOST_DEDUCED_TYPENAME node_type::mapped_type node_mapped_type;
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<Key, node_key_type>::value));
|
|
BOOST_STATIC_ASSERT((boost::is_same<T, node_mapped_type>::value));
|
|
// Superfluous,but just to make sure.
|
|
BOOST_STATIC_ASSERT((!boost::is_const<node_key_type>::value));
|
|
|
|
// Calling functions
|
|
|
|
r.insert(std::pair<Key const, T>(k, v));
|
|
r.insert(r.begin(), std::pair<Key const, T>(k, v));
|
|
std::pair<Key const, T> const value(k, v);
|
|
r.insert(value);
|
|
r.insert(r.end(), value);
|
|
|
|
Key k_lvalue(k);
|
|
T v_lvalue(v);
|
|
|
|
// Emplace
|
|
|
|
r.emplace(k, v);
|
|
r.emplace(k_lvalue, v_lvalue);
|
|
r.emplace(rvalue(k), rvalue(v));
|
|
|
|
r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k),
|
|
boost::make_tuple(v));
|
|
|
|
// Emplace with hint
|
|
|
|
r.emplace_hint(r.begin(), k, v);
|
|
r.emplace_hint(r.begin(), k_lvalue, v_lvalue);
|
|
r.emplace_hint(r.begin(), rvalue(k), rvalue(v));
|
|
|
|
r.emplace_hint(r.begin(), boost::unordered::piecewise_construct,
|
|
boost::make_tuple(k), boost::make_tuple(v));
|
|
|
|
// Extract
|
|
|
|
test::check_return_type<node_type>::equals(r.extract(r.begin()));
|
|
|
|
r.emplace(k, v);
|
|
test::check_return_type<node_type>::equals(r.extract(k));
|
|
|
|
r.emplace(k, v);
|
|
node_type n1 = r.extract(r.begin());
|
|
test::check_return_type<key_type>::equals_ref(n1.key());
|
|
test::check_return_type<T>::equals_ref(n1.mapped());
|
|
|
|
node_type n2 = boost::move(n1);
|
|
r.insert(boost::move(n2));
|
|
r.insert(r.extract(r.begin()));
|
|
n2 = r.extract(r.begin());
|
|
r.insert(r.begin(), boost::move(n2));
|
|
r.insert(r.end(), r.extract(r.begin()));
|
|
|
|
node_type n = r.extract(r.begin());
|
|
test::check_return_type<node_key_type>::equals_ref(n.key());
|
|
test::check_return_type<node_mapped_type>::equals_ref(n.mapped());
|
|
}
|
|
|
|
template <class X> void equality_test(X& r)
|
|
{
|
|
X const a = r, b = r;
|
|
|
|
test::check_return_type<bool>::equals(a == b);
|
|
test::check_return_type<bool>::equals(a != b);
|
|
test::check_return_type<bool>::equals(boost::operator==(a, b));
|
|
test::check_return_type<bool>::equals(boost::operator!=(a, b));
|
|
}
|
|
|
|
template <class X, class T> void unordered_unique_test(X& r, T const& t)
|
|
{
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
|
|
test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t));
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::insert_return_type insert_return_type;
|
|
|
|
// insert_return_type
|
|
|
|
// TODO;
|
|
// boost::function_requires<
|
|
// boost::MoveConstructibleConcept<insert_return_type>
|
|
// >();
|
|
// TODO;
|
|
// boost::function_requires<
|
|
// boost::MoveAssignableConcept<insert_return_type>
|
|
// >();
|
|
boost::function_requires<
|
|
boost::DefaultConstructibleConcept<insert_return_type> >();
|
|
// TODO:
|
|
// boost::function_requires<
|
|
// boost::DestructibleConcept<insert_return_type>
|
|
// >();
|
|
insert_return_type insert_return, insert_return2;
|
|
test::check_return_type<bool>::equals(insert_return.inserted);
|
|
test::check_return_type<iterator>::equals(insert_return.position);
|
|
test::check_return_type<node_type>::equals_ref(insert_return.node);
|
|
boost::swap(insert_return, insert_return2);
|
|
}
|
|
|
|
template <class X, class T> void unordered_equivalent_test(X& r, T const& t)
|
|
{
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
test::check_return_type<iterator>::equals(r.insert(t));
|
|
test::check_return_type<iterator>::equals(r.emplace(t));
|
|
}
|
|
|
|
template <class X, class Key, class T>
|
|
void unordered_map_functions(X&, Key const& k, T const& v)
|
|
{
|
|
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
|
|
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));
|
|
test::check_return_type<std::pair<iterator, bool> >::equals(
|
|
a.try_emplace(rvalue(k), v));
|
|
test::check_return_type<iterator>::equals(a.try_emplace(a.begin(), k, v));
|
|
test::check_return_type<iterator>::equals(
|
|
a.try_emplace(a.begin(), rvalue(k), v));
|
|
test::check_return_type<std::pair<iterator, bool> >::equals(
|
|
a.insert_or_assign(k, v));
|
|
test::check_return_type<std::pair<iterator, bool> >::equals(
|
|
a.insert_or_assign(rvalue(k), v));
|
|
test::check_return_type<iterator>::equals(
|
|
a.insert_or_assign(a.begin(), k, v));
|
|
test::check_return_type<iterator>::equals(
|
|
a.insert_or_assign(a.begin(), rvalue(k), v));
|
|
|
|
X const b = a;
|
|
test::check_return_type<mapped_type const>::equals_ref(b.at(k));
|
|
}
|
|
|
|
template <class X, class Key, class Hash, class Pred>
|
|
void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
|
{
|
|
unordered_destructible_test(x);
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
|
|
typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
|
|
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<iterator>::type
|
|
iterator_category;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type
|
|
iterator_difference;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type
|
|
iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<iterator>::type
|
|
iterator_reference;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<
|
|
local_iterator>::type local_iterator_category;
|
|
typedef BOOST_DEDUCED_TYPENAME
|
|
boost::iterator_difference<local_iterator>::type local_iterator_difference;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type
|
|
local_iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<local_iterator>::type
|
|
local_iterator_reference;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<
|
|
const_iterator>::type const_iterator_category;
|
|
typedef BOOST_DEDUCED_TYPENAME
|
|
boost::iterator_difference<const_iterator>::type const_iterator_difference;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type
|
|
const_iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<const_iterator>::type
|
|
const_iterator_reference;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<
|
|
const_local_iterator>::type const_local_iterator_category;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<
|
|
const_local_iterator>::type const_local_iterator_difference;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<
|
|
const_local_iterator>::type const_local_iterator_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<
|
|
const_local_iterator>::type const_local_iterator_reference;
|
|
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
|
|
// boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
|
|
// boost::function_requires<boost::AssignableConcept<key_type> >();
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value));
|
|
test::check_return_type<std::size_t>::equals(hf(k));
|
|
|
|
BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value));
|
|
test::check_return_type<bool>::convertible(eq(k, k));
|
|
|
|
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<local_iterator_category, iterator_category>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<local_iterator_difference, iterator_difference>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<local_iterator_pointer, iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT(
|
|
(boost::is_same<local_iterator_reference, iterator_reference>::value));
|
|
|
|
boost::function_requires<
|
|
boost::InputIteratorConcept<const_local_iterator> >();
|
|
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_category,
|
|
const_iterator_category>::value));
|
|
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_difference,
|
|
const_iterator_difference>::value));
|
|
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_pointer,
|
|
const_iterator_pointer>::value));
|
|
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
|
|
const_iterator_reference>::value));
|
|
|
|
X a;
|
|
allocator_type m = a.get_allocator();
|
|
|
|
// Constructors
|
|
|
|
X(10, hf, eq);
|
|
X a1(10, hf, eq);
|
|
X(10, hf);
|
|
X a2(10, hf);
|
|
X(10);
|
|
X a3(10);
|
|
X();
|
|
X a4;
|
|
|
|
X(10, hf, eq, m);
|
|
X a1a(10, hf, eq, m);
|
|
X(10, hf, m);
|
|
X a2a(10, hf, m);
|
|
X(10, m);
|
|
X a3a(10, m);
|
|
(X(m));
|
|
X a4a(m);
|
|
|
|
test::check_return_type<size_type>::equals(a.erase(k));
|
|
|
|
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;
|
|
|
|
test::check_return_type<hasher>::equals(b.hash_function());
|
|
test::check_return_type<key_equal>::equals(b.key_eq());
|
|
|
|
test::check_return_type<iterator>::equals(a.find(k));
|
|
test::check_return_type<const_iterator>::equals(b.find(k));
|
|
test::check_return_type<size_type>::equals(b.count(k));
|
|
test::check_return_type<std::pair<iterator, iterator> >::equals(
|
|
a.equal_range(k));
|
|
test::check_return_type<std::pair<const_iterator, const_iterator> >::equals(
|
|
b.equal_range(k));
|
|
test::check_return_type<size_type>::equals(b.bucket_count());
|
|
test::check_return_type<size_type>::equals(b.max_bucket_count());
|
|
test::check_return_type<size_type>::equals(b.bucket(k));
|
|
test::check_return_type<size_type>::equals(b.bucket_size(0));
|
|
|
|
test::check_return_type<local_iterator>::equals(a.begin(0));
|
|
test::check_return_type<const_local_iterator>::equals(b.begin(0));
|
|
test::check_return_type<local_iterator>::equals(a.end(0));
|
|
test::check_return_type<const_local_iterator>::equals(b.end(0));
|
|
|
|
test::check_return_type<const_local_iterator>::equals(a.cbegin(0));
|
|
test::check_return_type<const_local_iterator>::equals(b.cbegin(0));
|
|
test::check_return_type<const_local_iterator>::equals(a.cend(0));
|
|
test::check_return_type<const_local_iterator>::equals(b.cend(0));
|
|
|
|
test::check_return_type<float>::equals(b.load_factor());
|
|
test::check_return_type<float>::equals(b.max_load_factor());
|
|
a.max_load_factor((float)2.0);
|
|
a.rehash(100);
|
|
|
|
a.merge(a2);
|
|
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
|
a.merge(rvalue_default<X>());
|
|
#endif
|
|
|
|
// Avoid unused variable warnings:
|
|
|
|
sink(a);
|
|
sink(a1);
|
|
sink(a2);
|
|
sink(a3);
|
|
sink(a4);
|
|
sink(a1a);
|
|
sink(a2a);
|
|
sink(a3a);
|
|
sink(a4a);
|
|
}
|
|
|
|
template <class X, class Key, class T, class Hash, class Pred>
|
|
void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
|
{
|
|
unordered_test(x, k, hf, eq);
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
|
|
|
X a;
|
|
allocator_type m = a.get_allocator();
|
|
|
|
BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
|
|
BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
|
|
|
|
// Constructors
|
|
|
|
X(i, j, 10, hf, eq);
|
|
X a5(i, j, 10, hf, eq);
|
|
X(i, j, 10, hf);
|
|
X a6(i, j, 10, hf);
|
|
X(i, j, 10);
|
|
X a7(i, j, 10);
|
|
X(i, j);
|
|
X a8(i, j);
|
|
|
|
X(i, j, 10, hf, eq, m);
|
|
X a5a(i, j, 10, hf, eq, m);
|
|
X(i, j, 10, hf, m);
|
|
X a6a(i, j, 10, hf, m);
|
|
X(i, j, 10, m);
|
|
X a7a(i, j, 10, m);
|
|
|
|
// Not specified for some reason (maybe ambiguity with another constructor?)
|
|
// X(i, j, m);
|
|
// X a8a(i, j, m);
|
|
// sink(a8a);
|
|
|
|
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
std::size_t min_buckets = 10;
|
|
X({t});
|
|
X({t}, min_buckets);
|
|
X({t}, min_buckets, hf);
|
|
X({t}, min_buckets, hf, eq);
|
|
// X({t}, m);
|
|
X({t}, min_buckets, m);
|
|
X({t}, min_buckets, hf, m);
|
|
X({t}, min_buckets, hf, eq, m);
|
|
#endif
|
|
|
|
X const b;
|
|
sink(X(b));
|
|
X a9(b);
|
|
a = b;
|
|
|
|
sink(X(b, m));
|
|
X a9a(b, m);
|
|
|
|
X b1;
|
|
b1.insert(t);
|
|
X a9b(b1);
|
|
sink(a9b);
|
|
X a9c(b1, m);
|
|
sink(a9c);
|
|
|
|
const_iterator q = a.cbegin();
|
|
|
|
test::check_return_type<iterator>::equals(a.insert(q, t));
|
|
test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
|
|
|
|
a.insert(i, j);
|
|
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
std::initializer_list<T> list = {t};
|
|
a.insert(list);
|
|
a.insert({t, t, t});
|
|
|
|
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) && \
|
|
(!defined(__clang__) || __clang_major__ >= 4 || \
|
|
(__clang_major__ == 3 && __clang_minor__ >= 4))
|
|
a.insert({});
|
|
a.insert({t});
|
|
a.insert({t, t});
|
|
#endif
|
|
#endif
|
|
|
|
X a10;
|
|
a10.insert(t);
|
|
q = a10.cbegin();
|
|
test::check_return_type<iterator>::equals(a10.erase(q));
|
|
|
|
// Avoid unused variable warnings:
|
|
|
|
sink(a);
|
|
sink(a5);
|
|
sink(a6);
|
|
sink(a7);
|
|
sink(a8);
|
|
sink(a9);
|
|
sink(a5a);
|
|
sink(a6a);
|
|
sink(a7a);
|
|
sink(a9a);
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
|
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
|
node_type const n_const = a.extract(a.begin());
|
|
test::check_return_type<allocator_type>::equals(n_const.get_allocator());
|
|
}
|
|
|
|
template <class X, class Key, class T, class Hash, class Pred>
|
|
void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
|
|
{
|
|
unordered_test(x, k, hf, eq);
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
|
|
|
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
|
X x1(rvalue_default<X>());
|
|
X x2(boost::move(x1));
|
|
x1 = rvalue_default<X>();
|
|
x2 = boost::move(x1);
|
|
#endif
|
|
|
|
X a;
|
|
allocator_type m = a.get_allocator();
|
|
|
|
test::minimal::constructor_param* i = 0;
|
|
test::minimal::constructor_param* j = 0;
|
|
|
|
// Constructors
|
|
|
|
X(i, j, 10, hf, eq);
|
|
X a5(i, j, 10, hf, eq);
|
|
X(i, j, 10, hf);
|
|
X a6(i, j, 10, hf);
|
|
X(i, j, 10);
|
|
X a7(i, j, 10);
|
|
X(i, j);
|
|
X a8(i, j);
|
|
|
|
X(i, j, 10, hf, eq, m);
|
|
X a5a(i, j, 10, hf, eq, m);
|
|
X(i, j, 10, hf, m);
|
|
X a6a(i, j, 10, hf, m);
|
|
X(i, j, 10, m);
|
|
X a7a(i, j, 10, m);
|
|
|
|
// Not specified for some reason (maybe ambiguity with another constructor?)
|
|
// X(i, j, m);
|
|
// X a8a(i, j, m);
|
|
// sink(a8a);
|
|
|
|
const_iterator q = a.cbegin();
|
|
|
|
test::minimal::constructor_param v;
|
|
a.emplace(v);
|
|
test::check_return_type<iterator>::equals(a.emplace_hint(q, v));
|
|
|
|
T v1(v);
|
|
a.emplace(boost::move(v1));
|
|
T v2(v);
|
|
a.insert(boost::move(v2));
|
|
T v3(v);
|
|
test::check_return_type<iterator>::equals(a.emplace_hint(q, boost::move(v3)));
|
|
T v4(v);
|
|
test::check_return_type<iterator>::equals(a.insert(q, boost::move(v4)));
|
|
|
|
a.insert(i, j);
|
|
|
|
X a10;
|
|
T v5(v);
|
|
a10.insert(boost::move(v5));
|
|
q = a10.cbegin();
|
|
test::check_return_type<iterator>::equals(a10.erase(q));
|
|
|
|
// Avoid unused variable warnings:
|
|
|
|
sink(a);
|
|
sink(a5);
|
|
sink(a6);
|
|
sink(a7);
|
|
sink(a8);
|
|
sink(a5a);
|
|
sink(a6a);
|
|
sink(a7a);
|
|
sink(a10);
|
|
}
|
|
|
|
template <class X, class T> void unordered_set_member_test(X& x, T& t)
|
|
{
|
|
X x1(x);
|
|
x1.insert(t);
|
|
x1.begin()->dummy_member();
|
|
x1.cbegin()->dummy_member();
|
|
}
|
|
|
|
template <class X, class T> void unordered_map_member_test(X& x, T& t)
|
|
{
|
|
X x1(x);
|
|
x1.insert(t);
|
|
x1.begin()->first.dummy_member();
|
|
x1.cbegin()->first.dummy_member();
|
|
x1.begin()->second.dummy_member();
|
|
x1.cbegin()->second.dummy_member();
|
|
}
|