minimal.hpp 16 KB

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