• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&) { return true; }                             \
69   bool operator!=(name<T> const&) { return false; }                            \
70 /**/
71 
72 struct yes_type
73 {
74   enum
75   {
76     value = true
77   };
78 };
79 struct no_type
80 {
81   enum
82   {
83     value = false
84   };
85 };
86 
87 // For tracking calls...
88 
89 static int selected;
reset()90 void reset() { selected = 0; }
91 
call_select()92 template <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 
104 template <typename T> struct empty_allocator
105 {
106   typedef T value_type;
107   ALLOCATOR_METHODS(empty_allocator)
108 };
109 
test_empty_allocator()110 void test_empty_allocator()
111 {
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));
117 #else
118   BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
119 #endif
120   BOOST_STATIC_ASSERT(
121     (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
122   BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
123   BOOST_STATIC_ASSERT(
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(traits::is_always_equal::value);
130   BOOST_TEST(call_select<allocator>() == 0);
131 }
132 
133 // allocator 1
134 
135 template <typename T> struct allocator1
136 {
137   typedef T value_type;
138   ALLOCATOR_METHODS(allocator1)
139 
140   typedef yes_type propagate_on_container_copy_assignment;
141   typedef yes_type propagate_on_container_move_assignment;
142   typedef yes_type propagate_on_container_swap;
143   typedef yes_type is_always_equal;
144 
select_on_container_copy_constructionallocator1145   allocator1<T> select_on_container_copy_construction() const
146   {
147     ++selected;
148     return allocator1<T>();
149   }
150 };
151 
test_allocator1()152 void test_allocator1()
153 {
154   typedef allocator1<int> allocator;
155   typedef boost::unordered::detail::allocator_traits<allocator> traits;
156 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
157   BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
158     std::make_unsigned<std::ptrdiff_t>::type>::value));
159 #else
160   BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
161 #endif
162   BOOST_STATIC_ASSERT(
163     (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
164   BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
165   BOOST_STATIC_ASSERT(
166     (boost::is_same<traits::const_pointer, int const*>::value));
167   BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
168   BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
169   BOOST_TEST(traits::propagate_on_container_move_assignment::value);
170   BOOST_TEST(traits::propagate_on_container_swap::value);
171   BOOST_TEST(traits::is_always_equal::value);
172   BOOST_TEST(call_select<allocator>() == 1);
173 }
174 
175 // allocator 2
176 
177 template <typename Alloc> struct allocator2_base
178 {
select_on_container_copy_constructionallocator2_base179   Alloc select_on_container_copy_construction() const
180   {
181     ++selected;
182     return Alloc();
183   }
184 };
185 
186 template <typename T> struct allocator2 : allocator2_base<allocator2<T> >
187 {
188   typedef T value_type;
189   typedef T* pointer;
190   typedef T const* const_pointer;
191   typedef std::size_t size_type;
192 
193   ALLOCATOR_METHODS(allocator2)
194 
195   typedef no_type propagate_on_container_copy_assignment;
196   typedef no_type propagate_on_container_move_assignment;
197   typedef no_type propagate_on_container_swap;
198   typedef no_type is_always_equal;
199 };
200 
test_allocator2()201 void test_allocator2()
202 {
203   typedef allocator2<int> allocator;
204   typedef boost::unordered::detail::allocator_traits<allocator> traits;
205   BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
206   BOOST_STATIC_ASSERT(
207     (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
208   BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
209   BOOST_STATIC_ASSERT(
210     (boost::is_same<traits::const_pointer, int const*>::value));
211   BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
212   BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
213   BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
214   BOOST_TEST(!traits::propagate_on_container_swap::value);
215   BOOST_TEST(!traits::is_always_equal::value);
216   BOOST_TEST(call_select<allocator>() == 1);
217 }
218 
219 // allocator 3
220 
221 template <typename T> struct ptr
222 {
223   T* value_;
224 
ptrptr225   ptr(void* v) : value_((T*)v) {}
operator *ptr226   T& operator*() const { return *value_; }
227 };
228 
229 template <> struct ptr<void>
230 {
231   void* value_;
ptrptr232   ptr(void* v) : value_(v) {}
233 };
234 
235 template <> struct ptr<const void>
236 {
237   void const* value_;
ptrptr238   ptr(void const* v) : value_(v) {}
239 };
240 
241 template <typename T> struct allocator3
242 {
243   typedef T value_type;
244   typedef ptr<T> pointer;
245   typedef ptr<T const> const_pointer;
246   typedef unsigned short size_type;
247 
248   int x; // Just to make it non-empty, so that is_always_equal is false.
249 
250   ALLOCATOR_METHODS_TYPEDEFS(allocator3)
251 
252   typedef yes_type propagate_on_container_copy_assignment;
253   typedef no_type propagate_on_container_move_assignment;
254 
select_on_container_copy_constructionallocator3255   allocator3<T> select_on_container_copy_construction() const
256   {
257     ++selected;
258     return allocator3<T>();
259   }
260 };
261 
test_allocator3()262 void test_allocator3()
263 {
264   typedef allocator3<int> allocator;
265   typedef boost::unordered::detail::allocator_traits<allocator> traits;
266   BOOST_STATIC_ASSERT(
267     (boost::is_same<traits::size_type, unsigned short>::value));
268   BOOST_STATIC_ASSERT(
269     (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
270   BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
271   BOOST_STATIC_ASSERT(
272     (boost::is_same<traits::const_pointer, ptr<int const> >::value));
273   BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
274   BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
275   BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
276   BOOST_TEST(!traits::propagate_on_container_swap::value);
277   BOOST_TEST(!traits::is_always_equal::value);
278   BOOST_TEST(call_select<allocator>() == 1);
279 }
280 
main()281 int main()
282 {
283   test_empty_allocator();
284   test_allocator1();
285   test_allocator2();
286   test_allocator3();
287   return boost::report_errors();
288 }
289