2 // Copyright 2011 Daniel James.
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/unordered/detail/allocate.hpp>
7 #include <boost/detail/lightweight_test.hpp>
8 #include <boost/type_traits/is_same.hpp>
9 #include <boost/static_assert.hpp>
10 #include <boost/limits.hpp>
14 #define ALLOCATOR_METHODS(name) \
15 template <typename U> struct rebind { \
16 typedef name<U> other; \
20 template <typename Y> name(name<Y> const&) {} \
21 T* address(T& r) { return &r;} \
22 T const* address(T const& r) { return &r; } \
23 T* allocate(std::size_t n) \
24 { return static_cast<T*>(::operator new(n * sizeof(T))); } \
25 T* allocate(std::size_t n, void const*) \
26 { return static_cast<T*>(::operator new(n * sizeof(T))); } \
27 void deallocate(T* p, std::size_t) { ::operator delete((void*) p); } \
28 void construct(T* p, T const& t) { new(p) T(t); } \
29 void destroy(T* p) { p->~T(); } \
30 std::size_t max_size() const \
31 { return (std::numeric_limits<std::size_t>::max)(); } \
32 bool operator==(name<T> const&) { return true; } \
33 bool operator!=(name<T> const&) { return false; } \
36 #define ALLOCATOR_METHODS_TYPEDEFS(name) \
37 template <typename U> struct rebind { \
38 typedef name<U> other; \
42 template <typename Y> name(name<Y> const&) {} \
43 pointer address(T& r) { return &r;} \
44 const_pointer address(T const& r) { return &r; } \
45 pointer allocate(std::size_t n) \
46 { return pointer(::operator new(n * sizeof(T))); } \
47 pointer allocate(std::size_t n, void const*) \
48 { return pointer(::operator new(n * sizeof(T))); } \
49 void deallocate(pointer p, std::size_t) \
50 { ::operator delete((void*) p); } \
51 void construct(T* p, T const& t) { new(p) T(t); } \
52 void destroy(T* p) { p->~T(); } \
53 size_type max_size() const \
54 { return (std::numeric_limits<size_type>::max)(); } \
55 bool operator==(name<T> const&) { return true; } \
56 bool operator!=(name<T> const&) { return false; } \
59 struct yes_type
{ enum { value
= true }; };
60 struct no_type
{ enum { value
= false }; };
62 // For tracking calls...
69 template <typename Allocator
>
72 typedef boost::unordered::detail::allocator_traits
<Allocator
> traits
;
76 BOOST_TEST(traits::select_on_container_copy_construction(a
) == a
);
80 // Empty allocator test
83 struct empty_allocator
86 ALLOCATOR_METHODS(empty_allocator
)
89 void test_empty_allocator()
91 typedef empty_allocator
<int> allocator
;
92 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
93 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
94 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
,
95 std::make_unsigned
<std::ptrdiff_t>::type
>::value
));
97 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
, std::size_t>::value
));
99 BOOST_STATIC_ASSERT((boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
100 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, int*>::value
));
101 BOOST_STATIC_ASSERT((boost::is_same
<traits::const_pointer
, int const*>::value
));
102 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
103 BOOST_TEST(!traits::propagate_on_container_copy_assignment::value
);
104 BOOST_TEST(!traits::propagate_on_container_move_assignment::value
);
105 BOOST_TEST(!traits::propagate_on_container_swap::value
);
106 BOOST_TEST(call_select
<allocator
>() == 0);
111 template <typename T
>
114 typedef T value_type
;
115 ALLOCATOR_METHODS(allocator1
)
117 typedef yes_type propagate_on_container_copy_assignment
;
118 typedef yes_type propagate_on_container_move_assignment
;
119 typedef yes_type propagate_on_container_swap
;
121 allocator1
<T
> select_on_container_copy_construction() const {
123 return allocator1
<T
>();
127 void test_allocator1()
129 typedef allocator1
<int> allocator
;
130 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
131 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
132 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
,
133 std::make_unsigned
<std::ptrdiff_t>::type
>::value
));
135 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
, std::size_t>::value
));
137 BOOST_STATIC_ASSERT((boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
138 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, int*>::value
));
139 BOOST_STATIC_ASSERT((boost::is_same
<traits::const_pointer
, int const*>::value
));
140 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
141 BOOST_TEST(traits::propagate_on_container_copy_assignment::value
);
142 BOOST_TEST(traits::propagate_on_container_move_assignment::value
);
143 BOOST_TEST(traits::propagate_on_container_swap::value
);
144 BOOST_TEST(call_select
<allocator
>() == 1);
149 template <typename Alloc
>
150 struct allocator2_base
152 Alloc
select_on_container_copy_construction() const {
158 template <typename T
>
159 struct allocator2
: allocator2_base
<allocator2
<T
> >
161 typedef T value_type
;
163 typedef T
const* const_pointer
;
164 typedef std::size_t size_type
;
166 ALLOCATOR_METHODS(allocator2
)
168 typedef no_type propagate_on_container_copy_assignment
;
169 typedef no_type propagate_on_container_move_assignment
;
170 typedef no_type propagate_on_container_swap
;
173 void test_allocator2()
175 typedef allocator2
<int> allocator
;
176 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
177 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
, std::size_t>::value
));
178 BOOST_STATIC_ASSERT((boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
179 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, int*>::value
));
180 BOOST_STATIC_ASSERT((boost::is_same
<traits::const_pointer
, int const*>::value
));
181 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
182 BOOST_TEST(!traits::propagate_on_container_copy_assignment::value
);
183 BOOST_TEST(!traits::propagate_on_container_move_assignment::value
);
184 BOOST_TEST(!traits::propagate_on_container_swap::value
);
185 BOOST_TEST(call_select
<allocator
>() == 1);
190 template <typename T
>
195 ptr(void* v
) : value_((T
*) v
) {}
196 T
& operator*() const { return *value_
; }
203 ptr(void* v
) : value_(v
) {}
207 struct ptr
<const void>
210 ptr(void const* v
) : value_(v
) {}
213 template <typename T
>
216 typedef T value_type
;
217 typedef ptr
<T
> pointer
;
218 typedef ptr
<T
const> const_pointer
;
219 typedef unsigned short size_type
;
221 ALLOCATOR_METHODS_TYPEDEFS(allocator3
)
223 typedef yes_type propagate_on_container_copy_assignment
;
224 typedef no_type propagate_on_container_move_assignment
;
226 allocator3
<T
> select_on_container_copy_construction() const {
228 return allocator3
<T
>();
232 void test_allocator3()
234 typedef allocator3
<int> allocator
;
235 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
236 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
, unsigned short>::value
));
237 BOOST_STATIC_ASSERT((boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
238 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, ptr
<int> >::value
));
239 BOOST_STATIC_ASSERT((boost::is_same
<traits::const_pointer
, ptr
<int const> >::value
));
240 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
241 BOOST_TEST(traits::propagate_on_container_copy_assignment::value
);
242 BOOST_TEST(!traits::propagate_on_container_move_assignment::value
);
243 BOOST_TEST(!traits::propagate_on_container_swap::value
);
244 BOOST_TEST(call_select
<allocator
>() == 1);
249 test_empty_allocator();
253 return boost::report_errors();