From 99e6bef4ef23ba46d21826e444f902a6f3add123 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 11 Aug 2011 21:17:57 +0000 Subject: [PATCH] Unordered: Starting to support allocator_traits. [SVN r73678] --- .../unordered/detail/allocator_helpers.hpp | 192 ++++++++++++++++-- include/boost/unordered/detail/buckets.hpp | 25 +-- include/boost/unordered/detail/equivalent.hpp | 10 +- include/boost/unordered/detail/node.hpp | 15 +- include/boost/unordered/detail/table.hpp | 40 ++-- include/boost/unordered/detail/unique.hpp | 10 +- include/boost/unordered/unordered_map.hpp | 25 +-- include/boost/unordered/unordered_set.hpp | 26 +-- test/objects/minimal.hpp | 64 ++++++ test/unordered/compile_map.cpp | 57 +++++- test/unordered/compile_set.cpp | 59 +++++- 11 files changed, 435 insertions(+), 88 deletions(-) diff --git a/include/boost/unordered/detail/allocator_helpers.hpp b/include/boost/unordered/detail/allocator_helpers.hpp index 417c0870..30fc94bc 100644 --- a/include/boost/unordered/detail/allocator_helpers.hpp +++ b/include/boost/unordered/detail/allocator_helpers.hpp @@ -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 +#include #if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \ && !defined(__BORLANDC__) @@ -23,24 +27,185 @@ # include #endif +#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS +# include +#endif + +#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS) +#include +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 + struct integral_constant { enum { value = Value }; }; + typedef integral_constant true_type; + typedef integral_constant false_type; +}}} +#endif + namespace boost { namespace unordered { namespace detail { +#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS + template + struct allocator_traits : std::allocator_traits {}; + + template + struct rebind_wrap + { + typedef typename allocator_traits::rebind_alloc type; + }; +#else // rebind_wrap // // Rebind allocators. For some problematic libraries, use rebind_to // from . -#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) - template +# if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) + template struct rebind_wrap : ::boost::detail::allocator::rebind_to {}; -#else - template +# else + template struct rebind_wrap { typedef BOOST_DEDUCED_TYPENAME Alloc::BOOST_NESTED_TEMPLATE rebind::other type; }; +# endif + + struct convertible_from_anything + { + template convertible_from_anything(T const&); + }; + + // Infrastructure for providing a default type for Tp::tname if absent. + #define BOOST_DEFAULT_TYPE_TMPLT(tname) \ + template \ + struct default_type_ ## tname { \ + \ + template \ + static char test(int, BOOST_DEDUCED_TYPENAME X::tname*); \ + \ + template \ + static int test(convertible_from_anything, void*); \ + \ + struct DefaultWrap { typedef Default tname; }; \ + \ + static const bool value = (1 == sizeof(test(0, 0))); \ + \ + typedef BOOST_DEDUCED_TYPENAME \ + boost::detail::if_true:: \ + BOOST_NESTED_TEMPLATE then \ + ::type::tname type; \ + } + + #define BOOST_DEFAULT_TYPE(T,tname, arg) \ + BOOST_DEDUCED_TYPENAME default_type_ ## tname::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 + 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:: + // BOOST_NESTED_TEMPLATE rebind::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:: + // BOOST_NESTED_TEMPLATE rebind::other) + // void_pointer; + + //typedef BOOST_DEFAULT_TYPE(Alloc, const_void_pointer, + // BOOST_DEDUCED_TYPENAME pointer_traits:: + // BOOST_NESTED_TEMPLATE rebind::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 + // static void construct(Alloc& a, T* p, Args&&... args) { + // DEFAULT_FUNC(construct,void)(a, p, std::forward(args)...); + // } + + template + static void construct(Alloc& a, T* p, T const& x) { + a.construct(p, x); + } + + template + 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 + template struct allocator_array_constructor { - typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer; + typedef BOOST_DEDUCED_TYPENAME allocator_traits::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::destroy(alloc_, p); - alloc_.deallocate(ptr_, length_); + allocator_traits::deallocate(alloc_, ptr_, length_); } } - template + template void construct(V const& v, std::size_t l) { BOOST_ASSERT(!ptr_); length_ = l; - ptr_ = alloc_.allocate(length_); + ptr_ = allocator_traits::allocate(alloc_, length_); pointer end = ptr_ + static_cast(length_); for(constructed_ = ptr_; constructed_ != end; ++constructed_) - alloc_.construct(constructed_, v); + allocator_traits::construct(alloc_, constructed_, v); } pointer get() const diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index 4689b322..c2ea2306 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -49,16 +49,16 @@ namespace boost { namespace unordered { namespace detail { typedef A value_allocator; typedef ::boost::unordered::detail::bucket bucket; - typedef BOOST_DEDUCED_TYPENAME A::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME allocator_traits::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::pointer bucket_ptr; typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr; typedef BOOST_DEDUCED_TYPENAME rebind_wrap::type node_allocator; - typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr; + typedef BOOST_DEDUCED_TYPENAME allocator_traits::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::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::destroy(node_alloc(), real_ptr); + allocator_traits::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::destroy(bucket_alloc(), begin); } - bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1); + allocator_traits::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::destroy(buckets_.node_alloc(), node_); - buckets_.node_alloc().deallocate(node_, 1); + allocator_traits::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::allocate(buckets_.node_alloc(), 1); + allocator_traits::construct(buckets_.node_alloc(), node_, node()); node_->init(buckets_.bucket_alloc().address(*node_)); node_constructed_ = true; diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp index 8c19ad99..ea4b438c 100644 --- a/include/boost/unordered/detail/equivalent.hpp +++ b/include/boost/unordered/detail/equivalent.hpp @@ -279,10 +279,10 @@ namespace boost { namespace unordered { namespace detail { template struct multiset : public types< - BOOST_DEDUCED_TYPENAME A::value_type, - BOOST_DEDUCED_TYPENAME A::value_type, + BOOST_DEDUCED_TYPENAME allocator_traits::value_type, + BOOST_DEDUCED_TYPENAME allocator_traits::value_type, H, P, A, - set_extractor, + set_extractor::value_type>, false> { typedef equivalent_table > impl; @@ -291,9 +291,9 @@ namespace boost { namespace unordered { namespace detail { template struct multimap : public types< - K, BOOST_DEDUCED_TYPENAME A::value_type, + K, BOOST_DEDUCED_TYPENAME allocator_traits::value_type, H, P, A, - map_extractor, + map_extractor::value_type>, false> { typedef equivalent_table > impl; diff --git a/include/boost/unordered/detail/node.hpp b/include/boost/unordered/detail/node.hpp index 7867bbad..4beddfa2 100644 --- a/include/boost/unordered/detail/node.hpp +++ b/include/boost/unordered/detail/node.hpp @@ -28,7 +28,7 @@ namespace boost { namespace unordered { namespace detail { // // For unordered_set/unordered_map: // - // bucket value_base + // bucket value_base::value_type> // | | // +--------------+-------------+ // | @@ -36,7 +36,7 @@ namespace boost { namespace unordered { namespace detail { // // For unordered_multiset/unordered_multimap: // - // bucket value_base + // bucket value_base::value_type> // | | // +--------------+-------------+ // | @@ -57,7 +57,8 @@ namespace boost { namespace unordered { namespace detail { typedef BOOST_DEDUCED_TYPENAME ::boost::unordered::detail::rebind_wrap::type bucket_allocator; - typedef BOOST_DEDUCED_TYPENAME bucket_allocator::pointer bucket_ptr; + typedef BOOST_DEDUCED_TYPENAME + allocator_traits::pointer bucket_ptr; typedef bucket_ptr node_ptr; node_ptr next_; @@ -101,12 +102,12 @@ namespace boost { namespace unordered { namespace detail { template struct ungrouped_node : ::boost::unordered::detail::bucket, - value_base + value_base::value_type> { typedef ::boost::unordered::detail::bucket 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::value_type value_type; std::size_t hash_; @@ -176,12 +177,12 @@ namespace boost { namespace unordered { namespace detail { template struct grouped_node : ::boost::unordered::detail::bucket, - value_base + value_base::value_type> { typedef ::boost::unordered::detail::bucket 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::value_type value_type; std::size_t hash_; node_ptr group_prev_; diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index db4625cc..c2f1fa77 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -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::value_type, std::ptrdiff_t, - BOOST_DEDUCED_TYPENAME A::pointer, - BOOST_DEDUCED_TYPENAME A::reference> + BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::pointer, + BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type&> { public: - typedef BOOST_DEDUCED_TYPENAME A::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type value_type; private: typedef ::boost::unordered::detail::buckets 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::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::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::const_pointer, + BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type const& > { public: - typedef BOOST_DEDUCED_TYPENAME A::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type value_type; private: typedef ::boost::unordered::detail::buckets 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::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::value_type, std::ptrdiff_t, - BOOST_DEDUCED_TYPENAME A::pointer, - BOOST_DEDUCED_TYPENAME A::reference > + BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::pointer, + BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type& > { public: - typedef BOOST_DEDUCED_TYPENAME A::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type value_type; private: typedef ::boost::unordered::detail::buckets 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::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::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::const_pointer, + BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type const& > { public: - typedef BOOST_DEDUCED_TYPENAME A::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits::value_type value_type; private: typedef ::boost::unordered::detail::buckets 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::value_type const& operator*() const { return node::get_value(node_); } value_type const* operator->() const { diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp index e115cdd3..858cc5ad 100644 --- a/include/boost/unordered/detail/unique.hpp +++ b/include/boost/unordered/detail/unique.hpp @@ -370,10 +370,10 @@ namespace boost { namespace unordered { namespace detail { template struct set : public types< - BOOST_DEDUCED_TYPENAME A::value_type, - BOOST_DEDUCED_TYPENAME A::value_type, + BOOST_DEDUCED_TYPENAME allocator_traits::value_type, + BOOST_DEDUCED_TYPENAME allocator_traits::value_type, H, P, A, - set_extractor, + set_extractor::value_type>, true> { typedef ::boost::unordered::detail::unique_table > impl; @@ -382,9 +382,9 @@ namespace boost { namespace unordered { namespace detail { template struct map : public types< - K, BOOST_DEDUCED_TYPENAME A::value_type, + K, BOOST_DEDUCED_TYPENAME allocator_traits::value_type, H, P, A, - map_extractor, + map_extractor::value_type>, true> { typedef ::boost::unordered::detail::unique_table > impl; diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 122937d1..da852a1c 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -56,6 +56,7 @@ namespace unordered ::boost::unordered::detail::rebind_wrap< allocator_type, value_type>::type value_allocator; + typedef ::boost::unordered::detail::allocator_traits allocator_traits; typedef ::boost::unordered::detail::map 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 + allocator_traits; typedef ::boost::unordered::detail::multimap 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; diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 00eaa5e8..a6525187 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -56,6 +56,8 @@ namespace unordered ::boost::unordered::detail::rebind_wrap< allocator_type, value_type>::type value_allocator; + typedef ::boost::unordered::detail::allocator_traits + allocator_traits; typedef ::boost::unordered::detail::set 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 + allocator_traits; typedef ::boost::unordered::detail::multiset 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; diff --git a/test/objects/minimal.hpp b/test/objects/minimal.hpp index be740f55..fbb5a869 100644 --- a/test/objects/minimal.hpp +++ b/test/objects/minimal.hpp @@ -33,6 +33,7 @@ namespace minimal template class ptr; template class const_ptr; template class allocator; + template class cxx11_allocator; class copy_constructible { @@ -316,6 +317,69 @@ namespace minimal void swap(allocator&, allocator&) { } + + // C++11 allocator + // + // Not a fully minimal C++11 allocator, just what I support. Hopefully will + // cut down further in the future. + + template + class cxx11_allocator + { + public: + typedef T value_type; + template struct rebind { typedef cxx11_allocator other; }; + + cxx11_allocator() {} + template cxx11_allocator(cxx11_allocator 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(::operator new(n * sizeof(T))); + } + + template + T* allocate(std::size_t n, const_ptr u) { + return static_cast(::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 void construct(T* p, Args&&... args) { + new((void*)p) T(std::forward(args)...); + } +#endif + + void destroy(T* p) { p->~T(); } + + std::size_t max_size() const { return 1000u; } + }; + + template + inline bool operator==(cxx11_allocator const&, cxx11_allocator const&) + { + return true; + } + + template + inline bool operator!=(cxx11_allocator const&, cxx11_allocator const&) + { + return false; + } + + template + void swap(cxx11_allocator&, cxx11_allocator&) + { + } } } diff --git a/test/unordered/compile_map.cpp b/test/unordered/compile_map.cpp index a006c7e4..a30e14b4 100644 --- a/test/unordered/compile_map.cpp +++ b/test/unordered/compile_map.cpp @@ -17,6 +17,19 @@ // Explicit instantiation to catch compile-time errors +template class boost::unordered_map< + int, + int, + boost::hash, + std::equal_to, + test::minimal::allocator > >; +template class boost::unordered_multimap< + int, + int, + boost::hash, + std::equal_to, + test::minimal::allocator > >; + 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_map; + boost::unordered_map, std::equal_to, + test::minimal::cxx11_allocator > + > int_map2; + boost::unordered_map< test::minimal::assignable, test::minimal::copy_constructible, @@ -50,12 +68,18 @@ UNORDERED_AUTO_TEST(test0) test::minimal::allocator > map; container_test(int_map, std::pair(0, 0)); + container_test(int_map2, std::pair(0, 0)); container_test(map, value); std::cout<<"Test unordered_multimap.\n"; boost::unordered_multimap int_multimap; + boost::unordered_multimap, std::equal_to, + test::minimal::cxx11_allocator > + > int_multimap2; + boost::unordered_multimap< test::minimal::assignable, test::minimal::copy_constructible, @@ -64,6 +88,7 @@ UNORDERED_AUTO_TEST(test0) test::minimal::allocator > multimap; container_test(int_multimap, std::pair(0, 0)); + container_test(int_multimap2, std::pair(0, 0)); container_test(multimap, value); } @@ -74,6 +99,11 @@ UNORDERED_AUTO_TEST(equality_tests) { boost::unordered_map int_map; + boost::unordered_map, std::equal_to, + test::minimal::cxx11_allocator > + > 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 > map; equality_test(int_map); + equality_test(int_map2); equality_test(map); boost::unordered_multimap int_multimap; + boost::unordered_multimap, std::equal_to, + test::minimal::cxx11_allocator > + > 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 > multimap; equality_test(int_multimap); + equality_test(int_multimap2); equality_test(multimap); } @@ -107,18 +144,37 @@ UNORDERED_AUTO_TEST(test1) { boost::unordered_map map; + boost::unordered_map, std::equal_to, + test::minimal::cxx11_allocator > + > 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 multimap; + boost::unordered_multimap, std::equal_to, + test::minimal::cxx11_allocator > + > 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, diff --git a/test/unordered/compile_set.cpp b/test/unordered/compile_set.cpp index 96647162..62efc272 100644 --- a/test/unordered/compile_set.cpp +++ b/test/unordered/compile_set.cpp @@ -16,7 +16,18 @@ #include "./compile_tests.hpp" // Explicit instantiation to catch compile-time errors - +/* +template class boost::unordered_set< + int, + boost::hash, + std::equal_to, + test::minimal::allocator >; +template class boost::unordered_multiset< + int, + boost::hash, + std::equal_to, + test::minimal::allocator >; +*/ template class boost::unordered_set< test::minimal::assignable, test::minimal::hash, @@ -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_set; + + boost::unordered_set, std::equal_to, + test::minimal::cxx11_allocator + > int_set2; + boost::unordered_set< test::minimal::assignable, test::minimal::hash, @@ -41,10 +59,18 @@ UNORDERED_AUTO_TEST(test0) test::minimal::allocator > 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_multiset; + + boost::unordered_multiset, std::equal_to, + test::minimal::cxx11_allocator + > int_multiset2; + boost::unordered_multiset< test::minimal::assignable, test::minimal::hash, @@ -52,6 +78,7 @@ UNORDERED_AUTO_TEST(test0) test::minimal::allocator > 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_set; + boost::unordered_set, std::equal_to, + test::minimal::cxx11_allocator + > int_set2; + boost::unordered_set< test::minimal::copy_constructible_equality_comparable, test::minimal::hash, @@ -67,10 +99,16 @@ UNORDERED_AUTO_TEST(equality_tests) { test::minimal::allocator > set; equality_test(int_set); + equality_test(int_set2); equality_test(set); boost::unordered_multiset int_multiset; + boost::unordered_multiset, std::equal_to, + test::minimal::cxx11_allocator + > int_multiset2; + boost::unordered_multiset< test::minimal::copy_constructible_equality_comparable, test::minimal::hash, @@ -78,6 +116,7 @@ UNORDERED_AUTO_TEST(equality_tests) { test::minimal::allocator > multiset; equality_test(int_multiset); + equality_test(int_multiset2); equality_test(multiset); } @@ -91,17 +130,35 @@ UNORDERED_AUTO_TEST(test1) boost::unordered_set set; + boost::unordered_set, std::equal_to, + test::minimal::cxx11_allocator + > 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 multiset; + boost::unordered_multiset, std::equal_to, + test::minimal::cxx11_allocator + > 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)