optional_test_move.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // Copyright (C) 2014 - 2015 Andrzej Krzemienski.
  2. //
  3. // Use, modification, and distribution is subject to the Boost Software
  4. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/lib/optional for documentation.
  8. //
  9. // You are welcome to contact the author at:
  10. // akrzemi1@gmail.com
  11. #include "boost/optional/optional.hpp"
  12. #ifdef __BORLANDC__
  13. #pragma hdrstop
  14. #endif
  15. #include "boost/core/lightweight_test.hpp"
  16. using boost::optional;
  17. using boost::none;
  18. //#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
  19. //#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
  20. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  21. enum State
  22. {
  23. sDefaultConstructed,
  24. sValueCopyConstructed,
  25. sValueMoveConstructed,
  26. sCopyConstructed,
  27. sMoveConstructed,
  28. sMoveAssigned,
  29. sCopyAssigned,
  30. sValueCopyAssigned,
  31. sValueMoveAssigned,
  32. sMovedFrom,
  33. sIntConstructed
  34. };
  35. struct OracleVal
  36. {
  37. State s;
  38. int i;
  39. OracleVal(int i = 0) : s(sIntConstructed), i(i) {}
  40. };
  41. struct Oracle
  42. {
  43. State s;
  44. OracleVal val;
  45. Oracle() : s(sDefaultConstructed) {}
  46. Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {}
  47. Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;}
  48. Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {}
  49. Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;}
  50. Oracle& operator=(const OracleVal& v) { s = sValueCopyAssigned; val = v; return *this; }
  51. Oracle& operator=(OracleVal&& v) { s = sValueMoveAssigned; val = std::move(v); v.s = sMovedFrom; return *this; }
  52. Oracle& operator=(const Oracle& o) { s = sCopyAssigned; val = o.val; return *this; }
  53. Oracle& operator=(Oracle&& o) { s = sMoveAssigned; val = std::move(o.val); o.s = sMovedFrom; return *this; }
  54. };
  55. bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; }
  56. bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; }
  57. void test_move_ctor_from_U()
  58. {
  59. optional<Oracle> o1 ((OracleVal()));
  60. BOOST_TEST(o1);
  61. BOOST_TEST(o1->s == sValueMoveConstructed || o1->s == sMoveConstructed);
  62. OracleVal v1;
  63. optional<Oracle> o2 (v1);
  64. BOOST_TEST(o2);
  65. BOOST_TEST(o2->s == sValueCopyConstructed || o2->s == sCopyConstructed || o2->s == sMoveConstructed );
  66. BOOST_TEST(v1.s == sIntConstructed);
  67. optional<Oracle> o3 (boost::move(v1));
  68. BOOST_TEST(o3);
  69. BOOST_TEST(o3->s == sValueMoveConstructed || o3->s == sMoveConstructed);
  70. BOOST_TEST(v1.s == sMovedFrom);
  71. }
  72. void test_move_ctor_form_T()
  73. {
  74. optional<Oracle> o1 ((Oracle()));
  75. BOOST_TEST(o1);
  76. BOOST_TEST(o1->s == sMoveConstructed);
  77. Oracle v1;
  78. optional<Oracle> o2 (v1);
  79. BOOST_TEST(o2);
  80. BOOST_TEST(o2->s == sCopyConstructed);
  81. BOOST_TEST(v1.s == sDefaultConstructed);
  82. optional<Oracle> o3 (boost::move(v1));
  83. BOOST_TEST(o3);
  84. BOOST_TEST(o3->s == sMoveConstructed);
  85. BOOST_TEST(v1.s == sMovedFrom);
  86. }
  87. void test_move_ctor_from_optional_T()
  88. {
  89. optional<Oracle> o1;
  90. optional<Oracle> o2(boost::move(o1));
  91. BOOST_TEST(!o1);
  92. BOOST_TEST(!o2);
  93. optional<Oracle> o3((Oracle()));
  94. optional<Oracle> o4(boost::move(o3));
  95. BOOST_TEST(o3);
  96. BOOST_TEST(o4);
  97. BOOST_TEST(o3->s == sMovedFrom);
  98. BOOST_TEST(o4->s == sMoveConstructed);
  99. optional<Oracle> o5((optional<Oracle>()));
  100. BOOST_TEST(!o5);
  101. optional<Oracle> o6((optional<Oracle>(Oracle())));
  102. BOOST_TEST(o6);
  103. BOOST_TEST(o6->s == sMoveConstructed);
  104. optional<Oracle> o7(o6); // does copy ctor from non-const lvalue compile?
  105. }
  106. void test_move_assign_from_U()
  107. {
  108. optional<Oracle> o1 = boost::none; // test if additional ctors didn't break it
  109. o1 = boost::none; // test if additional assignments didn't break it
  110. o1 = OracleVal();
  111. BOOST_TEST(o1);
  112. BOOST_TEST(o1->s == sValueMoveConstructed);
  113. o1 = OracleVal();
  114. BOOST_TEST(o1);
  115. BOOST_TEST(o1->s == sMoveAssigned);
  116. OracleVal v1;
  117. optional<Oracle> o2;
  118. o2 = v1;
  119. BOOST_TEST(o2);
  120. BOOST_TEST(o2->s == sValueCopyConstructed);
  121. BOOST_TEST(v1.s == sIntConstructed);
  122. o2 = v1;
  123. BOOST_TEST(o2);
  124. BOOST_TEST(o2->s == sCopyAssigned || o2->s == sMoveAssigned);
  125. BOOST_TEST(v1.s == sIntConstructed);
  126. optional<Oracle> o3;
  127. o3 = boost::move(v1);
  128. BOOST_TEST(o3);
  129. BOOST_TEST(o3->s == sValueMoveConstructed);
  130. BOOST_TEST(v1.s == sMovedFrom);
  131. }
  132. void test_move_assign_from_T()
  133. {
  134. optional<Oracle> o1;
  135. o1 = Oracle();
  136. BOOST_TEST(o1);
  137. BOOST_TEST(o1->s == sMoveConstructed);
  138. o1 = Oracle();
  139. BOOST_TEST(o1);
  140. BOOST_TEST(o1->s == sMoveAssigned);
  141. Oracle v1;
  142. optional<Oracle> o2;
  143. o2 = v1;
  144. BOOST_TEST(o2);
  145. BOOST_TEST(o2->s == sCopyConstructed);
  146. BOOST_TEST(v1.s == sDefaultConstructed);
  147. o2 = v1;
  148. BOOST_TEST(o2);
  149. BOOST_TEST(o2->s == sCopyAssigned);
  150. BOOST_TEST(v1.s == sDefaultConstructed);
  151. optional<Oracle> o3;
  152. o3 = boost::move(v1);
  153. BOOST_TEST(o3);
  154. BOOST_TEST(o3->s == sMoveConstructed);
  155. BOOST_TEST(v1.s == sMovedFrom);
  156. }
  157. void test_move_assign_from_optional_T()
  158. {
  159. optional<Oracle> o1;
  160. optional<Oracle> o2;
  161. o1 = optional<Oracle>();
  162. BOOST_TEST(!o1);
  163. optional<Oracle> o3((Oracle()));
  164. o1 = o3;
  165. BOOST_TEST(o3);
  166. BOOST_TEST(o3->s == sMoveConstructed);
  167. BOOST_TEST(o1);
  168. BOOST_TEST(o1->s == sCopyConstructed);
  169. o2 = boost::move(o3);
  170. BOOST_TEST(o3);
  171. BOOST_TEST(o3->s == sMovedFrom);
  172. BOOST_TEST(o2);
  173. BOOST_TEST(o2->s == sMoveConstructed);
  174. o2 = optional<Oracle>((Oracle()));
  175. BOOST_TEST(o2);
  176. BOOST_TEST(o2->s == sMoveAssigned);
  177. }
  178. class MoveOnly
  179. {
  180. public:
  181. int val;
  182. MoveOnly(int v) : val(v) {}
  183. MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
  184. void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
  185. private:
  186. MoveOnly(MoveOnly const&);
  187. void operator=(MoveOnly const&);
  188. friend class MoveOnlyB;
  189. };
  190. void test_with_move_only()
  191. {
  192. optional<MoveOnly> o1;
  193. optional<MoveOnly> o2((MoveOnly(1)));
  194. BOOST_TEST(o2);
  195. BOOST_TEST(o2->val == 1);
  196. optional<MoveOnly> o3 (boost::move(o1));
  197. BOOST_TEST(!o3);
  198. optional<MoveOnly> o4 (boost::move(o2));
  199. BOOST_TEST(o4);
  200. BOOST_TEST(o4->val == 1);
  201. BOOST_TEST(o2);
  202. BOOST_TEST(o2->val == 0);
  203. o3 = boost::move(o4);
  204. BOOST_TEST(o3);
  205. BOOST_TEST(o3->val == 1);
  206. BOOST_TEST(o4);
  207. BOOST_TEST(o4->val == 0);
  208. }
  209. class MoveOnlyB
  210. {
  211. public:
  212. int val;
  213. MoveOnlyB(int v) : val(v) {}
  214. MoveOnlyB(MoveOnlyB&& rhs) : val(rhs.val) { rhs.val = 0; }
  215. void operator=(MoveOnlyB&& rhs) {val = rhs.val; rhs.val = 0; }
  216. MoveOnlyB(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
  217. void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
  218. private:
  219. MoveOnlyB(MoveOnlyB const&);
  220. void operator=(MoveOnlyB const&);
  221. MoveOnlyB(MoveOnly const&);
  222. void operator=(MoveOnly const&);
  223. };
  224. void test_move_assign_from_optional_U()
  225. {
  226. optional<MoveOnly> a((MoveOnly(2)));
  227. optional<MoveOnlyB> b1;
  228. b1 = boost::move(a);
  229. BOOST_TEST(b1);
  230. BOOST_TEST(b1->val == 2);
  231. BOOST_TEST(a);
  232. BOOST_TEST(a->val == 0);
  233. b1 = MoveOnly(4);
  234. BOOST_TEST(b1);
  235. BOOST_TEST(b1->val == 4);
  236. }
  237. void test_move_ctor_from_optional_U()
  238. {
  239. optional<MoveOnly> a((MoveOnly(2)));
  240. optional<MoveOnlyB> b1(boost::move(a));
  241. BOOST_TEST(b1);
  242. BOOST_TEST(b1->val == 2);
  243. BOOST_TEST(a);
  244. BOOST_TEST(a->val == 0);
  245. optional<MoveOnlyB> b2(( optional<MoveOnly>(( MoveOnly(4) )) ));
  246. BOOST_TEST(b2);
  247. BOOST_TEST(b2->val == 4);
  248. }
  249. void test_swap()
  250. {
  251. optional<MoveOnly> a((MoveOnly(2)));
  252. optional<MoveOnly> b((MoveOnly(3)));
  253. swap(a, b);
  254. BOOST_TEST(a->val == 3);
  255. BOOST_TEST(b->val == 2);
  256. }
  257. void test_optional_ref_to_movables()
  258. {
  259. MoveOnly m(3);
  260. optional<MoveOnly&> orm = m;
  261. orm->val = 2;
  262. BOOST_TEST(m.val == 2);
  263. optional<MoveOnly&> orm2 = orm;
  264. orm2->val = 1;
  265. BOOST_TEST(m.val == 1);
  266. BOOST_TEST(orm->val == 1);
  267. optional<MoveOnly&> orm3 = boost::move(orm);
  268. orm3->val = 4;
  269. BOOST_TEST(m.val == 4);
  270. BOOST_TEST(orm->val == 4);
  271. BOOST_TEST(orm2->val == 4);
  272. }
  273. #endif
  274. int main()
  275. {
  276. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  277. test_move_ctor_from_U();
  278. test_move_ctor_form_T();
  279. test_move_ctor_from_optional_T();
  280. test_move_ctor_from_optional_U();
  281. test_move_assign_from_U();
  282. test_move_assign_from_T();
  283. test_move_assign_from_optional_T();
  284. test_move_assign_from_optional_U();
  285. test_with_move_only();
  286. test_optional_ref_to_movables();
  287. test_swap();
  288. #endif
  289. return boost::report_errors();
  290. }