test_smart_cast.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // test_smart_cast.cpp:
  3. // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
  4. // Use, modification and distribution is subject to the Boost Software
  5. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // <gennadiy.rozental@tfn.com>
  8. #include <exception>
  9. #include <boost/serialization/smart_cast.hpp>
  10. #include "test_tools.hpp"
  11. #include <boost/noncopyable.hpp>
  12. using namespace boost::serialization;
  13. class Base1 : public boost::noncopyable
  14. {
  15. char a;
  16. };
  17. class Base2
  18. {
  19. int b;
  20. };
  21. #ifdef BOOST_MSVC
  22. # pragma warning(push)
  23. # pragma warning(disable : 4511 4512)
  24. #endif
  25. class Derived : public Base1, public Base2
  26. {
  27. long c;
  28. };
  29. #ifdef BOOST_MSVC
  30. #pragma warning(pop)
  31. #endif
  32. // if compiler doesn't support TPS, the smart_cast syntax doesn't
  33. // work for references. One has to use the smart_cast_reference
  34. // syntax (tested below ) instead.
  35. void test_static_reference_cast_2(){
  36. Derived d;
  37. Base1 & b1 = static_cast<Base1 &>(d);
  38. Base2 & b2 = static_cast<Base2 &>(d);
  39. Base1 & scb1 = smart_cast<Base1 &, Derived &>(d);
  40. Base2 & scb2 = smart_cast<Base2 &, Derived &>(d);
  41. BOOST_CHECK_EQUAL(& b1, & scb1);
  42. BOOST_CHECK_EQUAL(& b2, & scb2);
  43. // downcast
  44. // BOOST_CHECK_EQUAL(& d, & (smart_cast<Derived &, Base1 &>(b1)));
  45. // BOOST_CHECK_EQUAL(& d, & (smart_cast<Derived &, Base2 &>(b2)));
  46. // crosscast pointers fails at compiler time
  47. // BOOST_CHECK_EQUAL(pB2,smart_cast<B2 *>(pB1));
  48. // though explicit cross cast will always work
  49. BOOST_CHECK_EQUAL(& b2,(
  50. & smart_cast<Base2 &, Derived &>(
  51. smart_cast<Derived &, Base1 &>(b1)
  52. ))
  53. );
  54. }
  55. void test_static_reference_cast_1(){
  56. Derived d;
  57. Base1 & b1 = static_cast<Base1 &>(d);
  58. Base2 & b2 = static_cast<Base2 &>(d);
  59. Base1 & scb1 = smart_cast_reference<Base1 &>(d);
  60. Base2 & scb2 = smart_cast_reference<Base2 &>(d);
  61. BOOST_CHECK_EQUAL(& b1, & scb1);
  62. BOOST_CHECK_EQUAL(& b2, & scb2);
  63. // downcast
  64. BOOST_CHECK_EQUAL(& d, & (smart_cast_reference<Derived &>(b1)));
  65. BOOST_CHECK_EQUAL(& d, & (smart_cast_reference<Derived &>(b2)));
  66. // crosscast pointers fails at compiler time
  67. // BOOST_CHECK_EQUAL(pB2,smart_cast<B2 *>(pB1));
  68. // though explicit cross cast will always work
  69. BOOST_CHECK_EQUAL(& b2,(
  70. & smart_cast_reference<Base2 &>(
  71. smart_cast_reference<Derived &>(b1)
  72. ))
  73. );
  74. }
  75. void test_static_pointer_cast(){
  76. // pointers
  77. Derived d;
  78. Derived *pD = & d;
  79. Base1 *pB1 = pD;
  80. Base2 *pB2 = pD;
  81. // upcast
  82. BOOST_CHECK_EQUAL(pB1, smart_cast<Base1 *>(pD));
  83. BOOST_CHECK_EQUAL(pB2, smart_cast<Base2 *>(pD));
  84. // downcast
  85. BOOST_CHECK_EQUAL(pD, smart_cast<Derived *>(pB1));
  86. BOOST_CHECK_EQUAL(pD, smart_cast<Derived *>(pB2));
  87. // crosscast pointers fails at compiler time
  88. // BOOST_CHECK_EQUAL(pB2, smart_cast<Base2 *>(pB1));
  89. // though explicit cross cast will always work
  90. BOOST_CHECK_EQUAL(pB2,
  91. smart_cast<Base2 *>(
  92. smart_cast<Derived *>(pB1)
  93. )
  94. );
  95. }
  96. class VBase1 : public boost::noncopyable
  97. {
  98. char a;
  99. public:
  100. virtual ~VBase1(){};
  101. };
  102. class VBase2
  103. {
  104. int b;
  105. public:
  106. virtual ~VBase2(){};
  107. };
  108. #ifdef BOOST_MSVC
  109. # pragma warning(push)
  110. # pragma warning(disable : 4511 4512)
  111. #endif
  112. class VDerived : public VBase1, public VBase2
  113. {
  114. long c;
  115. public:
  116. virtual ~VDerived(){};
  117. };
  118. #ifdef BOOST_MSVC
  119. #pragma warning(pop)
  120. #endif
  121. // see above
  122. void test_dynamic_reference_cast_2(){
  123. VDerived d;
  124. VBase1 &b1 = dynamic_cast<VBase1 &>(d);
  125. VBase2 &b2 = static_cast<VBase2 &>(d);
  126. VBase1 & vb1 = smart_cast<VBase1 &, VDerived &>(d);
  127. BOOST_CHECK_EQUAL(& b1, & vb1);
  128. BOOST_CHECK_EQUAL(& b2, (& smart_cast<VBase2 &, VDerived &>(d)));
  129. // downcast
  130. BOOST_CHECK_EQUAL(& d, (& smart_cast<VDerived &, VBase1 &>(b1)));
  131. BOOST_CHECK_EQUAL(& d, (& smart_cast<VDerived &, VBase2 &>(b2)));
  132. // crosscast
  133. BOOST_CHECK_EQUAL(& b2, (& smart_cast<VBase2 &, VBase1 &>(b1)));
  134. // explicit cross cast should always work
  135. BOOST_CHECK_EQUAL(& b2, (
  136. & smart_cast<VBase2 &, VDerived &>(
  137. smart_cast<VDerived &, VBase1 &>(b1)
  138. ))
  139. );
  140. }
  141. void test_dynamic_reference_cast_1(){
  142. VDerived d;
  143. VBase1 &b1 = dynamic_cast<VBase1 &>(d);
  144. VBase2 &b2 = static_cast<VBase2 &>(d);
  145. VBase1 & vb1 = smart_cast_reference<VBase1 &>(d);
  146. BOOST_CHECK_EQUAL(& b1, & vb1);
  147. BOOST_CHECK_EQUAL(& b2, (& smart_cast_reference<VBase2 &>(d)));
  148. // downcast
  149. BOOST_CHECK_EQUAL(& d, (& smart_cast_reference<VDerived &>(b1)));
  150. BOOST_CHECK_EQUAL(& d, (& smart_cast_reference<VDerived &>(b2)));
  151. // crosscast
  152. BOOST_CHECK_EQUAL(& b2, (& smart_cast_reference<VBase2 &>(b1)));
  153. // explicit cross cast should always work
  154. BOOST_CHECK_EQUAL(& b2, (
  155. & smart_cast_reference<VBase2 &>(
  156. smart_cast_reference<VDerived &>(b1)
  157. ))
  158. );
  159. }
  160. void test_dynamic_pointer_cast(){
  161. // pointers
  162. VDerived d;
  163. VDerived *pD = & d;
  164. VBase1 *pB1 = pD;
  165. VBase2 *pB2 = pD;
  166. // upcast
  167. BOOST_CHECK_EQUAL(pB1, smart_cast<VBase1 *>(pD));
  168. BOOST_CHECK_EQUAL(pB2, smart_cast<VBase2 *>(pD));
  169. // downcast
  170. BOOST_CHECK_EQUAL(pD, smart_cast<VDerived *>(pB1));
  171. BOOST_CHECK_EQUAL(pD, smart_cast<VDerived *>(pB2));
  172. // crosscast pointers fails at compiler time
  173. BOOST_CHECK_EQUAL(pB2, smart_cast<VBase2 *>(pB1));
  174. // though explicit cross cast will always work
  175. BOOST_CHECK_EQUAL(pB2,
  176. smart_cast<VBase2 *>(
  177. smart_cast<VDerived *>(pB1)
  178. )
  179. );
  180. }
  181. int
  182. test_main(int /* argc */, char * /* argv */[])
  183. {
  184. test_static_reference_cast_2();
  185. test_static_reference_cast_1();
  186. test_static_pointer_cast();
  187. test_dynamic_reference_cast_2();
  188. test_dynamic_reference_cast_1();
  189. test_dynamic_pointer_cast();
  190. return EXIT_SUCCESS;
  191. }