1
2// Copyright 2006-2009 Daniel James.
3// Copyright 2022 Christian Mazakas
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7// Define some minimal classes which provide the bare minimum concepts to
8// test that the containers don't rely on something that they shouldn't.
9// They are not intended to be good examples of how to implement the concepts.
10
11#if !defined(BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER)
12#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
13
14#include <boost/core/addressof.hpp>
15#include <boost/core/lightweight_test.hpp>
16#include <boost/core/pointer_traits.hpp>
17#include <cstddef>
18#include <utility>
19
20#if defined(BOOST_MSVC)
21#pragma warning(push)
22#pragma warning(disable : 4100) // unreferenced formal parameter
23#endif
24
25#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
26#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
27#else
28#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
29#endif
30
31namespace test {
32 namespace minimal {
33 class destructible;
34 class copy_constructible;
35 class copy_constructible_equality_comparable;
36 class default_assignable;
37 class assignable;
38
39 struct ampersand_operator_used
40 {
41 ampersand_operator_used() { BOOST_TEST(false); }
42 };
43
44 template <class T> class hash;
45 template <class T> class equal_to;
46 template <class T> class ptr;
47 template <class T> class const_ptr;
48 template <class T> class allocator;
49 template <class T> class cxx11_allocator;
50
51 struct constructor_param
52 {
53 operator int() const { return 0; }
54 };
55
56 class destructible
57 {
58 public:
59 destructible(constructor_param const&) {}
60 ~destructible() {}
61 void dummy_member() const {}
62
63 private:
64 destructible(destructible const&);
65 destructible& operator=(destructible const&);
66 };
67
68 class copy_constructible
69 {
70 public:
71 copy_constructible(constructor_param const&) {}
72 copy_constructible(copy_constructible const&) {}
73 ~copy_constructible() {}
74 void dummy_member() const {}
75
76 private:
77 copy_constructible& operator=(copy_constructible const&);
78 copy_constructible() {}
79 };
80
81 class copy_constructible_equality_comparable
82 {
83 public:
84 copy_constructible_equality_comparable(constructor_param const&) {}
85
86 copy_constructible_equality_comparable(
87 copy_constructible_equality_comparable const&)
88 {
89 }
90
91 ~copy_constructible_equality_comparable() {}
92
93 void dummy_member() const {}
94
95 private:
96 copy_constructible_equality_comparable& operator=(
97 copy_constructible_equality_comparable const&);
98 copy_constructible_equality_comparable() {}
99#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
100 ampersand_operator_used operator&() const
101 {
102 return ampersand_operator_used();
103 }
104#endif
105 };
106
107 bool operator==(copy_constructible_equality_comparable,
108 copy_constructible_equality_comparable)
109 {
110 return true;
111 }
112
113 bool operator!=(copy_constructible_equality_comparable,
114 copy_constructible_equality_comparable)
115 {
116 return false;
117 }
118
119 class default_assignable
120 {
121 public:
122 default_assignable(constructor_param const&) {}
123
124 default_assignable() {}
125
126 default_assignable(default_assignable const&) {}
127
128 default_assignable& operator=(default_assignable const&) { return *this; }
129
130 ~default_assignable() {}
131
132 void dummy_member() const {}
133
134#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
135 ampersand_operator_used operator&() const
136 {
137 return ampersand_operator_used();
138 }
139#endif
140 };
141
142 class assignable
143 {
144 public:
145 assignable(constructor_param const&) {}
146 assignable(assignable const&) {}
147 assignable& operator=(assignable const&) { return *this; }
148 ~assignable() {}
149 void dummy_member() const {}
150
151 private:
152 assignable() {}
153#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
154 ampersand_operator_used operator&() const
155 {
156 return ampersand_operator_used();
157 }
158#endif
159 };
160
161 struct movable_init
162 {
163 };
164
165 class movable1
166 {
167 public:
168 movable1(constructor_param const&) {}
169 movable1() {}
170 explicit movable1(movable_init) {}
171 movable1(movable1 const&) = delete;
172 movable1& operator=(movable1 const&) = delete;
173 movable1(movable1&&) {}
174 movable1& operator=(movable1&&) { return *this; }
175 ~movable1() {}
176 void dummy_member() const {}
177 };
178
179 class movable2
180 {
181 public:
182 movable2(constructor_param const&) {}
183 explicit movable2(movable_init) {}
184 movable2(movable2&&) {}
185 ~movable2() {}
186 movable2& operator=(movable2&&) { return *this; }
187 void dummy_member() const {}
188
189 private:
190 movable2() {}
191 movable2(movable2 const&);
192 movable2& operator=(movable2 const&);
193 };
194
195 template <class T> class hash
196 {
197 public:
198 hash(constructor_param const&) {}
199 hash() {}
200 hash(hash const&) {}
201 hash& operator=(hash const&) { return *this; }
202 ~hash() {}
203
204#if defined(BOOST_UNORDERED_FOA_TESTS)
205 hash(hash&&) = default;
206 hash& operator=(hash&&) = default;
207#endif
208
209 std::size_t operator()(T const&) const { return 0; }
210#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
211 ampersand_operator_used operator&() const
212 {
213 return ampersand_operator_used();
214 }
215#endif
216 };
217
218 template <class T> class equal_to
219 {
220 public:
221 equal_to(constructor_param const&) {}
222 equal_to() {}
223 equal_to(equal_to const&) {}
224 equal_to& operator=(equal_to const&) { return *this; }
225 ~equal_to() {}
226
227#if defined(BOOST_UNORDERED_FOA_TESTS)
228 equal_to(equal_to&&) = default;
229 equal_to& operator=(equal_to&&) = default;
230#endif
231
232 bool operator()(T const&, T const&) const { return true; }
233#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
234 ampersand_operator_used operator&() const
235 {
236 return ampersand_operator_used();
237 }
238#endif
239 };
240
241 template <class T> class ptr;
242 template <class T> class const_ptr;
243
244 struct void_ptr
245 {
246#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
247 template <typename T> friend class ptr;
248
249 private:
250#endif
251
252 void* ptr_;
253
254 public:
255 void_ptr() : ptr_(0) {}
256
257 template <typename T> explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
258
259 // I'm not using the safe bool idiom because the containers should be
260 // able to cope with bool conversions.
261 operator bool() const { return !!ptr_; }
262
263 bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
264 bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
265 };
266
267 class void_const_ptr
268 {
269#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
270 template <typename T> friend class const_ptr;
271
272 private:
273#endif
274
275 void* ptr_;
276
277 public:
278 void_const_ptr() : ptr_(0) {}
279
280 template <typename T>
281 explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_)
282 {
283 }
284
285 // I'm not using the safe bool idiom because the containers should be
286 // able to cope with bool conversions.
287 operator bool() const { return !!ptr_; }
288
289 bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
290 bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
291 };
292
293 template <class T> class ptr
294 {
295 friend class allocator<T>;
296 friend class const_ptr<T>;
297 friend struct void_ptr;
298
299 T* ptr_;
300
301 ptr(T* x) : ptr_(x) {}
302
303 public:
304 ptr() : ptr_(0) {}
305 ptr(std::nullptr_t) : ptr_(0) {}
306 explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {}
307
308 T& operator*() const { return *ptr_; }
309 T* operator->() const { return ptr_; }
310 ptr& operator++()
311 {
312 ++ptr_;
313 return *this;
314 }
315 ptr operator++(int)
316 {
317 ptr tmp(*this);
318 ++ptr_;
319 return tmp;
320 }
321 ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
322 friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); }
323
324 ptr& operator+=(std::ptrdiff_t s)
325 {
326 ptr_ += s;
327 return *this;
328 }
329
330 ptr& operator-=(std::ptrdiff_t s)
331 {
332 ptr_ -= s;
333 return *this;
334 }
335
336 std::ptrdiff_t operator-(ptr p) const { return ptr_ - p.ptr_; }
337 ptr operator-(std::ptrdiff_t s) const { return ptr(ptr_ - s); }
338 T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
339 bool operator!() const { return !ptr_; }
340
341 static ptr pointer_to(T& p) {
342 return ptr(std::addressof(p));
343 }
344
345 // I'm not using the safe bool idiom because the containers should be
346 // able to cope with bool conversions.
347 operator bool() const { return !!ptr_; }
348
349 bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
350 bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
351 bool operator==(std::nullptr_t) const { return ptr_ == nullptr; }
352 bool operator!=(std::nullptr_t) const { return ptr_ != nullptr; }
353 bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
354 bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
355 bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
356 bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
357#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
358 ampersand_operator_used operator&() const
359 {
360 return ampersand_operator_used();
361 }
362#endif
363 };
364
365 template <class T> class const_ptr
366 {
367 friend class allocator<T>;
368 friend struct const_void_ptr;
369
370 T const* ptr_;
371
372 const_ptr(T const* ptr) : ptr_(ptr) {}
373
374 public:
375 const_ptr() : ptr_(0) {}
376 const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
377 explicit const_ptr(void_const_ptr const& x) : ptr_((T const*)x.ptr_) {}
378
379 T const& operator*() const { return *ptr_; }
380 T const* operator->() const { return ptr_; }
381 const_ptr& operator++()
382 {
383 ++ptr_;
384 return *this;
385 }
386 const_ptr operator++(int)
387 {
388 const_ptr tmp(*this);
389 ++ptr_;
390 return tmp;
391 }
392 const_ptr operator+(std::ptrdiff_t s) const
393 {
394 return const_ptr(ptr_ + s);
395 }
396 friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
397 {
398 return ptr<T>(s + p.ptr_);
399 }
400 T const& operator[](int s) const { return ptr_[s]; }
401 bool operator!() const { return !ptr_; }
402 operator bool() const { return !!ptr_; }
403
404 bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
405 bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
406 bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
407 bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
408 bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
409 bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
410#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
411 ampersand_operator_used operator&() const
412 {
413 return ampersand_operator_used();
414 }
415#endif
416 };
417
418 template <class T> class allocator
419 {
420 public:
421 typedef std::size_t size_type;
422 typedef std::ptrdiff_t difference_type;
423 typedef void_ptr void_pointer;
424 typedef void_const_ptr const_void_pointer;
425 typedef ptr<T> pointer;
426 typedef const_ptr<T> const_pointer;
427 typedef T& reference;
428 typedef T const& const_reference;
429 typedef T value_type;
430
431 template <class U> struct rebind
432 {
433 typedef allocator<U> other;
434 };
435
436 allocator() {}
437 template <class Y> allocator(allocator<Y> const&) {}
438 allocator(allocator const&) {}
439 ~allocator() {}
440
441 pointer address(reference r) { return pointer(&r); }
442 const_pointer address(const_reference r) { return const_pointer(&r); }
443
444 pointer allocate(size_type n)
445 {
446 return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
447 }
448
449 template <class Y> pointer allocate(size_type n, const_ptr<Y>)
450 {
451 return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
452 }
453
454 void deallocate(pointer p, size_type)
455 {
456 ::operator delete((void*)p.ptr_);
457 }
458
459 template <class U, class... Args>
460 void construct(U* p, Args&&... args)
461 {
462 new ((void*)p) U(std::forward<Args>(args)...);
463 }
464
465 template <class U> void destroy(U* p) { p->~U(); }
466
467 size_type max_size() const { return 1000; }
468
469#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
470 BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
471 public:
472 allocator& operator=(allocator const&) { return *this; }
473#else
474 private:
475 allocator& operator=(allocator const&);
476#endif
477#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
478 ampersand_operator_used operator&() const
479 {
480 return ampersand_operator_used();
481 }
482#endif
483 };
484
485 template <class T> class allocator<T const>
486 {
487 public:
488 typedef std::size_t size_type;
489 typedef std::ptrdiff_t difference_type;
490 typedef void_ptr void_pointer;
491 typedef void_const_ptr const_void_pointer;
492 // Maybe these two should be const_ptr<T>
493 typedef ptr<T const> pointer;
494 typedef const_ptr<T const> const_pointer;
495 typedef T const& reference;
496 typedef T const& const_reference;
497 typedef T const value_type;
498
499 template <class U> struct rebind
500 {
501 typedef allocator<U> other;
502 };
503
504 allocator() {}
505 template <class Y> allocator(allocator<Y> const&) {}
506 allocator(allocator const&) {}
507 ~allocator() {}
508
509 const_pointer address(const_reference r) { return const_pointer(&r); }
510
511 pointer allocate(size_type n)
512 {
513 return pointer(static_cast<T const*>(::operator new(n * sizeof(T))));
514 }
515
516 template <class Y> pointer allocate(size_type n, const_ptr<Y>)
517 {
518 return pointer(static_cast<T const*>(::operator new(n * sizeof(T))));
519 }
520
521 void deallocate(pointer p, size_type)
522 {
523 ::operator delete((void*)p.ptr_);
524 }
525
526 template <class U, class... Args>
527 void construct(U* p, Args&&... args)
528 {
529 new (p) U(std::forward<Args>(args)...);
530 }
531
532 template <class U> void destroy(U* p) { p->~U(); }
533
534 size_type max_size() const { return 1000; }
535
536#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
537 BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
538 public:
539 allocator& operator=(allocator const&) { return *this; }
540#else
541 private:
542 allocator& operator=(allocator const&);
543#endif
544#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
545 ampersand_operator_used operator&() const
546 {
547 return ampersand_operator_used();
548 }
549#endif
550 };
551
552 template <class T>
553 inline bool operator==(allocator<T> const&, allocator<T> const&)
554 {
555 return true;
556 }
557
558 template <class T>
559 inline bool operator!=(allocator<T> const&, allocator<T> const&)
560 {
561 return false;
562 }
563
564 template <class T> void swap(allocator<T>&, allocator<T>&) {}
565
566 // C++11 allocator
567 //
568 // Not a fully minimal C++11 allocator, just what I support. Hopefully will
569 // cut down further in the future.
570
571 template <class T> class cxx11_allocator
572 {
573 public:
574 typedef T value_type;
575 // template <class U> struct rebind { typedef cxx11_allocator<U> other; };
576
577 cxx11_allocator() {}
578 template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
579 cxx11_allocator(cxx11_allocator const&) {}
580 ~cxx11_allocator() {}
581
582 T* address(T& r) { return &r; }
583 T const* address(T const& r) { return &r; }
584
585 T* allocate(std::size_t n)
586 {
587 return static_cast<T*>(::operator new(n * sizeof(T)));
588 }
589
590 template <class Y> T* allocate(std::size_t n, const_ptr<Y>)
591 {
592 return static_cast<T*>(::operator new(n * sizeof(T)));
593 }
594
595 void deallocate(T* p, std::size_t) { ::operator delete((void*)p); }
596
597 template <class U, class... Args>
598 void construct(U* p, Args&&... args)
599 {
600 new ((void*)p) U(std::forward<Args>(args)...);
601 }
602
603 template <class U> void destroy(U* p) { p->~U(); }
604
605 std::size_t max_size() const { return 1000u; }
606 };
607
608 template <class T>
609 inline bool operator==(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
610 {
611 return true;
612 }
613
614 template <class T>
615 inline bool operator!=(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
616 {
617 return false;
618 }
619
620 template <class T> void swap(cxx11_allocator<T>&, cxx11_allocator<T>&) {}
621 }
622}
623
624#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
625namespace boost {
626#else
627namespace test {
628 namespace minimal {
629#endif
630 std::size_t hash_value(test::minimal::copy_constructible_equality_comparable)
631 {
632 return 1;
633 }
634#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
635}
636}
637#else
638 }
639#endif
640
641#if defined(BOOST_MSVC)
642#pragma warning(pop)
643#endif
644
645namespace boost {
646 template <> struct pointer_traits< ::test::minimal::void_ptr>
647 {
648 template <class U> struct rebind_to
649 {
650 typedef ::test::minimal::ptr<U> type;
651 };
652
653 template<class U>
654 using rebind=typename rebind_to<U>::type;
655 };
656}
657
658#endif
659

source code of boost/libs/unordered/test/objects/minimal.hpp