optional_test.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
  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. // fernando_cacciola@hotmail.com
  11. //
  12. // Revisions:
  13. // 12 May 2008 (added more swap tests)
  14. //
  15. #include<iostream>
  16. #include<stdexcept>
  17. #include<string>
  18. #define BOOST_ENABLE_ASSERT_HANDLER
  19. #include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
  20. #include "boost/mpl/bool.hpp"
  21. #include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
  22. #include "boost/optional/optional.hpp"
  23. #ifdef __BORLANDC__
  24. #pragma hdrstop
  25. #endif
  26. #include "boost/none.hpp"
  27. #include "boost/core/lightweight_test.hpp"
  28. #include "optional_test_common.hpp"
  29. void test_implicit_construction ( optional<double> opt, double v, double z )
  30. {
  31. check_value(opt,v,z);
  32. }
  33. void test_implicit_construction ( optional<X> opt, X const& v, X const& z )
  34. {
  35. check_value(opt,v,z);
  36. }
  37. void test_default_implicit_construction ( double, optional<double> opt )
  38. {
  39. BOOST_TEST(!opt);
  40. }
  41. void test_default_implicit_construction ( X const&, optional<X> opt )
  42. {
  43. BOOST_TEST(!opt);
  44. }
  45. //
  46. // Basic test.
  47. // Check ordinary functionality:
  48. // Initialization, assignment, comparison and value-accessing.
  49. //
  50. template<class T>
  51. void test_basics( T const* )
  52. {
  53. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  54. T z(0);
  55. T a(1);
  56. // Default construction.
  57. // 'def' state is Uninitialized.
  58. // T::T() is not called (and it is not even defined)
  59. optional<T> def ;
  60. check_uninitialized(def);
  61. // Implicit construction
  62. // The first parameter is implicitely converted to optional<T>(a);
  63. test_implicit_construction(a,a,z);
  64. // Direct initialization.
  65. // 'oa' state is Initialized with 'a'
  66. // T::T( T const& x ) is used.
  67. set_pending_copy( ARG(T) ) ;
  68. optional<T> oa ( a ) ;
  69. check_is_not_pending_copy( ARG(T) );
  70. check_initialized(oa);
  71. check_value(oa,a,z);
  72. T b(2);
  73. optional<T> ob ;
  74. // Value-Assignment upon Uninitialized optional.
  75. // T::T( T const& x ) is used.
  76. set_pending_copy( ARG(T) ) ;
  77. ob = a ;
  78. check_is_not_pending_copy( ARG(T) ) ;
  79. check_initialized(ob);
  80. check_value(ob,a,z);
  81. // Value-Assignment upon Initialized optional.
  82. // T::operator=( T const& x ) is used
  83. set_pending_assign( ARG(T) ) ;
  84. set_pending_copy ( ARG(T) ) ;
  85. set_pending_dtor ( ARG(T) ) ;
  86. ob = b ;
  87. check_is_not_pending_assign( ARG(T) ) ;
  88. check_is_pending_copy ( ARG(T) ) ;
  89. check_is_pending_dtor ( ARG(T) ) ;
  90. check_initialized(ob);
  91. check_value(ob,b,z);
  92. // Assignment initialization.
  93. // T::T ( T const& x ) is used to copy new value.
  94. set_pending_copy( ARG(T) ) ;
  95. optional<T> const oa2 ( oa ) ;
  96. check_is_not_pending_copy( ARG(T) ) ;
  97. check_initialized_const(oa2);
  98. check_value_const(oa2,a,z);
  99. // Assignment
  100. // T::operator= ( T const& x ) is used to copy new value.
  101. set_pending_assign( ARG(T) ) ;
  102. oa = ob ;
  103. check_is_not_pending_assign( ARG(T) ) ;
  104. check_initialized(oa);
  105. check_value(oa,b,z);
  106. // Uninitializing Assignment upon Initialized Optional
  107. // T::~T() is used to destroy previous value in oa.
  108. set_pending_dtor( ARG(T) ) ;
  109. set_pending_copy( ARG(T) ) ;
  110. oa = def ;
  111. check_is_not_pending_dtor( ARG(T) ) ;
  112. check_is_pending_copy ( ARG(T) ) ;
  113. check_uninitialized(oa);
  114. // Uninitializing Assignment upon Uninitialized Optional
  115. // (Dtor is not called this time)
  116. set_pending_dtor( ARG(T) ) ;
  117. set_pending_copy( ARG(T) ) ;
  118. oa = def ;
  119. check_is_pending_dtor( ARG(T) ) ;
  120. check_is_pending_copy( ARG(T) ) ;
  121. check_uninitialized(oa);
  122. // Deinitialization of Initialized Optional
  123. // T::~T() is used to destroy previous value in ob.
  124. set_pending_dtor( ARG(T) ) ;
  125. ob.reset();
  126. check_is_not_pending_dtor( ARG(T) ) ;
  127. check_uninitialized(ob);
  128. // Deinitialization of Uninitialized Optional
  129. // (Dtor is not called this time)
  130. set_pending_dtor( ARG(T) ) ;
  131. ob.reset();
  132. check_is_pending_dtor( ARG(T) ) ;
  133. check_uninitialized(ob);
  134. }
  135. template<class T>
  136. void test_conditional_ctor_and_get_valur_or ( T const* )
  137. {
  138. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  139. T a(321);
  140. T z(123);
  141. optional<T> const cdef0(false,a);
  142. optional<T> def0(false,a);
  143. optional<T> def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified
  144. check_uninitialized(def0);
  145. check_uninitialized(def1);
  146. optional<T> const co0(true,a);
  147. optional<T> o0(true,a);
  148. optional<T> o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified
  149. check_initialized(o0);
  150. check_initialized(o1);
  151. check_value(o0,a,z);
  152. check_value(o1,a,z);
  153. T b = def0.get_value_or(z);
  154. BOOST_TEST( b == z ) ;
  155. b = get_optional_value_or(def0,z);
  156. BOOST_TEST( b == z ) ;
  157. b = o0.get_value_or(z);
  158. BOOST_TEST( b == a ) ;
  159. b = get_optional_value_or(o0,z);
  160. BOOST_TEST( b == a ) ;
  161. T const& crz = z ;
  162. T& rz = z ;
  163. T const& crzz = def0.get_value_or(crz);
  164. BOOST_TEST( crzz == crz ) ;
  165. T& rzz = def0.get_value_or(rz);
  166. BOOST_TEST( rzz == rz ) ;
  167. T const& crzzz = get_optional_value_or(cdef0,crz);
  168. BOOST_TEST( crzzz == crz ) ;
  169. T& rzzz = get_optional_value_or(def0,rz);
  170. BOOST_TEST( rzzz == rz ) ;
  171. T const& crb = o0.get_value_or(crz);
  172. BOOST_TEST( crb == a ) ;
  173. T& rb = o0.get_value_or(rz);
  174. BOOST_TEST( rb == b ) ;
  175. T const& crbb = get_optional_value_or(co0,crz);
  176. BOOST_TEST( crbb == b ) ;
  177. T const& crbbb = get_optional_value_or(o0,crz);
  178. BOOST_TEST( crbbb == b ) ;
  179. T& rbb = get_optional_value_or(o0,rz);
  180. BOOST_TEST( rbb == b ) ;
  181. T& ra = a ;
  182. optional<T&> defref(false,ra);
  183. BOOST_TEST(!defref);
  184. optional<T&> ref(true,ra);
  185. BOOST_TEST(!!ref);
  186. a = T(432);
  187. BOOST_TEST( *ref == a ) ;
  188. T& r1 = defref.get_value_or(z);
  189. BOOST_TEST( r1 == z ) ;
  190. T& r2 = ref.get_value_or(z);
  191. BOOST_TEST( r2 == a ) ;
  192. }
  193. //
  194. // Test Direct Value Manipulation
  195. //
  196. template<class T>
  197. void test_direct_value_manip( T const* )
  198. {
  199. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  200. T x(3);
  201. optional<T> const c_opt0(x) ;
  202. optional<T> opt0(x);
  203. BOOST_TEST( c_opt0.get().V() == x.V() ) ;
  204. BOOST_TEST( opt0.get().V() == x.V() ) ;
  205. BOOST_TEST( c_opt0->V() == x.V() ) ;
  206. BOOST_TEST( opt0->V() == x.V() ) ;
  207. BOOST_TEST( (*c_opt0).V() == x.V() ) ;
  208. BOOST_TEST( (* opt0).V() == x.V() ) ;
  209. T y(4);
  210. opt0 = y ;
  211. BOOST_TEST( get(opt0).V() == y.V() ) ;
  212. }
  213. //
  214. // Test Uninitialized access assert
  215. //
  216. template<class T>
  217. void test_uninitialized_access( T const* )
  218. {
  219. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  220. optional<T> def ;
  221. bool passed = false ;
  222. try
  223. {
  224. // This should throw because 'def' is uninitialized
  225. T const& n = def.get() ;
  226. boost::ignore_unused(n);
  227. passed = true ;
  228. }
  229. catch (...) {}
  230. BOOST_TEST(!passed);
  231. passed = false ;
  232. try
  233. {
  234. // This should throw because 'def' is uninitialized
  235. T const& n = *def ;
  236. boost::ignore_unused(n);
  237. passed = true ;
  238. }
  239. catch (...) {}
  240. BOOST_TEST(!passed);
  241. passed = false ;
  242. try
  243. {
  244. T v(5) ;
  245. boost::ignore_unused(v);
  246. // This should throw because 'def' is uninitialized
  247. *def = v ;
  248. passed = true ;
  249. }
  250. catch (...) {}
  251. BOOST_TEST(!passed);
  252. passed = false ;
  253. try
  254. {
  255. // This should throw because 'def' is uninitialized
  256. T v = *(def.operator->()) ;
  257. boost::ignore_unused(v);
  258. passed = true ;
  259. }
  260. catch (...) {}
  261. BOOST_TEST(!passed);
  262. }
  263. #if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0
  264. void prevent_buggy_optimization( bool v ) {}
  265. #endif
  266. //
  267. // Test Direct Initialization of optional for a T with throwing copy-ctor.
  268. //
  269. template<class T>
  270. void test_throwing_direct_init( T const* )
  271. {
  272. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  273. T a(6);
  274. int count = get_instance_count( ARG(T) ) ;
  275. set_throw_on_copy( ARG(T) ) ;
  276. bool passed = false ;
  277. try
  278. {
  279. // This should:
  280. // Attempt to copy construct 'a' and throw.
  281. // 'opt' won't be constructed.
  282. set_pending_copy( ARG(T) ) ;
  283. #if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0
  284. // Intel C++ 7.0 specific:
  285. // For some reason, when "check_is_not_pending_copy",
  286. // after the exception block is reached,
  287. // X::pending_copy==true even though X's copy ctor set it to false.
  288. // I guessed there is some sort of optimization bug,
  289. // and it seems to be the since the following additional line just
  290. // solves the problem (!?)
  291. prevent_buggy_optimization(X::pending_copy);
  292. #endif
  293. optional<T> opt(a) ;
  294. passed = true ;
  295. }
  296. catch ( ... ){}
  297. BOOST_TEST(!passed);
  298. check_is_not_pending_copy( ARG(T) );
  299. check_instance_count(count, ARG(T) );
  300. reset_throw_on_copy( ARG(T) ) ;
  301. }
  302. //
  303. // Test Value Assignment to an Uninitialized optional for a T with a throwing copy-ctor
  304. //
  305. template<class T>
  306. void test_throwing_val_assign_on_uninitialized( T const* )
  307. {
  308. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  309. T a(7);
  310. int count = get_instance_count( ARG(T) ) ;
  311. set_throw_on_copy( ARG(T) ) ;
  312. optional<T> opt ;
  313. bool passed = false ;
  314. try
  315. {
  316. // This should:
  317. // Attempt to copy construct 'a' and throw.
  318. // opt should be left uninitialized.
  319. set_pending_copy( ARG(T) ) ;
  320. opt.reset( a );
  321. passed = true ;
  322. }
  323. catch ( ... ) {}
  324. BOOST_TEST(!passed);
  325. check_is_not_pending_copy( ARG(T) );
  326. check_instance_count(count, ARG(T) );
  327. check_uninitialized(opt);
  328. reset_throw_on_copy( ARG(T) ) ;
  329. }
  330. //
  331. // Test Value Reset on an Initialized optional for a T with a throwing copy-ctor
  332. //
  333. template<class T>
  334. void test_throwing_val_assign_on_initialized( T const* )
  335. {
  336. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  337. T z(0);
  338. T a(8);
  339. T b(9);
  340. T x(-1);
  341. int count = get_instance_count( ARG(T) ) ;
  342. optional<T> opt ( b ) ;
  343. ++ count ;
  344. check_instance_count(count, ARG(T) );
  345. check_value(opt,b,z);
  346. set_throw_on_assign( ARG(T) ) ;
  347. bool passed = false ;
  348. try
  349. {
  350. // This should:
  351. // Attempt to assign 'a' and throw.
  352. // opt is kept initialized but its value not neccesarily fully assigned
  353. // (in this test, incompletely assigned is flaged with the value -1 being set)
  354. set_pending_assign( ARG(T) ) ;
  355. opt.reset ( a ) ;
  356. passed = true ;
  357. }
  358. catch ( ... ) {}
  359. BOOST_TEST(!passed);
  360. check_is_not_pending_assign( ARG(T) );
  361. check_instance_count(count, ARG(T) );
  362. check_initialized(opt);
  363. check_value(opt,x,z);
  364. reset_throw_on_assign ( ARG(T) ) ;
  365. }
  366. //
  367. // Test Copy Initialization from an Initialized optional for a T with a throwing copy-ctor
  368. //
  369. template<class T>
  370. void test_throwing_copy_initialization( T const* )
  371. {
  372. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  373. T z(0);
  374. T a(10);
  375. optional<T> opt (a);
  376. int count = get_instance_count( ARG(T) ) ;
  377. set_throw_on_copy( ARG(T) ) ;
  378. bool passed = false ;
  379. try
  380. {
  381. // This should:
  382. // Attempt to copy construct 'opt' and throw.
  383. // opt1 won't be constructed.
  384. set_pending_copy( ARG(T) ) ;
  385. optional<T> opt1 = opt ;
  386. passed = true ;
  387. }
  388. catch ( ... ) {}
  389. BOOST_TEST(!passed);
  390. check_is_not_pending_copy( ARG(T) );
  391. check_instance_count(count, ARG(T) );
  392. // Nothing should have happened to the source optional.
  393. check_initialized(opt);
  394. check_value(opt,a,z);
  395. reset_throw_on_copy( ARG(T) ) ;
  396. }
  397. //
  398. // Test Assignment to an Uninitialized optional from an Initialized optional
  399. // for a T with a throwing copy-ctor
  400. //
  401. template<class T>
  402. void test_throwing_assign_to_uninitialized( T const* )
  403. {
  404. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  405. T z(0);
  406. T a(11);
  407. optional<T> opt0 ;
  408. optional<T> opt1(a) ;
  409. int count = get_instance_count( ARG(T) ) ;
  410. set_throw_on_copy( ARG(T) ) ;
  411. bool passed = false ;
  412. try
  413. {
  414. // This should:
  415. // Attempt to copy construct 'opt1.value()' into opt0 and throw.
  416. // opt0 should be left uninitialized.
  417. set_pending_copy( ARG(T) ) ;
  418. opt0 = opt1 ;
  419. passed = true ;
  420. }
  421. catch ( ... ) {}
  422. BOOST_TEST(!passed);
  423. check_is_not_pending_copy( ARG(T) );
  424. check_instance_count(count, ARG(T) );
  425. check_uninitialized(opt0);
  426. reset_throw_on_copy( ARG(T) ) ;
  427. }
  428. //
  429. // Test Assignment to an Initialized optional from an Initialized optional
  430. // for a T with a throwing copy-ctor
  431. //
  432. template<class T>
  433. void test_throwing_assign_to_initialized( T const* )
  434. {
  435. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  436. T z(0);
  437. T a(12);
  438. T b(13);
  439. T x(-1);
  440. optional<T> opt0(a) ;
  441. optional<T> opt1(b) ;
  442. int count = get_instance_count( ARG(T) ) ;
  443. set_throw_on_assign( ARG(T) ) ;
  444. bool passed = false ;
  445. try
  446. {
  447. // This should:
  448. // Attempt to copy construct 'opt1.value()' into opt0 and throw.
  449. // opt0 is kept initialized but its value not neccesarily fully assigned
  450. // (in this test, incompletely assigned is flaged with the value -1 being set)
  451. set_pending_assign( ARG(T) ) ;
  452. opt0 = opt1 ;
  453. passed = true ;
  454. }
  455. catch ( ... ) {}
  456. BOOST_TEST(!passed);
  457. // opt0 was left uninitialized
  458. check_is_not_pending_assign( ARG(T) );
  459. check_instance_count(count, ARG(T) );
  460. check_initialized(opt0);
  461. check_value(opt0,x,z);
  462. reset_throw_on_assign( ARG(T) ) ;
  463. }
  464. //
  465. // Test swap in a no-throwing case
  466. //
  467. template<class T>
  468. void test_no_throwing_swap( T const* )
  469. {
  470. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  471. T z(0);
  472. T a(14);
  473. T b(15);
  474. optional<T> def0 ;
  475. optional<T> def1 ;
  476. optional<T> opt0(a) ;
  477. optional<T> opt1(b) ;
  478. int count = get_instance_count( ARG(T) ) ;
  479. swap(def0,def1);
  480. check_uninitialized(def0);
  481. check_uninitialized(def1);
  482. swap(def0,opt0);
  483. check_uninitialized(opt0);
  484. check_initialized(def0);
  485. check_value(def0,a,z);
  486. // restore def0 and opt0
  487. swap(def0,opt0);
  488. swap(opt0,opt1);
  489. check_instance_count(count, ARG(T) );
  490. check_initialized(opt0);
  491. check_initialized(opt1);
  492. check_value(opt0,b,z);
  493. check_value(opt1,a,z);
  494. }
  495. //
  496. // Test swap in a throwing case
  497. //
  498. template<class T>
  499. void test_throwing_swap( T const* )
  500. {
  501. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  502. T a(16);
  503. T b(17);
  504. T x(-1);
  505. optional<T> opt0(a) ;
  506. optional<T> opt1(b) ;
  507. set_throw_on_assign( ARG(T) ) ;
  508. //
  509. // Case 1: Both Initialized.
  510. //
  511. bool passed = false ;
  512. try
  513. {
  514. // This should attempt to swap optionals and fail at swap(X&,X&).
  515. swap(opt0,opt1);
  516. passed = true ;
  517. }
  518. catch ( ... ) {}
  519. BOOST_TEST(!passed);
  520. // optional's swap doesn't affect the initialized states of the arguments. Therefore,
  521. // the following must hold:
  522. check_initialized(opt0);
  523. check_initialized(opt1);
  524. check_value(opt0,x,a);
  525. check_value(opt1,b,x);
  526. //
  527. // Case 2: Only one Initialized.
  528. //
  529. reset_throw_on_assign( ARG(T) ) ;
  530. opt0.reset();
  531. opt1.reset(a);
  532. set_throw_on_copy( ARG(T) ) ;
  533. passed = false ;
  534. try
  535. {
  536. // This should attempt to swap optionals and fail at opt0.reset(*opt1)
  537. // Both opt0 and op1 are left unchanged (unswaped)
  538. swap(opt0,opt1);
  539. passed = true ;
  540. }
  541. catch ( ... ) {}
  542. BOOST_TEST(!passed);
  543. check_uninitialized(opt0);
  544. check_initialized(opt1);
  545. check_value(opt1,a,x);
  546. reset_throw_on_copy( ARG(T) ) ;
  547. }
  548. //
  549. // This verifies relational operators.
  550. //
  551. template<class T>
  552. void test_relops( T const* )
  553. {
  554. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  555. T v0(0);
  556. T v1(1);
  557. T v2(1);
  558. optional<T> def0 ;
  559. optional<T> def1 ;
  560. optional<T> opt0(v0);
  561. optional<T> opt1(v1);
  562. optional<T> opt2(v2);
  563. // Check identity
  564. BOOST_TEST ( def0 == def0 ) ;
  565. BOOST_TEST ( opt0 == opt0 ) ;
  566. BOOST_TEST ( !(def0 != def0) ) ;
  567. BOOST_TEST ( !(opt0 != opt0) ) ;
  568. // Check when both are uininitalized.
  569. BOOST_TEST ( def0 == def1 ) ; // both uninitialized compare equal
  570. BOOST_TEST ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
  571. BOOST_TEST ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
  572. BOOST_TEST ( !(def0 != def1) ) ;
  573. BOOST_TEST ( def0 <= def1 ) ;
  574. BOOST_TEST ( def0 >= def1 ) ;
  575. // Check when only lhs is uninitialized.
  576. BOOST_TEST ( def0 != opt0 ) ; // uninitialized is never equal to initialized
  577. BOOST_TEST ( !(def0 == opt0) ) ;
  578. BOOST_TEST ( def0 < opt0 ) ; // uninitialized is always less than initialized
  579. BOOST_TEST ( !(def0 > opt0) ) ;
  580. BOOST_TEST ( def0 <= opt0 ) ;
  581. BOOST_TEST ( !(def0 >= opt0) ) ;
  582. // Check when only rhs is uninitialized.
  583. BOOST_TEST ( opt0 != def0 ) ; // initialized is never equal to uninitialized
  584. BOOST_TEST ( !(opt0 == def0) ) ;
  585. BOOST_TEST ( !(opt0 < def0) ) ; // initialized is never less than uninitialized
  586. BOOST_TEST ( opt0 > def0 ) ;
  587. BOOST_TEST ( !(opt0 <= def0) ) ;
  588. BOOST_TEST ( opt0 >= opt0 ) ;
  589. // If both are initialized, values are compared
  590. BOOST_TEST ( opt0 != opt1 ) ;
  591. BOOST_TEST ( opt1 == opt2 ) ;
  592. BOOST_TEST ( opt0 < opt1 ) ;
  593. BOOST_TEST ( opt1 > opt0 ) ;
  594. BOOST_TEST ( opt1 <= opt2 ) ;
  595. BOOST_TEST ( opt1 >= opt0 ) ;
  596. // Compare against a value directly
  597. BOOST_TEST ( opt0 == v0 ) ;
  598. BOOST_TEST ( opt0 != v1 ) ;
  599. BOOST_TEST ( opt1 == v2 ) ;
  600. BOOST_TEST ( opt0 < v1 ) ;
  601. BOOST_TEST ( opt1 > v0 ) ;
  602. BOOST_TEST ( opt1 <= v2 ) ;
  603. BOOST_TEST ( opt1 >= v0 ) ;
  604. BOOST_TEST ( v0 != opt1 ) ;
  605. BOOST_TEST ( v1 == opt2 ) ;
  606. BOOST_TEST ( v0 < opt1 ) ;
  607. BOOST_TEST ( v1 > opt0 ) ;
  608. BOOST_TEST ( v1 <= opt2 ) ;
  609. BOOST_TEST ( v1 >= opt0 ) ;
  610. BOOST_TEST ( def0 != v0 ) ;
  611. BOOST_TEST ( !(def0 == v0) ) ;
  612. BOOST_TEST ( def0 < v0 ) ;
  613. BOOST_TEST ( !(def0 > v0) ) ;
  614. BOOST_TEST ( def0 <= v0 ) ;
  615. BOOST_TEST ( !(def0 >= v0) ) ;
  616. BOOST_TEST ( v0 != def0 ) ;
  617. BOOST_TEST ( !(v0 == def0) ) ;
  618. BOOST_TEST ( !(v0 < def0) ) ;
  619. BOOST_TEST ( v0 > def0 ) ;
  620. BOOST_TEST ( !(v0 <= def0) ) ;
  621. BOOST_TEST ( v0 >= opt0 ) ;
  622. }
  623. template<class T>
  624. void test_none( T const* )
  625. {
  626. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  627. using boost::none ;
  628. optional<T> def0 ;
  629. optional<T> def1(none) ;
  630. optional<T> non_def( T(1234) ) ;
  631. BOOST_TEST ( def0 == none ) ;
  632. BOOST_TEST ( non_def != none ) ;
  633. BOOST_TEST ( !def1 ) ;
  634. BOOST_TEST ( !(non_def < none) ) ;
  635. BOOST_TEST ( non_def > none ) ;
  636. BOOST_TEST ( !(non_def <= none) ) ;
  637. BOOST_TEST ( non_def >= none ) ;
  638. non_def = none ;
  639. BOOST_TEST ( !non_def ) ;
  640. test_default_implicit_construction(T(1),none);
  641. }
  642. template<class T>
  643. void test_arrow( T const* )
  644. {
  645. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  646. T a(1234);
  647. optional<T> oa(a) ;
  648. optional<T> const coa(a) ;
  649. BOOST_TEST ( coa->V() == 1234 ) ;
  650. oa->V() = 4321 ;
  651. BOOST_TEST ( a.V() = 1234 ) ;
  652. BOOST_TEST ( (*oa).V() = 4321 ) ;
  653. }
  654. void test_with_builtin_types()
  655. {
  656. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  657. test_basics( ARG(double) );
  658. test_conditional_ctor_and_get_valur_or( ARG(double) );
  659. test_uninitialized_access( ARG(double) );
  660. test_no_throwing_swap( ARG(double) );
  661. test_relops( ARG(double) ) ;
  662. test_none( ARG(double) ) ;
  663. }
  664. // MSVC < 11.0 doesn't destroy X when we call ptr->VBase::VBase.
  665. // Make sure that we work around this bug.
  666. struct VBase : virtual X
  667. {
  668. VBase(int v) : X(v) {}
  669. // MSVC 8.0 doesn't generate this correctly...
  670. VBase(const VBase& other) : X(static_cast<const X&>(other)) {}
  671. };
  672. void test_with_class_type()
  673. {
  674. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  675. test_basics( ARG(X) );
  676. test_basics( ARG(VBase) );
  677. test_conditional_ctor_and_get_valur_or( ARG(X) );
  678. test_direct_value_manip( ARG(X) );
  679. test_uninitialized_access( ARG(X) );
  680. test_throwing_direct_init( ARG(X) );
  681. test_throwing_val_assign_on_uninitialized( ARG(X) );
  682. test_throwing_val_assign_on_initialized( ARG(X) );
  683. test_throwing_copy_initialization( ARG(X) );
  684. test_throwing_assign_to_uninitialized( ARG(X) );
  685. test_throwing_assign_to_initialized( ARG(X) );
  686. test_no_throwing_swap( ARG(X) );
  687. test_throwing_swap( ARG(X) );
  688. test_relops( ARG(X) ) ;
  689. test_none( ARG(X) ) ;
  690. test_arrow( ARG(X) ) ;
  691. BOOST_TEST ( X::count == 0 ) ;
  692. }
  693. int eat ( bool ) { return 1 ; }
  694. int eat ( char ) { return 1 ; }
  695. int eat ( int ) { return 1 ; }
  696. int eat ( void const* ) { return 1 ; }
  697. template<class T> int eat ( T ) { return 0 ; }
  698. //
  699. // This verifies that operator safe_bool() behaves properly.
  700. //
  701. template<class T>
  702. void test_no_implicit_conversions_impl( T const& )
  703. {
  704. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  705. optional<T> def ;
  706. BOOST_TEST ( eat(def) == 0 ) ;
  707. }
  708. void test_no_implicit_conversions()
  709. {
  710. TRACE( std::endl << BOOST_CURRENT_FUNCTION );
  711. bool b = false ;
  712. char c = 0 ;
  713. int i = 0 ;
  714. void const* p = 0 ;
  715. test_no_implicit_conversions_impl(b);
  716. test_no_implicit_conversions_impl(c);
  717. test_no_implicit_conversions_impl(i);
  718. test_no_implicit_conversions_impl(p);
  719. }
  720. // Test for support for classes with overridden operator&
  721. class CustomAddressOfClass
  722. {
  723. int n;
  724. public:
  725. CustomAddressOfClass() : n(0) {}
  726. CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {}
  727. explicit CustomAddressOfClass(int m) : n(m) {}
  728. int* operator& () { return &n; }
  729. bool operator== (CustomAddressOfClass const& that) const { return n == that.n; }
  730. };
  731. void test_custom_addressof_operator()
  732. {
  733. boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10));
  734. BOOST_TEST(!!o1);
  735. BOOST_TEST(o1.get() == CustomAddressOfClass(10));
  736. o1 = CustomAddressOfClass(20);
  737. BOOST_TEST(!!o1);
  738. BOOST_TEST(o1.get() == CustomAddressOfClass(20));
  739. o1 = boost::none;
  740. BOOST_TEST(!o1);
  741. }
  742. int main()
  743. {
  744. try
  745. {
  746. test_with_class_type();
  747. test_with_builtin_types();
  748. test_no_implicit_conversions();
  749. test_custom_addressof_operator();
  750. }
  751. catch ( ... )
  752. {
  753. BOOST_ERROR("Unexpected Exception caught!");
  754. }
  755. return boost::report_errors();
  756. }