pointer_traits_test.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/intrusive for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #include <boost/intrusive/detail/mpl.hpp>
  11. #include <boost/static_assert.hpp>
  12. #include <boost/intrusive/pointer_traits.hpp>
  13. #include <boost/core/lightweight_test.hpp>
  14. struct CompleteSmartPtrStats
  15. {
  16. static unsigned static_cast_called;
  17. static unsigned dynamic_cast_called;
  18. static unsigned const_cast_called;
  19. static unsigned pointer_to_called;
  20. static void reset_stats()
  21. {
  22. static_cast_called = 0;
  23. dynamic_cast_called = 0;
  24. const_cast_called = 0;
  25. pointer_to_called = 0;
  26. }
  27. };
  28. unsigned CompleteSmartPtrStats::static_cast_called= 0;
  29. unsigned CompleteSmartPtrStats::dynamic_cast_called = 0;
  30. unsigned CompleteSmartPtrStats::const_cast_called = 0;
  31. unsigned CompleteSmartPtrStats::pointer_to_called = 0;
  32. template<class T>
  33. class CompleteSmartPtr
  34. {
  35. template <class U>
  36. friend class CompleteSmartPtr;
  37. void unspecified_bool_type_func() const {}
  38. typedef void (CompleteSmartPtr::*unspecified_bool_type)() const;
  39. public:
  40. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  41. template <class U> using rebind = CompleteSmartPtr<U>;
  42. #else
  43. template <class U> struct rebind
  44. { typedef CompleteSmartPtr<U> other; };
  45. #endif
  46. typedef char difference_type;
  47. typedef T element_type;
  48. CompleteSmartPtr()
  49. : ptr_(0)
  50. {}
  51. explicit CompleteSmartPtr(T &p)
  52. : ptr_(&p)
  53. {}
  54. CompleteSmartPtr(const CompleteSmartPtr &c)
  55. { this->ptr_ = c.ptr_; }
  56. CompleteSmartPtr & operator=(const CompleteSmartPtr &c)
  57. { this->ptr_ = c.ptr_; }
  58. static CompleteSmartPtr pointer_to(T &r)
  59. { ++CompleteSmartPtrStats::pointer_to_called; return CompleteSmartPtr(r); }
  60. T * operator->() const
  61. { return ptr_; }
  62. T & operator *() const
  63. { return *ptr_; }
  64. operator unspecified_bool_type() const
  65. { return ptr_? &CompleteSmartPtr::unspecified_bool_type_func : 0; }
  66. template<class U>
  67. static CompleteSmartPtr static_cast_from(const CompleteSmartPtr<U> &uptr)
  68. {
  69. ++CompleteSmartPtrStats::static_cast_called;
  70. element_type* const p = static_cast<element_type*>(uptr.ptr_);
  71. return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
  72. }
  73. template<class U>
  74. static CompleteSmartPtr const_cast_from(const CompleteSmartPtr<U> &uptr)
  75. {
  76. ++CompleteSmartPtrStats::const_cast_called;
  77. element_type* const p = const_cast<element_type*>(uptr.ptr_);
  78. return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
  79. }
  80. template<class U>
  81. static CompleteSmartPtr dynamic_cast_from(const CompleteSmartPtr<U> &uptr)
  82. {
  83. ++CompleteSmartPtrStats::dynamic_cast_called;
  84. element_type* const p = dynamic_cast<element_type*>(uptr.ptr_);
  85. return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
  86. }
  87. friend bool operator ==(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
  88. { return l.ptr_ == r.ptr_; }
  89. friend bool operator !=(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
  90. { return l.ptr_ != r.ptr_; }
  91. private:
  92. T *ptr_;
  93. };
  94. template<class T>
  95. class SimpleSmartPtr
  96. {
  97. void unspecified_bool_type_func() const {}
  98. typedef void (SimpleSmartPtr::*unspecified_bool_type)() const;
  99. public:
  100. SimpleSmartPtr()
  101. : ptr_(0)
  102. {}
  103. explicit SimpleSmartPtr(T *p)
  104. : ptr_(p)
  105. {}
  106. SimpleSmartPtr(const SimpleSmartPtr &c)
  107. { this->ptr_ = c.ptr_; }
  108. SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
  109. { this->ptr_ = c.ptr_; }
  110. friend bool operator ==(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
  111. { return l.ptr_ == r.ptr_; }
  112. friend bool operator !=(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
  113. { return l.ptr_ != r.ptr_; }
  114. T* operator->() const
  115. { return ptr_; }
  116. T & operator *() const
  117. { return *ptr_; }
  118. operator unspecified_bool_type() const
  119. { return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0; }
  120. private:
  121. T *ptr_;
  122. };
  123. class B{ public: virtual ~B(){} };
  124. class D : public B {};
  125. class DD : public virtual B {};
  126. int main()
  127. {
  128. int dummy;
  129. //Raw pointer
  130. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  131. <int*>::element_type, int>::value ));
  132. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  133. <int*>::pointer, int*>::value ));
  134. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  135. <int*>::difference_type, std::ptrdiff_t>::value ));
  136. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  137. <int*>::rebind_pointer<double>::type
  138. , double*>::value ));
  139. BOOST_TEST(boost::intrusive::pointer_traits<int*>::pointer_to(dummy) == &dummy);
  140. BOOST_TEST(boost::intrusive::pointer_traits<D*>:: static_cast_from((B*)0) == 0);
  141. BOOST_TEST(boost::intrusive::pointer_traits<D*>:: const_cast_from((const D*)0) == 0);
  142. BOOST_TEST(boost::intrusive::pointer_traits<DD*>:: dynamic_cast_from((B*)0) == 0);
  143. //Complete smart pointer
  144. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  145. < CompleteSmartPtr<int> >::element_type, int>::value ));
  146. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  147. < CompleteSmartPtr<int> >::pointer, CompleteSmartPtr<int> >::value ));
  148. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  149. < CompleteSmartPtr<int> >::difference_type, char>::value ));
  150. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  151. < CompleteSmartPtr<int> >::rebind_pointer<double>::type
  152. , CompleteSmartPtr<double> >::value ));
  153. //pointer_to
  154. CompleteSmartPtrStats::reset_stats();
  155. BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<int> >::pointer_to(dummy) == CompleteSmartPtr<int>(dummy));
  156. BOOST_TEST(CompleteSmartPtrStats::pointer_to_called == 1);
  157. //static_cast_from
  158. CompleteSmartPtrStats::reset_stats();
  159. BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::static_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<D>());
  160. BOOST_TEST(CompleteSmartPtrStats::static_cast_called == 1);
  161. //const_cast_from
  162. CompleteSmartPtrStats::reset_stats();
  163. BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::const_cast_from(CompleteSmartPtr<const D>()) == CompleteSmartPtr<D>());
  164. BOOST_TEST(CompleteSmartPtrStats::const_cast_called == 1);
  165. //dynamic_cast_from
  166. CompleteSmartPtrStats::reset_stats();
  167. BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<DD> >::dynamic_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<DD>());
  168. BOOST_TEST(CompleteSmartPtrStats::dynamic_cast_called == 1);
  169. //Simple smart pointer
  170. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  171. < SimpleSmartPtr<int> >::element_type, int>::value ));
  172. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  173. < SimpleSmartPtr<int> >::pointer, SimpleSmartPtr<int> >::value ));
  174. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  175. < SimpleSmartPtr<int> >::difference_type, std::ptrdiff_t>::value ));
  176. BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
  177. < SimpleSmartPtr<int> >::rebind_pointer<double>::type
  178. , SimpleSmartPtr<double> >::value ));
  179. BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<int> >::pointer_to(dummy) == SimpleSmartPtr<int>(&dummy));
  180. BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::static_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<D>());
  181. BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::const_cast_from(SimpleSmartPtr<const D>()) == SimpleSmartPtr<D>());
  182. BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<DD> >::dynamic_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<DD>());
  183. return boost::report_errors();
  184. }