1 2 // Copyright 2006-2009 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 // Define some minimal classes which provide the bare minimum concepts to 7 // test that the containers don't rely on something that they shouldn't. 8 // They are not intended to be good examples of how to implement the concepts. 9 10 #if !defined(BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER) 11 #define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER 12 13 #include <boost/move/move.hpp> 14 #include <cstddef> 15 #include <utility> 16 17 #if defined(BOOST_MSVC) 18 #pragma warning(push) 19 #pragma warning(disable : 4100) // unreferenced formal parameter 20 #endif 21 22 #if !BOOST_WORKAROUND(BOOST_MSVC, == 1500) 23 #define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1 24 #else 25 #define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0 26 #endif 27 28 namespace test { 29 namespace minimal { 30 class destructible; 31 class copy_constructible; 32 class copy_constructible_equality_comparable; 33 class default_assignable; 34 class assignable; 35 36 struct ampersand_operator_used 37 { ampersand_operator_usedtest::minimal::ampersand_operator_used38 ampersand_operator_used() { BOOST_TEST(false); } 39 }; 40 41 template <class T> class hash; 42 template <class T> class equal_to; 43 template <class T> class ptr; 44 template <class T> class const_ptr; 45 template <class T> class allocator; 46 template <class T> class cxx11_allocator; 47 48 struct constructor_param 49 { operator inttest::minimal::constructor_param50 operator int() const { return 0; } 51 }; 52 53 class destructible 54 { 55 public: destructible(constructor_param const &)56 destructible(constructor_param const&) {} ~destructible()57 ~destructible() {} dummy_member() const58 void dummy_member() const {} 59 60 private: 61 destructible(destructible const&); 62 destructible& operator=(destructible const&); 63 }; 64 65 class copy_constructible 66 { 67 public: copy_constructible(constructor_param const &)68 copy_constructible(constructor_param const&) {} copy_constructible(copy_constructible const &)69 copy_constructible(copy_constructible const&) {} ~copy_constructible()70 ~copy_constructible() {} dummy_member() const71 void dummy_member() const {} 72 73 private: 74 copy_constructible& operator=(copy_constructible const&); copy_constructible()75 copy_constructible() {} 76 }; 77 78 class copy_constructible_equality_comparable 79 { 80 public: copy_constructible_equality_comparable(constructor_param const &)81 copy_constructible_equality_comparable(constructor_param const&) {} 82 copy_constructible_equality_comparable(copy_constructible_equality_comparable const &)83 copy_constructible_equality_comparable( 84 copy_constructible_equality_comparable const&) 85 { 86 } 87 ~copy_constructible_equality_comparable()88 ~copy_constructible_equality_comparable() {} 89 dummy_member() const90 void dummy_member() const {} 91 92 private: 93 copy_constructible_equality_comparable& operator=( 94 copy_constructible_equality_comparable const&); copy_constructible_equality_comparable()95 copy_constructible_equality_comparable() {} 96 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const97 ampersand_operator_used operator&() const 98 { 99 return ampersand_operator_used(); 100 } 101 #endif 102 }; 103 operator ==(copy_constructible_equality_comparable,copy_constructible_equality_comparable)104 bool operator==(copy_constructible_equality_comparable, 105 copy_constructible_equality_comparable) 106 { 107 return true; 108 } 109 operator !=(copy_constructible_equality_comparable,copy_constructible_equality_comparable)110 bool operator!=(copy_constructible_equality_comparable, 111 copy_constructible_equality_comparable) 112 { 113 return false; 114 } 115 116 class default_assignable 117 { 118 public: default_assignable(constructor_param const &)119 default_assignable(constructor_param const&) {} 120 default_assignable()121 default_assignable() {} 122 default_assignable(default_assignable const &)123 default_assignable(default_assignable const&) {} 124 operator =(default_assignable const &)125 default_assignable& operator=(default_assignable const&) { return *this; } 126 ~default_assignable()127 ~default_assignable() {} 128 dummy_member() const129 void dummy_member() const {} 130 131 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const132 ampersand_operator_used operator&() const 133 { 134 return ampersand_operator_used(); 135 } 136 #endif 137 }; 138 139 class assignable 140 { 141 public: assignable(constructor_param const &)142 assignable(constructor_param const&) {} assignable(assignable const &)143 assignable(assignable const&) {} operator =(assignable const &)144 assignable& operator=(assignable const&) { return *this; } ~assignable()145 ~assignable() {} dummy_member() const146 void dummy_member() const {} 147 148 private: assignable()149 assignable() {} 150 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const151 ampersand_operator_used operator&() const 152 { 153 return ampersand_operator_used(); 154 } 155 #endif 156 }; 157 158 struct movable_init 159 { 160 }; 161 162 class movable1 163 { 164 BOOST_MOVABLE_BUT_NOT_COPYABLE(movable1) 165 166 public: movable1(constructor_param const &)167 movable1(constructor_param const&) {} movable1()168 movable1() {} movable1(movable_init)169 explicit movable1(movable_init) {} movable1(BOOST_RV_REF (movable1))170 movable1(BOOST_RV_REF(movable1)) {} operator =(BOOST_RV_REF (movable1))171 movable1& operator=(BOOST_RV_REF(movable1)) { return *this; } ~movable1()172 ~movable1() {} dummy_member() const173 void dummy_member() const {} 174 }; 175 176 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 177 class movable2 178 { 179 public: movable2(constructor_param const &)180 movable2(constructor_param const&) {} movable2(movable_init)181 explicit movable2(movable_init) {} movable2(movable2 &&)182 movable2(movable2&&) {} ~movable2()183 ~movable2() {} operator =(movable2 &&)184 movable2& operator=(movable2&&) { return *this; } dummy_member() const185 void dummy_member() const {} 186 187 private: movable2()188 movable2() {} 189 movable2(movable2 const&); 190 movable2& operator=(movable2 const&); 191 }; 192 #else 193 typedef movable1 movable2; 194 #endif 195 196 template <class T> class hash 197 { 198 public: hash(constructor_param const &)199 hash(constructor_param const&) {} hash()200 hash() {} hash(hash const &)201 hash(hash const&) {} operator =(hash const &)202 hash& operator=(hash const&) { return *this; } ~hash()203 ~hash() {} 204 operator ()(T const &) const205 std::size_t operator()(T const&) const { return 0; } 206 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const207 ampersand_operator_used operator&() const 208 { 209 return ampersand_operator_used(); 210 } 211 #endif 212 }; 213 214 template <class T> class equal_to 215 { 216 public: equal_to(constructor_param const &)217 equal_to(constructor_param const&) {} equal_to()218 equal_to() {} equal_to(equal_to const &)219 equal_to(equal_to const&) {} operator =(equal_to const &)220 equal_to& operator=(equal_to const&) { return *this; } ~equal_to()221 ~equal_to() {} 222 operator ()(T const &,T const &) const223 bool operator()(T const&, T const&) const { return true; } 224 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const225 ampersand_operator_used operator&() const 226 { 227 return ampersand_operator_used(); 228 } 229 #endif 230 }; 231 232 template <class T> class ptr; 233 template <class T> class const_ptr; 234 235 struct void_ptr 236 { 237 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) 238 template <typename T> friend class ptr; 239 240 private: 241 #endif 242 243 void* ptr_; 244 245 public: void_ptrtest::minimal::void_ptr246 void_ptr() : ptr_(0) {} 247 void_ptrtest::minimal::void_ptr248 template <typename T> explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {} 249 250 // I'm not using the safe bool idiom because the containers should be 251 // able to cope with bool conversions. operator booltest::minimal::void_ptr252 operator bool() const { return !!ptr_; } 253 operator ==test::minimal::void_ptr254 bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; } operator !=test::minimal::void_ptr255 bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; } 256 }; 257 258 class void_const_ptr 259 { 260 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) 261 template <typename T> friend class const_ptr; 262 263 private: 264 #endif 265 266 void* ptr_; 267 268 public: void_const_ptr()269 void_const_ptr() : ptr_(0) {} 270 271 template <typename T> void_const_ptr(const_ptr<T> const & x)272 explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_) 273 { 274 } 275 276 // I'm not using the safe bool idiom because the containers should be 277 // able to cope with bool conversions. operator bool() const278 operator bool() const { return !!ptr_; } 279 operator ==(void_const_ptr const & x) const280 bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; } operator !=(void_const_ptr const & x) const281 bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; } 282 }; 283 284 template <class T> class ptr 285 { 286 friend class allocator<T>; 287 friend class const_ptr<T>; 288 friend struct void_ptr; 289 290 T* ptr_; 291 ptr(T * x)292 ptr(T* x) : ptr_(x) {} 293 294 public: ptr()295 ptr() : ptr_(0) {} ptr(void_ptr const & x)296 explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {} 297 operator *() const298 T& operator*() const { return *ptr_; } operator ->() const299 T* operator->() const { return ptr_; } operator ++()300 ptr& operator++() 301 { 302 ++ptr_; 303 return *this; 304 } operator ++(int)305 ptr operator++(int) 306 { 307 ptr tmp(*this); 308 ++ptr_; 309 return tmp; 310 } operator +(std::ptrdiff_t s) const311 ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); } operator +(std::ptrdiff_t s,ptr p)312 friend ptr operator+(std::ptrdiff_t s, ptr p) 313 { 314 return ptr<T>(s + p.ptr_); 315 } operator [](std::ptrdiff_t s) const316 T& operator[](std::ptrdiff_t s) const { return ptr_[s]; } operator !() const317 bool operator!() const { return !ptr_; } 318 319 // I'm not using the safe bool idiom because the containers should be 320 // able to cope with bool conversions. operator bool() const321 operator bool() const { return !!ptr_; } 322 operator ==(ptr const & x) const323 bool operator==(ptr const& x) const { return ptr_ == x.ptr_; } operator !=(ptr const & x) const324 bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; } operator <(ptr const & x) const325 bool operator<(ptr const& x) const { return ptr_ < x.ptr_; } operator >(ptr const & x) const326 bool operator>(ptr const& x) const { return ptr_ > x.ptr_; } operator <=(ptr const & x) const327 bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } operator >=(ptr const & x) const328 bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } 329 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const330 ampersand_operator_used operator&() const 331 { 332 return ampersand_operator_used(); 333 } 334 #endif 335 }; 336 337 template <class T> class const_ptr 338 { 339 friend class allocator<T>; 340 friend struct const_void_ptr; 341 342 T const* ptr_; 343 const_ptr(T const * ptr)344 const_ptr(T const* ptr) : ptr_(ptr) {} 345 346 public: const_ptr()347 const_ptr() : ptr_(0) {} const_ptr(ptr<T> const & x)348 const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {} const_ptr(void_const_ptr const & x)349 explicit const_ptr(void_const_ptr const& x) : ptr_((T const*)x.ptr_) {} 350 operator *() const351 T const& operator*() const { return *ptr_; } operator ->() const352 T const* operator->() const { return ptr_; } operator ++()353 const_ptr& operator++() 354 { 355 ++ptr_; 356 return *this; 357 } operator ++(int)358 const_ptr operator++(int) 359 { 360 const_ptr tmp(*this); 361 ++ptr_; 362 return tmp; 363 } operator +(std::ptrdiff_t s) const364 const_ptr operator+(std::ptrdiff_t s) const 365 { 366 return const_ptr(ptr_ + s); 367 } operator +(std::ptrdiff_t s,const_ptr p)368 friend const_ptr operator+(std::ptrdiff_t s, const_ptr p) 369 { 370 return ptr<T>(s + p.ptr_); 371 } operator [](int s) const372 T const& operator[](int s) const { return ptr_[s]; } operator !() const373 bool operator!() const { return !ptr_; } operator bool() const374 operator bool() const { return !!ptr_; } 375 operator ==(const_ptr const & x) const376 bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; } operator !=(const_ptr const & x) const377 bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; } operator <(const_ptr const & x) const378 bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; } operator >(const_ptr const & x) const379 bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; } operator <=(const_ptr const & x) const380 bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; } operator >=(const_ptr const & x) const381 bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; } 382 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const383 ampersand_operator_used operator&() const 384 { 385 return ampersand_operator_used(); 386 } 387 #endif 388 }; 389 390 template <class T> class allocator 391 { 392 public: 393 typedef std::size_t size_type; 394 typedef std::ptrdiff_t difference_type; 395 typedef void_ptr void_pointer; 396 typedef void_const_ptr const_void_pointer; 397 typedef ptr<T> pointer; 398 typedef const_ptr<T> const_pointer; 399 typedef T& reference; 400 typedef T const& const_reference; 401 typedef T value_type; 402 403 template <class U> struct rebind 404 { 405 typedef allocator<U> other; 406 }; 407 allocator()408 allocator() {} allocator(allocator<Y> const &)409 template <class Y> allocator(allocator<Y> const&) {} allocator(allocator const &)410 allocator(allocator const&) {} ~allocator()411 ~allocator() {} 412 address(reference r)413 pointer address(reference r) { return pointer(&r); } address(const_reference r)414 const_pointer address(const_reference r) { return const_pointer(&r); } 415 allocate(size_type n)416 pointer allocate(size_type n) 417 { 418 return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); 419 } 420 allocate(size_type n,const_ptr<Y>)421 template <class Y> pointer allocate(size_type n, const_ptr<Y>) 422 { 423 return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); 424 } 425 deallocate(pointer p,size_type)426 void deallocate(pointer p, size_type) 427 { 428 ::operator delete((void*)p.ptr_); 429 } 430 construct(T * p,T const & t)431 void construct(T* p, T const& t) { new ((void*)p) T(t); } 432 433 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) construct(T * p,BOOST_FWD_REF (Args)...args)434 template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) 435 { 436 new ((void*)p) T(boost::forward<Args>(args)...); 437 } 438 #endif 439 destroy(T * p)440 void destroy(T* p) { p->~T(); } 441 max_size() const442 size_type max_size() const { return 1000; } 443 444 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \ 445 BOOST_WORKAROUND(BOOST_MSVC, <= 1300) 446 public: operator =(allocator const &)447 allocator& operator=(allocator const&) { return *this; } 448 #else 449 private: 450 allocator& operator=(allocator const&); 451 #endif 452 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const453 ampersand_operator_used operator&() const 454 { 455 return ampersand_operator_used(); 456 } 457 #endif 458 }; 459 460 template <class T> class allocator<T const> 461 { 462 public: 463 typedef std::size_t size_type; 464 typedef std::ptrdiff_t difference_type; 465 typedef void_ptr void_pointer; 466 typedef void_const_ptr const_void_pointer; 467 // Maybe these two should be const_ptr<T> 468 typedef ptr<T const> pointer; 469 typedef const_ptr<T const> const_pointer; 470 typedef T const& reference; 471 typedef T const& const_reference; 472 typedef T const value_type; 473 474 template <class U> struct rebind 475 { 476 typedef allocator<U> other; 477 }; 478 allocator()479 allocator() {} allocator(allocator<Y> const &)480 template <class Y> allocator(allocator<Y> const&) {} allocator(allocator const &)481 allocator(allocator const&) {} ~allocator()482 ~allocator() {} 483 address(const_reference r)484 const_pointer address(const_reference r) { return const_pointer(&r); } 485 allocate(size_type n)486 pointer allocate(size_type n) 487 { 488 return pointer(static_cast<T const*>(::operator new(n * sizeof(T)))); 489 } 490 allocate(size_type n,const_ptr<Y>)491 template <class Y> pointer allocate(size_type n, const_ptr<Y>) 492 { 493 return pointer(static_cast<T const*>(::operator new(n * sizeof(T)))); 494 } 495 deallocate(pointer p,size_type)496 void deallocate(pointer p, size_type) 497 { 498 ::operator delete((void*)p.ptr_); 499 } 500 construct(T const * p,T const & t)501 void construct(T const* p, T const& t) { new ((void*)p) T(t); } 502 503 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 504 template <class... Args> construct(T const * p,BOOST_FWD_REF (Args)...args)505 void construct(T const* p, BOOST_FWD_REF(Args)... args) 506 { 507 new ((void*)p) T(boost::forward<Args>(args)...); 508 } 509 #endif 510 destroy(T const * p)511 void destroy(T const* p) { p->~T(); } 512 max_size() const513 size_type max_size() const { return 1000; } 514 515 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \ 516 BOOST_WORKAROUND(BOOST_MSVC, <= 1300) 517 public: operator =(allocator const &)518 allocator& operator=(allocator const&) { return *this; } 519 #else 520 private: 521 allocator& operator=(allocator const&); 522 #endif 523 #if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED operator &() const524 ampersand_operator_used operator&() const 525 { 526 return ampersand_operator_used(); 527 } 528 #endif 529 }; 530 531 template <class T> operator ==(allocator<T> const &,allocator<T> const &)532 inline bool operator==(allocator<T> const&, allocator<T> const&) 533 { 534 return true; 535 } 536 537 template <class T> operator !=(allocator<T> const &,allocator<T> const &)538 inline bool operator!=(allocator<T> const&, allocator<T> const&) 539 { 540 return false; 541 } 542 swap(allocator<T> &,allocator<T> &)543 template <class T> void swap(allocator<T>&, allocator<T>&) {} 544 545 // C++11 allocator 546 // 547 // Not a fully minimal C++11 allocator, just what I support. Hopefully will 548 // cut down further in the future. 549 550 template <class T> class cxx11_allocator 551 { 552 public: 553 typedef T value_type; 554 // template <class U> struct rebind { typedef cxx11_allocator<U> other; }; 555 cxx11_allocator()556 cxx11_allocator() {} cxx11_allocator(cxx11_allocator<Y> const &)557 template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {} cxx11_allocator(cxx11_allocator const &)558 cxx11_allocator(cxx11_allocator const&) {} ~cxx11_allocator()559 ~cxx11_allocator() {} 560 address(T & r)561 T* address(T& r) { return &r; } address(T const & r)562 T const* address(T const& r) { return &r; } 563 allocate(std::size_t n)564 T* allocate(std::size_t n) 565 { 566 return static_cast<T*>(::operator new(n * sizeof(T))); 567 } 568 allocate(std::size_t n,const_ptr<Y>)569 template <class Y> T* allocate(std::size_t n, const_ptr<Y>) 570 { 571 return static_cast<T*>(::operator new(n * sizeof(T))); 572 } 573 deallocate(T * p,std::size_t)574 void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } 575 construct(T * p,T const & t)576 void construct(T* p, T const& t) { new ((void*)p) T(t); } 577 578 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) construct(T * p,BOOST_FWD_REF (Args)...args)579 template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) 580 { 581 new ((void*)p) T(boost::forward<Args>(args)...); 582 } 583 #endif 584 destroy(T * p)585 void destroy(T* p) { p->~T(); } 586 max_size() const587 std::size_t max_size() const { return 1000u; } 588 }; 589 590 template <class T> operator ==(cxx11_allocator<T> const &,cxx11_allocator<T> const &)591 inline bool operator==(cxx11_allocator<T> const&, cxx11_allocator<T> const&) 592 { 593 return true; 594 } 595 596 template <class T> operator !=(cxx11_allocator<T> const &,cxx11_allocator<T> const &)597 inline bool operator!=(cxx11_allocator<T> const&, cxx11_allocator<T> const&) 598 { 599 return false; 600 } 601 swap(cxx11_allocator<T> &,cxx11_allocator<T> &)602 template <class T> void swap(cxx11_allocator<T>&, cxx11_allocator<T>&) {} 603 } 604 } 605 606 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) 607 namespace boost { 608 #else 609 namespace test { 610 namespace minimal { 611 #endif hash_value(test::minimal::copy_constructible_equality_comparable)612 std::size_t hash_value(test::minimal::copy_constructible_equality_comparable) 613 { 614 return 1; 615 } 616 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) 617 } 618 } 619 #else 620 } 621 #endif 622 623 #if defined(BOOST_MSVC) 624 #pragma warning(pop) 625 #endif 626 627 #endif 628