cpp11_pointer_cast_test.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //
  2. // cpp11_pointer_cast_test.cpp - a test for boost/pointer_cast.hpp with std::shared_ptr and std::unique_ptr
  3. //
  4. // Copyright (c) 2016 Karolin Varner
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #include <boost/pointer_cast.hpp>
  11. #include <boost/config.hpp>
  12. #include <boost/detail/lightweight_test.hpp>
  13. #include <boost/get_pointer.hpp>
  14. #include <boost/shared_ptr.hpp>
  15. #include <memory>
  16. #include <utility>
  17. #include <functional>
  18. #if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) \
  19. || defined( BOOST_NO_CXX11_HDR_FUNCTIONAL ) \
  20. || defined( BOOST_NO_CXX11_HDR_UTILITY ) \
  21. || defined( BOOST_NO_CXX11_LAMBDAS ) \
  22. || defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  23. // We expect all the features or none of the features to be
  24. // available, since we should be on C++11
  25. int main() { return 0; }
  26. #else
  27. namespace
  28. {
  29. // Let's create these inheritance relationship:
  30. //
  31. // base base2
  32. // | |
  33. // derived
  34. // |
  35. // derived_derived
  36. //
  37. class base
  38. {
  39. public:
  40. virtual ~base(){}
  41. int filler [5];
  42. };
  43. class base2
  44. {
  45. public:
  46. virtual ~base2(){}
  47. int filler [5];
  48. };
  49. class derived
  50. : public base, public base2
  51. {
  52. int filler [5];
  53. };
  54. class derived_derived
  55. : public derived
  56. {
  57. int filler [5];
  58. };
  59. // And now some simple check functions
  60. #if !defined( BOOST_NO_RTTI )
  61. template <class BasePtr>
  62. bool check_dynamic_pointer_cast(const BasePtr &ptr)
  63. {
  64. //Check that dynamic_pointer_cast versus dynamic_cast
  65. return
  66. //Correct cast with dynamic_pointer_cast
  67. boost::get_pointer(boost::dynamic_pointer_cast<derived>(ptr)) ==
  68. //Correct cast with dynamic_cast
  69. dynamic_cast<derived*>(boost::get_pointer(ptr))
  70. &&
  71. //Incorrect cast with dynamic_pointer_cast
  72. boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>(ptr)) ==
  73. //Incorrect cast with dynamic_cast
  74. dynamic_cast<derived_derived*>(boost::get_pointer(ptr));
  75. }
  76. #endif
  77. template <class BasePtr>
  78. bool check_static_pointer_cast(const BasePtr &ptr)
  79. {
  80. return
  81. //Cast base -> derived -> base2 using static_pointer_cast
  82. boost::get_pointer(
  83. boost::static_pointer_cast<base2>(
  84. boost::static_pointer_cast<derived>(ptr))) ==
  85. //Now the same with static_cast
  86. static_cast<base2*>(static_cast<derived*>(boost::get_pointer(ptr)));
  87. }
  88. template <class BasePtr>
  89. bool check_const_pointer_cast(const BasePtr &ptr)
  90. {
  91. return
  92. //Unconst and const again using const_pointer_cast
  93. boost::get_pointer(
  94. boost::const_pointer_cast<const base>
  95. (boost::const_pointer_cast<base>(ptr))) ==
  96. //Now the same with const_cast
  97. const_cast<const base*>(const_cast<base*>(boost::get_pointer(ptr)));
  98. }
  99. template <class BasePtr>
  100. void check_all_copy_casts(const BasePtr &ptr)
  101. {
  102. #if !defined( BOOST_NO_RTTI )
  103. BOOST_TEST( check_dynamic_pointer_cast( ptr ) );
  104. #endif
  105. BOOST_TEST( check_static_pointer_cast( ptr ) );
  106. BOOST_TEST( check_const_pointer_cast( ptr ) );
  107. }
  108. #if !defined( BOOST_NO_RTTI )
  109. template <class BasePtr>
  110. bool check_dynamic_moving_pointer_cast(std::function<BasePtr()> f)
  111. {
  112. BasePtr smart1 = f(), smart2 = f();
  113. derived* expect1 = dynamic_cast<derived*>(boost::get_pointer(smart1));
  114. derived_derived* expect2 = dynamic_cast<derived_derived*>(boost::get_pointer(smart2));
  115. //Check that dynamic_pointer_cast versus dynamic_cast
  116. return
  117. //Correct cast with dynamic_pointer_cast
  118. boost::get_pointer(boost::dynamic_pointer_cast<derived>( std::move(smart1) )) == expect1
  119. &&
  120. //Incorrect cast with dynamic_pointer_cast
  121. boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>( std::move(smart2) )) == expect2;
  122. }
  123. #endif
  124. template <class BasePtr>
  125. bool check_static_moving_pointer_cast(std::function<BasePtr()> f)
  126. {
  127. BasePtr smart = f();
  128. base2 *expect = static_cast<base2*>(static_cast<derived*>(boost::get_pointer(smart)));
  129. return
  130. //Cast base -> derived -> base2 using static_pointer_cast
  131. boost::get_pointer(
  132. boost::static_pointer_cast<base2>(
  133. boost::static_pointer_cast<derived>( std::move(smart) ))) ==
  134. //Now the same with static_cast
  135. expect;
  136. }
  137. template <class BasePtr>
  138. bool check_const_moving_pointer_cast(std::function<BasePtr()> f)
  139. {
  140. BasePtr smart = f();
  141. const base *expect = const_cast<const base*>(const_cast<base*>(boost::get_pointer(smart)));
  142. return
  143. //Unconst and const again using const_pointer_cast
  144. boost::get_pointer(
  145. boost::const_pointer_cast<const base>
  146. (boost::const_pointer_cast<base>( std::move(smart) ))) ==
  147. //Now the same with const_cast
  148. expect;
  149. }
  150. template <class BasePtr>
  151. void check_all_moving_casts(std::function<BasePtr()> f) {
  152. #if !defined( BOOST_NO_RTTI )
  153. BOOST_TEST( check_dynamic_moving_pointer_cast( f ) );
  154. #endif
  155. BOOST_TEST( check_static_moving_pointer_cast( f ) );
  156. BOOST_TEST( check_const_moving_pointer_cast( f ) );
  157. }
  158. }
  159. int main()
  160. {
  161. std::shared_ptr<base> std_shared(new derived);
  162. boost::shared_ptr<base> boost_shared(new derived);
  163. base *plain = boost_shared.get();
  164. // plain & boost::shared_ptr moving pointer_cast checks; there
  165. // is no specific handleing for those types at the moment; this
  166. // test just makes sure they won't break when std::move() is used
  167. // in generic code
  168. check_all_moving_casts<boost::shared_ptr<base>>([&boost_shared]() {
  169. return boost_shared;
  170. });
  171. check_all_moving_casts<base*>([plain]() {
  172. return plain;
  173. });
  174. // std::shared_ptr casts
  175. check_all_copy_casts(std_shared);
  176. check_all_moving_casts<std::shared_ptr<base>>([&std_shared]() {
  177. return std_shared;
  178. });
  179. // std::unique_ptr casts
  180. check_all_moving_casts<std::unique_ptr<base>>([]() {
  181. return std::unique_ptr<base>(new derived);
  182. });
  183. return boost::report_errors();
  184. }
  185. #endif