Unordered: Starting to support allocator_traits.

[SVN r73678]
This commit is contained in:
Daniel James
2011-08-11 21:17:57 +00:00
parent 3d5314b5f5
commit 99e6bef4ef
11 changed files with 435 additions and 88 deletions

View File

@ -1,9 +1,12 @@
// Copyright 2005-2011 Daniel James.
// Copyright 2009 Pablo Halpern.
//
// 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)
// A couple of templates to make using allocators easier.
//
// Written by Daniel James using some code from Pablo Halpern's
// allocator traits implementation.
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
@ -13,6 +16,7 @@
#endif
#include <boost/config.hpp>
#include <boost/detail/select_type.hpp>
#if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
&& !defined(__BORLANDC__)
@ -23,24 +27,185 @@
# include <boost/detail/allocator_utilities.hpp>
#endif
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
# include <memory>
#endif
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
#include <type_traits>
namespace boost { namespace unordered { namespace detail {
using std::integral_constant;
using std::true_type;
using std::false_type;
}}}
#else
namespace boost { namespace unordered { namespace detail {
template <typename T, T Value>
struct integral_constant { enum { value = Value }; };
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
}}}
#endif
namespace boost { namespace unordered { namespace detail {
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
template <typename Alloc>
struct allocator_traits : std::allocator_traits<Alloc> {};
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef typename allocator_traits<Alloc>::rebind_alloc<T> type;
};
#else
// rebind_wrap
//
// Rebind allocators. For some problematic libraries, use rebind_to
// from <boost/detail/allocator_utilities.hpp>.
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
template <class Alloc, class T>
# if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
template <typename Alloc, typename T>
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
#else
template <class Alloc, class T>
# else
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef BOOST_DEDUCED_TYPENAME
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
# endif
struct convertible_from_anything
{
template<typename T> convertible_from_anything(T const&);
};
// Infrastructure for providing a default type for Tp::tname if absent.
#define BOOST_DEFAULT_TYPE_TMPLT(tname) \
template <typename Tp, typename Default> \
struct default_type_ ## tname { \
\
template <typename X> \
static char test(int, BOOST_DEDUCED_TYPENAME X::tname*); \
\
template <typename X> \
static int test(convertible_from_anything, void*); \
\
struct DefaultWrap { typedef Default tname; }; \
\
static const bool value = (1 == sizeof(test<Tp>(0, 0))); \
\
typedef BOOST_DEDUCED_TYPENAME \
boost::detail::if_true<value>:: \
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
::type::tname type; \
}
#define BOOST_DEFAULT_TYPE(T,tname, arg) \
BOOST_DEDUCED_TYPENAME default_type_ ## tname<T, arg>::type
BOOST_DEFAULT_TYPE_TMPLT(pointer);
BOOST_DEFAULT_TYPE_TMPLT(const_pointer);
BOOST_DEFAULT_TYPE_TMPLT(void_pointer);
BOOST_DEFAULT_TYPE_TMPLT(const_void_pointer);
BOOST_DEFAULT_TYPE_TMPLT(difference_type);
BOOST_DEFAULT_TYPE_TMPLT(size_type);
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
template <typename Alloc>
struct allocator_traits
{
typedef Alloc allocator_type;
typedef typename Alloc::value_type value_type;
typedef BOOST_DEFAULT_TYPE(Alloc, pointer, value_type*)
pointer;
// For now always use the allocator's const_pointer.
//typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer,
// BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<const value_type>::other)
// const_pointer;
typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer, value_type const*)
const_pointer;
// I'm not using void pointers for now.
//typedef BOOST_DEFAULT_TYPE(Alloc, void_pointer,
// BOOST_NESTED_TEMPLATE pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<void>::other)
// void_pointer;
//typedef BOOST_DEFAULT_TYPE(Alloc, const_void_pointer,
// BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
// BOOST_NESTED_TEMPLATE rebind<const void>::other)
// const_void_pointer;
typedef BOOST_DEFAULT_TYPE(Alloc, difference_type, std::ptrdiff_t)
difference_type;
typedef BOOST_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type;
// TODO: rebind_alloc and rebind_traits
static pointer allocate(Alloc& a, size_type n)
{ return a.allocate(n); }
// I never use this, so I'll just comment it out for now.
//
//static pointer allocate(Alloc& a, size_type n, const_void_pointer hint)
// { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
static void deallocate(Alloc& a, pointer p, size_type n)
{ a.deallocate(p, n); }
// Only support the basic copy constructor
// template <typename T, typename... Args>
// static void construct(Alloc& a, T* p, Args&&... args) {
// DEFAULT_FUNC(construct,void)(a, p, std::forward<Args>(args)...);
// }
template <typename T>
static void construct(Alloc& a, T* p, T const& x) {
a.construct(p, x);
}
template <typename T>
static void destroy(Alloc& a, T* p) {
// DEFAULT_FUNC(destroy,void)(a, p);
a.destroy(p);
}
static size_type max_size(const Alloc& a)
{ return a.max_size(); }
// Allocator propagation on construction
static Alloc select_on_container_copy_construction(const Alloc& rhs) {
//return BOOST_DEFAULT_FUNC(select_on_container_copy_construction,Alloc)(rhs);
return rhs;
}
// Allocator propagation on assignment and swap.
// Return true if lhs is modified.
typedef BOOST_DEFAULT_TYPE(
Alloc, propagate_on_container_copy_assignment, false_type)
propagate_on_container_copy_assignment;
typedef BOOST_DEFAULT_TYPE(
Alloc,propagate_on_container_move_assignment, false_type)
propagate_on_container_move_assignment;
typedef BOOST_DEFAULT_TYPE(
Alloc,propagate_on_container_swap,false_type)
propagate_on_container_swap;
};
#endif
// allocator_array_constructor
@ -49,10 +214,11 @@ namespace boost { namespace unordered { namespace detail {
// clean up if an exception is thrown before the container takes charge
// of it.
template <class Allocator>
template <typename Allocator>
struct allocator_array_constructor
{
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<Allocator>::pointer
pointer;
Allocator& alloc_;
pointer ptr_;
@ -69,21 +235,21 @@ namespace boost { namespace unordered { namespace detail {
~allocator_array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
alloc_.destroy(p);
allocator_traits<Allocator>::destroy(alloc_, p);
alloc_.deallocate(ptr_, length_);
allocator_traits<Allocator>::deallocate(alloc_, ptr_, length_);
}
}
template <class V>
template <typename V>
void construct(V const& v, std::size_t l)
{
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = alloc_.allocate(length_);
ptr_ = allocator_traits<Allocator>::allocate(alloc_, length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
alloc_.construct(constructed_, v);
allocator_traits<Allocator>::construct(alloc_, constructed_, v);
}
pointer get() const

View File

@ -49,16 +49,16 @@ namespace boost { namespace unordered { namespace detail {
typedef A value_allocator;
typedef ::boost::unordered::detail::bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_allocator
bucket_allocator;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<bucket_allocator>::pointer bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
node_allocator;
typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<node_allocator>::pointer real_node_ptr;
// Members
@ -91,7 +91,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_bucket_count() const
{
// -1 to account for the start bucket.
return prev_prime(this->bucket_alloc().max_size() - 1);
return prev_prime(allocator_traits<bucket_allocator>::max_size(bucket_alloc()) - 1);
}
////////////////////////////////////////////////////////////////////////
@ -184,8 +184,8 @@ namespace boost { namespace unordered { namespace detail {
real_node_ptr real_ptr(node_alloc().address(*raw_ptr));
::boost::unordered::detail::destroy(raw_ptr->value_ptr());
node_alloc().destroy(real_ptr);
node_alloc().deallocate(real_ptr, 1);
allocator_traits<node_allocator>::destroy(node_alloc(), real_ptr);
allocator_traits<node_allocator>::deallocate(node_alloc(), real_ptr, 1);
}
void delete_buckets()
@ -202,10 +202,10 @@ namespace boost { namespace unordered { namespace detail {
++end;
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
bucket_alloc().destroy(begin);
allocator_traits<bucket_allocator>::destroy(bucket_alloc(), begin);
}
bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1);
allocator_traits<bucket_allocator>::deallocate(bucket_alloc(), this->buckets_, this->bucket_count_ + 1);
this->buckets_ = bucket_ptr();
}
@ -476,6 +476,7 @@ namespace boost { namespace unordered { namespace detail {
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
buckets& buckets_;
real_node_ptr node_;
@ -570,9 +571,9 @@ namespace boost { namespace unordered { namespace detail {
}
if (node_constructed_)
buckets_.node_alloc().destroy(node_);
allocator_traits<node_allocator>::destroy(buckets_.node_alloc(), node_);
buckets_.node_alloc().deallocate(node_, 1);
allocator_traits<node_allocator>::deallocate(buckets_.node_alloc(), node_, 1);
}
}
@ -583,8 +584,8 @@ namespace boost { namespace unordered { namespace detail {
node_constructed_ = false;
value_constructed_ = false;
node_ = buckets_.node_alloc().allocate(1);
buckets_.node_alloc().construct(node_, node());
node_ = allocator_traits<node_allocator>::allocate(buckets_.node_alloc(), 1);
allocator_traits<node_allocator>::construct(buckets_.node_alloc(), node_, node());
node_->init(buckets_.bucket_alloc().address(*node_));
node_constructed_ = true;

View File

@ -279,10 +279,10 @@ namespace boost { namespace unordered { namespace detail {
template <class H, class P, class A>
struct multiset : public types<
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
H, P, A,
set_extractor<BOOST_DEDUCED_TYPENAME A::value_type>,
set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
false>
{
typedef equivalent_table<multiset<H, P, A> > impl;
@ -291,9 +291,9 @@ namespace boost { namespace unordered { namespace detail {
template <class K, class H, class P, class A>
struct multimap : public types<
K, BOOST_DEDUCED_TYPENAME A::value_type,
K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
H, P, A,
map_extractor<K, BOOST_DEDUCED_TYPENAME A::value_type>,
map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
false>
{
typedef equivalent_table<multimap<K, H, P, A> > impl;

View File

@ -28,7 +28,7 @@ namespace boost { namespace unordered { namespace detail {
//
// For unordered_set/unordered_map:
//
// bucket<A> value_base<A::value_type>
// bucket<A> value_base<allocator_traits<A>::value_type>
// | |
// +--------------+-------------+
// |
@ -36,7 +36,7 @@ namespace boost { namespace unordered { namespace detail {
//
// For unordered_multiset/unordered_multimap:
//
// bucket<A> value_base<A::value_type>
// bucket<A> value_base<allocator_traits<A>::value_type>
// | |
// +--------------+-------------+
// |
@ -57,7 +57,8 @@ namespace boost { namespace unordered { namespace detail {
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<A, bucket>::type
bucket_allocator;
typedef BOOST_DEDUCED_TYPENAME bucket_allocator::pointer bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME
allocator_traits<bucket_allocator>::pointer bucket_ptr;
typedef bucket_ptr node_ptr;
node_ptr next_;
@ -101,12 +102,12 @@ namespace boost { namespace unordered { namespace detail {
template <class A>
struct ungrouped_node
: ::boost::unordered::detail::bucket<A>,
value_base<BOOST_DEDUCED_TYPENAME A::value_type>
value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
{
typedef ::boost::unordered::detail::bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
std::size_t hash_;
@ -176,12 +177,12 @@ namespace boost { namespace unordered { namespace detail {
template <class A>
struct grouped_node
: ::boost::unordered::detail::bucket<A>,
value_base<BOOST_DEDUCED_TYPENAME A::value_type>
value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
{
typedef ::boost::unordered::detail::bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
std::size_t hash_;
node_ptr group_prev_;

View File

@ -617,13 +617,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
class l_iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::pointer,
BOOST_DEDUCED_TYPENAME A::reference>
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type&>
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
@ -641,7 +641,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
l_iterator() : ptr_() {}
l_iterator(node_ptr x, std::size_t b, std::size_t c)
: ptr_(x), bucket_(b), bucket_count_(c) {}
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
return node::get_value(ptr_);
}
value_type* operator->() const {
@ -678,13 +678,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
class cl_iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::const_pointer,
BOOST_DEDUCED_TYPENAME A::const_reference >
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
@ -705,7 +705,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
cl_iterator(local_iterator x)
: ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
BOOST_DEDUCED_TYPENAME A::const_reference
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const&
operator*() const {
return node::get_value(ptr_);
}
@ -743,13 +743,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
class iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::pointer,
BOOST_DEDUCED_TYPENAME A::reference >
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& >
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
@ -763,7 +763,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
iterator() : node_() {}
explicit iterator(node_ptr const& x) : node_(x) {}
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
return node::get_value(node_);
}
value_type* operator->() const {
@ -793,13 +793,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
class c_iterator
: public ::boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::const_pointer,
BOOST_DEDUCED_TYPENAME A::const_reference >
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
private:
typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
@ -829,7 +829,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
c_iterator() : node_() {}
explicit c_iterator(node_ptr const& x) : node_(x) {}
c_iterator(iterator const& x) : node_(x.node_) {}
BOOST_DEDUCED_TYPENAME A::const_reference operator*() const {
BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& operator*() const {
return node::get_value(node_);
}
value_type const* operator->() const {

View File

@ -370,10 +370,10 @@ namespace boost { namespace unordered { namespace detail {
template <class H, class P, class A>
struct set : public types<
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
H, P, A,
set_extractor<BOOST_DEDUCED_TYPENAME A::value_type>,
set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
true>
{
typedef ::boost::unordered::detail::unique_table<set<H, P, A> > impl;
@ -382,9 +382,9 @@ namespace boost { namespace unordered { namespace detail {
template <class K, class H, class P, class A>
struct map : public types<
K, BOOST_DEDUCED_TYPENAME A::value_type,
K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
H, P, A,
map_extractor<K, BOOST_DEDUCED_TYPENAME A::value_type>,
map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
true>
{
typedef ::boost::unordered::detail::unique_table<map<K, H, P, A> > impl;

View File

@ -56,6 +56,7 @@ namespace unordered
::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::map<K, H, P,
value_allocator> types;
@ -66,13 +67,12 @@ namespace unordered
public:
typedef BOOST_DEDUCED_TYPENAME
value_allocator::pointer pointer;
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::reference reference;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_reference const_reference;
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;
@ -407,6 +407,8 @@ namespace unordered
::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::multimap<K, H, P,
value_allocator> types;
@ -417,13 +419,12 @@ namespace unordered
public:
typedef BOOST_DEDUCED_TYPENAME
value_allocator::pointer pointer;
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::reference reference;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_reference const_reference;
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;

View File

@ -56,6 +56,8 @@ namespace unordered
::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<H, P,
value_allocator> types;
@ -66,13 +68,12 @@ namespace unordered
public:
typedef BOOST_DEDUCED_TYPENAME
value_allocator::pointer pointer;
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::reference reference;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_reference const_reference;
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;
@ -387,6 +388,8 @@ namespace unordered
::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<H, P,
value_allocator> types;
@ -397,13 +400,12 @@ namespace unordered
public:
typedef BOOST_DEDUCED_TYPENAME
value_allocator::pointer pointer;
allocator_traits::pointer pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_pointer const_pointer;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::reference reference;
typedef BOOST_DEDUCED_TYPENAME
value_allocator::const_reference const_reference;
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;

View File

@ -33,6 +33,7 @@ namespace minimal
template <class T> class ptr;
template <class T> class const_ptr;
template <class T> class allocator;
template <class T> class cxx11_allocator;
class copy_constructible
{
@ -316,6 +317,69 @@ namespace minimal
void swap(allocator<T>&, allocator<T>&)
{
}
// C++11 allocator
//
// Not a fully minimal C++11 allocator, just what I support. Hopefully will
// cut down further in the future.
template <class T>
class cxx11_allocator
{
public:
typedef T value_type;
template <class U> struct rebind { typedef cxx11_allocator<U> other; };
cxx11_allocator() {}
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
cxx11_allocator(cxx11_allocator const&) {}
~cxx11_allocator() {}
T* address(T& r) { return &r; }
T const* address(T const& r) { return &r; }
T* allocate(std::size_t n) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
template <class Y>
T* allocate(std::size_t n, const_ptr<Y> u) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
void deallocate(T* p, std::size_t) {
::operator delete((void*) p);
}
void construct(T* p, T const& t) { new((void*)p) T(t); }
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
new((void*)p) T(std::forward<Args>(args)...);
}
#endif
void destroy(T* p) { p->~T(); }
std::size_t max_size() const { return 1000u; }
};
template <class T>
inline bool operator==(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
{
return true;
}
template <class T>
inline bool operator!=(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
{
return false;
}
template <class T>
void swap(cxx11_allocator<T>&, cxx11_allocator<T>&)
{
}
}
}

View File

@ -17,6 +17,19 @@
// Explicit instantiation to catch compile-time errors
template class boost::unordered_map<
int,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_multimap<
int,
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_map<
test::minimal::assignable,
test::minimal::default_copy_constructible,
@ -42,6 +55,11 @@ UNORDERED_AUTO_TEST(test0)
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_map2;
boost::unordered_map<
test::minimal::assignable,
test::minimal::copy_constructible,
@ -50,12 +68,18 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::allocator<value_type> > map;
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_multimap2;
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible,
@ -64,6 +88,7 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::allocator<value_type> > multimap;
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value);
}
@ -74,6 +99,11 @@ UNORDERED_AUTO_TEST(equality_tests) {
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_map2;
boost::unordered_map<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
@ -82,10 +112,16 @@ UNORDERED_AUTO_TEST(equality_tests) {
test::minimal::allocator<value_type> > map;
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> int_multimap2;
boost::unordered_multimap<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
@ -94,6 +130,7 @@ UNORDERED_AUTO_TEST(equality_tests) {
test::minimal::allocator<value_type> > multimap;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
}
@ -107,18 +144,37 @@ UNORDERED_AUTO_TEST(test1) {
boost::unordered_map<int, int> map;
boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> map2;
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
unordered_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value);
unordered_unique_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> >
> multimap2;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_test(multimap2, value, map_value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
@ -149,7 +205,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_map_test(map, assignable, copy_constructible);
unordered_test(map, assignable, map_value, hash, equal_to);
boost::unordered_map<
test::minimal::assignable,
test::minimal::default_copy_constructible,

View File

@ -16,7 +16,18 @@
#include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors
/*
template class boost::unordered_set<
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
template class boost::unordered_multiset<
int,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
*/
template class boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
@ -33,7 +44,14 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::assignable assignable = test::minimal::assignable::create();
std::cout<<"Test unordered_set.\n";
boost::unordered_set<int> int_set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_set2;
boost::unordered_set<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
@ -41,10 +59,18 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::allocator<test::minimal::assignable> > set;
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_multiset2;
boost::unordered_multiset<
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
@ -52,6 +78,7 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::allocator<test::minimal::assignable> > multiset;
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
}
@ -60,6 +87,11 @@ UNORDERED_AUTO_TEST(equality_tests) {
boost::unordered_set<int> int_set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_set2;
boost::unordered_set<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
@ -67,10 +99,16 @@ UNORDERED_AUTO_TEST(equality_tests) {
test::minimal::allocator<value_type> > set;
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> int_multiset2;
boost::unordered_multiset<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
@ -78,6 +116,7 @@ UNORDERED_AUTO_TEST(equality_tests) {
test::minimal::allocator<value_type> > multiset;
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
}
@ -91,17 +130,35 @@ UNORDERED_AUTO_TEST(test1)
boost::unordered_set<int> set;
boost::unordered_set<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> set2;
unordered_unique_test(set, value);
unordered_set_test(set, value);
unordered_test(set, value, value, hash, equal_to);
unordered_unique_test(set2, value);
unordered_set_test(set2, value);
unordered_test(set2, value, value, hash, equal_to);
std::cout<<"Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset;
boost::unordered_multiset<int,
boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int>
> multiset2;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_test(multiset2, value, value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)