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/detail/lightweight_test.hpp>
7 #include <boost/limits.hpp>
8 #include <boost/static_assert.hpp>
9 #include <boost/type_traits/is_same.hpp>
10 #include <boost/unordered/detail/implementation.hpp>
14 #define ALLOCATOR_METHODS(name) \
15 template <typename U> struct rebind \
17 typedef name<U> other; \
21 template <typename Y> name(name<Y> const&) {} \
22 T* address(T& r) { return &r; } \
23 T const* address(T const& r) { return &r; } \
24 T* allocate(std::size_t n) \
26 return static_cast<T*>(::operator new(n * sizeof(T))); \
28 T* allocate(std::size_t n, void const*) \
30 return static_cast<T*>(::operator new(n * sizeof(T))); \
32 void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } \
33 void construct(T* p, T const& t) { new (p) T(t); } \
34 void destroy(T* p) { p->~T(); } \
35 std::size_t max_size() const \
37 return (std::numeric_limits<std::size_t>::max)(); \
39 bool operator==(name<T> const&) { return true; } \
40 bool operator!=(name<T> const&) { return false; } \
43 #define ALLOCATOR_METHODS_TYPEDEFS(name) \
44 template <typename U> struct rebind \
46 typedef name<U> other; \
50 template <typename Y> name(name<Y> const&) {} \
51 pointer address(T& r) { return &r; } \
52 const_pointer address(T const& r) { return &r; } \
53 pointer allocate(std::size_t n) \
55 return pointer(::operator new(n * sizeof(T))); \
57 pointer allocate(std::size_t n, void const*) \
59 return pointer(::operator new(n * sizeof(T))); \
61 void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \
62 void construct(T* p, T const& t) { new (p) T(t); } \
63 void destroy(T* p) { p->~T(); } \
64 size_type max_size() const \
66 return (std::numeric_limits<size_type>::max)(); \
68 bool operator==(name<T> const&) { return true; } \
69 bool operator!=(name<T> const&) { return false; } \
87 // For tracking calls...
90 void reset() { selected
= 0; }
92 template <typename Allocator
> int call_select()
94 typedef boost::unordered::detail::allocator_traits
<Allocator
> traits
;
98 BOOST_TEST(traits::select_on_container_copy_construction(a
) == a
);
102 // Empty allocator test
104 template <typename T
> struct empty_allocator
106 typedef T value_type
;
107 ALLOCATOR_METHODS(empty_allocator
)
110 void test_empty_allocator()
112 typedef empty_allocator
<int> allocator
;
113 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
114 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
115 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
,
116 std::make_unsigned
<std::ptrdiff_t>::type
>::value
));
118 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
, std::size_t>::value
));
121 (boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
122 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, int*>::value
));
124 (boost::is_same
<traits::const_pointer
, int const*>::value
));
125 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
126 BOOST_TEST(!traits::propagate_on_container_copy_assignment::value
);
127 BOOST_TEST(!traits::propagate_on_container_move_assignment::value
);
128 BOOST_TEST(!traits::propagate_on_container_swap::value
);
129 BOOST_TEST(call_select
<allocator
>() == 0);
134 template <typename T
> struct allocator1
136 typedef T value_type
;
137 ALLOCATOR_METHODS(allocator1
)
139 typedef yes_type propagate_on_container_copy_assignment
;
140 typedef yes_type propagate_on_container_move_assignment
;
141 typedef yes_type propagate_on_container_swap
;
143 allocator1
<T
> select_on_container_copy_construction() const
146 return allocator1
<T
>();
150 void test_allocator1()
152 typedef allocator1
<int> allocator
;
153 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
154 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
155 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
,
156 std::make_unsigned
<std::ptrdiff_t>::type
>::value
));
158 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
, std::size_t>::value
));
161 (boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
162 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, int*>::value
));
164 (boost::is_same
<traits::const_pointer
, int const*>::value
));
165 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
166 BOOST_TEST(traits::propagate_on_container_copy_assignment::value
);
167 BOOST_TEST(traits::propagate_on_container_move_assignment::value
);
168 BOOST_TEST(traits::propagate_on_container_swap::value
);
169 BOOST_TEST(call_select
<allocator
>() == 1);
174 template <typename Alloc
> struct allocator2_base
176 Alloc
select_on_container_copy_construction() const
183 template <typename T
> struct allocator2
: allocator2_base
<allocator2
<T
> >
185 typedef T value_type
;
187 typedef T
const* const_pointer
;
188 typedef std::size_t size_type
;
190 ALLOCATOR_METHODS(allocator2
)
192 typedef no_type propagate_on_container_copy_assignment
;
193 typedef no_type propagate_on_container_move_assignment
;
194 typedef no_type propagate_on_container_swap
;
197 void test_allocator2()
199 typedef allocator2
<int> allocator
;
200 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
201 BOOST_STATIC_ASSERT((boost::is_same
<traits::size_type
, std::size_t>::value
));
203 (boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
204 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, int*>::value
));
206 (boost::is_same
<traits::const_pointer
, int const*>::value
));
207 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
208 BOOST_TEST(!traits::propagate_on_container_copy_assignment::value
);
209 BOOST_TEST(!traits::propagate_on_container_move_assignment::value
);
210 BOOST_TEST(!traits::propagate_on_container_swap::value
);
211 BOOST_TEST(call_select
<allocator
>() == 1);
216 template <typename T
> struct ptr
220 ptr(void* v
) : value_((T
*)v
) {}
221 T
& operator*() const { return *value_
; }
224 template <> struct ptr
<void>
227 ptr(void* v
) : value_(v
) {}
230 template <> struct ptr
<const void>
233 ptr(void const* v
) : value_(v
) {}
236 template <typename T
> struct allocator3
238 typedef T value_type
;
239 typedef ptr
<T
> pointer
;
240 typedef ptr
<T
const> const_pointer
;
241 typedef unsigned short size_type
;
243 ALLOCATOR_METHODS_TYPEDEFS(allocator3
)
245 typedef yes_type propagate_on_container_copy_assignment
;
246 typedef no_type propagate_on_container_move_assignment
;
248 allocator3
<T
> select_on_container_copy_construction() const
251 return allocator3
<T
>();
255 void test_allocator3()
257 typedef allocator3
<int> allocator
;
258 typedef boost::unordered::detail::allocator_traits
<allocator
> traits
;
260 (boost::is_same
<traits::size_type
, unsigned short>::value
));
262 (boost::is_same
<traits::difference_type
, std::ptrdiff_t>::value
));
263 BOOST_STATIC_ASSERT((boost::is_same
<traits::pointer
, ptr
<int> >::value
));
265 (boost::is_same
<traits::const_pointer
, ptr
<int const> >::value
));
266 BOOST_STATIC_ASSERT((boost::is_same
<traits::value_type
, int>::value
));
267 BOOST_TEST(traits::propagate_on_container_copy_assignment::value
);
268 BOOST_TEST(!traits::propagate_on_container_move_assignment::value
);
269 BOOST_TEST(!traits::propagate_on_container_swap::value
);
270 BOOST_TEST(call_select
<allocator
>() == 1);
275 test_empty_allocator();
279 return boost::report_errors();