1
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)
5
6#include <boost/core/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>
11
12// Boilerplate
13
14#define ALLOCATOR_METHODS(name) \
15 template <typename U> struct rebind \
16 { \
17 typedef name<U> other; \
18 }; \
19 \
20 name() {} \
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) \
25 { \
26 return static_cast<T*>(::operator new(n * sizeof(T))); \
27 } \
28 T* allocate(std::size_t n, void const*) \
29 { \
30 return static_cast<T*>(::operator new(n * sizeof(T))); \
31 } \
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 \
36 { \
37 return (std::numeric_limits<std::size_t>::max)(); \
38 } \
39 bool operator==(name<T> const&) const { return true; } \
40 bool operator!=(name<T> const&) const { return false; } \
41/**/
42
43#define ALLOCATOR_METHODS_TYPEDEFS(name) \
44 template <typename U> struct rebind \
45 { \
46 typedef name<U> other; \
47 }; \
48 \
49 name() {} \
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) \
54 { \
55 return pointer(::operator new(n * sizeof(T))); \
56 } \
57 pointer allocate(std::size_t n, void const*) \
58 { \
59 return pointer(::operator new(n * sizeof(T))); \
60 } \
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 \
65 { \
66 return (std::numeric_limits<size_type>::max)(); \
67 } \
68 bool operator==(name<T> const&) const { return true; } \
69 bool operator!=(name<T> const&) const { return false; } \
70 /**/
71
72struct yes_type
73{
74 enum
75 {
76 value = true
77 };
78};
79struct no_type
80{
81 enum
82 {
83 value = false
84 };
85};
86
87// For tracking calls...
88
89static int selected;
90void reset() { selected = 0; }
91
92template <typename Allocator> int call_select()
93{
94 typedef boost::unordered::detail::allocator_traits<Allocator> traits;
95 Allocator a;
96
97 reset();
98 BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
99 return selected;
100}
101
102// Empty allocator test
103
104template <typename T> struct empty_allocator
105{
106 typedef T value_type;
107 ALLOCATOR_METHODS(empty_allocator)
108};
109
110void test_empty_allocator()
111{
112 typedef empty_allocator<int> allocator;
113 typedef boost::unordered::detail::allocator_traits<allocator> traits;
114 BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
115 std::make_unsigned<std::ptrdiff_t>::type>::value));
116 BOOST_STATIC_ASSERT(
117 (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
118 BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
119 BOOST_STATIC_ASSERT(
120 (boost::is_same<traits::const_pointer, int const*>::value));
121 BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
122 BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
123 BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
124 BOOST_TEST(!traits::propagate_on_container_swap::value);
125 BOOST_TEST(traits::is_always_equal::value);
126 BOOST_TEST(call_select<allocator>() == 0);
127}
128
129// allocator 1
130
131template <typename T> struct allocator1
132{
133 typedef T value_type;
134 ALLOCATOR_METHODS(allocator1)
135
136 typedef yes_type propagate_on_container_copy_assignment;
137 typedef yes_type propagate_on_container_move_assignment;
138 typedef yes_type propagate_on_container_swap;
139 typedef yes_type is_always_equal;
140
141 allocator1<T> select_on_container_copy_construction() const
142 {
143 ++selected;
144 return allocator1<T>();
145 }
146};
147
148void test_allocator1()
149{
150 typedef allocator1<int> allocator;
151 typedef boost::unordered::detail::allocator_traits<allocator> traits;
152 BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
153 std::make_unsigned<std::ptrdiff_t>::type>::value));
154 BOOST_STATIC_ASSERT(
155 (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
156 BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
157 BOOST_STATIC_ASSERT(
158 (boost::is_same<traits::const_pointer, int const*>::value));
159 BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
160 BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
161 BOOST_TEST(traits::propagate_on_container_move_assignment::value);
162 BOOST_TEST(traits::propagate_on_container_swap::value);
163 BOOST_TEST(traits::is_always_equal::value);
164 BOOST_TEST(call_select<allocator>() == 1);
165}
166
167// allocator 2
168
169template <typename Alloc> struct allocator2_base
170{
171 Alloc select_on_container_copy_construction() const
172 {
173 ++selected;
174 return Alloc();
175 }
176};
177
178template <typename T> struct allocator2 : allocator2_base<allocator2<T> >
179{
180 typedef T value_type;
181 typedef T* pointer;
182 typedef T const* const_pointer;
183 typedef std::size_t size_type;
184
185 ALLOCATOR_METHODS(allocator2)
186
187 typedef no_type propagate_on_container_copy_assignment;
188 typedef no_type propagate_on_container_move_assignment;
189 typedef no_type propagate_on_container_swap;
190 typedef no_type is_always_equal;
191};
192
193void test_allocator2()
194{
195 typedef allocator2<int> allocator;
196 typedef boost::unordered::detail::allocator_traits<allocator> traits;
197 BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
198 BOOST_STATIC_ASSERT(
199 (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
200 BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
201 BOOST_STATIC_ASSERT(
202 (boost::is_same<traits::const_pointer, int const*>::value));
203 BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
204 BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
205 BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
206 BOOST_TEST(!traits::propagate_on_container_swap::value);
207 BOOST_TEST(!traits::is_always_equal::value);
208 BOOST_TEST(call_select<allocator>() == 1);
209}
210
211// allocator 3
212
213template <typename T> struct ptr
214{
215 T* value_;
216
217 ptr(void* v) : value_((T*)v) {}
218 T& operator*() const { return *value_; }
219};
220
221template <> struct ptr<void>
222{
223 void* value_;
224 ptr(void* v) : value_(v) {}
225};
226
227template <> struct ptr<const void>
228{
229 void const* value_;
230 ptr(void const* v) : value_(v) {}
231};
232
233template <typename T> struct allocator3
234{
235 typedef T value_type;
236 typedef ptr<T> pointer;
237 typedef ptr<T const> const_pointer;
238 typedef unsigned short size_type;
239
240 int x; // Just to make it non-empty, so that is_always_equal is false.
241
242 ALLOCATOR_METHODS_TYPEDEFS(allocator3)
243
244 typedef yes_type propagate_on_container_copy_assignment;
245 typedef no_type propagate_on_container_move_assignment;
246
247 allocator3<T> select_on_container_copy_construction() const
248 {
249 ++selected;
250 allocator3<T> a;
251 a.x = 0;
252 return a;
253 }
254};
255
256void test_allocator3()
257{
258 typedef allocator3<int> allocator;
259 typedef boost::unordered::detail::allocator_traits<allocator> traits;
260 BOOST_STATIC_ASSERT(
261 (boost::is_same<traits::size_type, unsigned short>::value));
262 BOOST_STATIC_ASSERT(
263 (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
264 BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
265 BOOST_STATIC_ASSERT(
266 (boost::is_same<traits::const_pointer, ptr<int const> >::value));
267 BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
268 BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
269 BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
270 BOOST_TEST(!traits::propagate_on_container_swap::value);
271 BOOST_TEST(!traits::is_always_equal::value);
272 BOOST_TEST(call_select<allocator>() == 1);
273}
274
275int main()
276{
277 test_empty_allocator();
278 test_allocator1();
279 test_allocator2();
280 test_allocator3();
281 return boost::report_errors();
282}
283

source code of boost/libs/unordered/test/unordered/allocator_traits.cpp