old_optional_implementation.hpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
  2. // Copyright (C) 2014-2016 Andrzej Krzemienski.
  3. //
  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. //
  8. // See http://www.boost.org/libs/optional for documentation.
  9. //
  10. // You are welcome to contact the maintainer at:
  11. // akrzemi1@gmail.com
  12. #ifndef BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
  13. #define BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
  14. #include <boost/detail/reference_content.hpp>
  15. #include <boost/type_traits/is_reference.hpp>
  16. #include <boost/type_traits/integral_constant.hpp>
  17. #include <boost/type_traits/conditional.hpp>
  18. namespace boost {
  19. namespace optional_detail {
  20. template<class T>
  21. struct types_when_isnt_ref
  22. {
  23. typedef T const& reference_const_type ;
  24. typedef T & reference_type ;
  25. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  26. typedef T && rval_reference_type ;
  27. typedef T && reference_type_of_temporary_wrapper;
  28. #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
  29. // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
  30. // causes warnings about returning references to a temporary.
  31. static T&& move(T&& r) { return r; }
  32. #else
  33. static rval_reference_type move(reference_type r) { return boost::move(r); }
  34. #endif
  35. #endif
  36. typedef T const* pointer_const_type ;
  37. typedef T * pointer_type ;
  38. typedef T const& argument_type ;
  39. } ;
  40. template<class T>
  41. struct types_when_is_ref
  42. {
  43. typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
  44. typedef raw_type& reference_const_type ;
  45. typedef raw_type& reference_type ;
  46. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  47. typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
  48. typedef raw_type& reference_type_of_temporary_wrapper;
  49. static reference_type move(reference_type r) { return r; }
  50. #endif
  51. typedef raw_type* pointer_const_type ;
  52. typedef raw_type* pointer_type ;
  53. typedef raw_type& argument_type ;
  54. } ;
  55. template <class To, class From>
  56. void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
  57. {
  58. #ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
  59. BOOST_STATIC_ASSERT_MSG(
  60. !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value,
  61. "binding rvalue references to optional lvalue references is disallowed");
  62. #endif
  63. }
  64. struct optional_tag {} ;
  65. template<class T>
  66. class optional_base : public optional_tag
  67. {
  68. private :
  69. typedef
  70. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  71. BOOST_DEDUCED_TYPENAME
  72. #endif
  73. ::boost::detail::make_reference_content<T>::type internal_type ;
  74. typedef aligned_storage<internal_type> storage_type ;
  75. typedef types_when_isnt_ref<T> types_when_not_ref ;
  76. typedef types_when_is_ref<T> types_when_ref ;
  77. typedef optional_base<T> this_type ;
  78. protected :
  79. typedef T value_type ;
  80. typedef true_type is_reference_tag ;
  81. typedef false_type is_not_reference_tag ;
  82. typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
  83. public:
  84. typedef BOOST_DEDUCED_TYPENAME conditional<is_reference_predicate::value,types_when_ref,types_when_not_ref>::type types ;
  85. protected:
  86. typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
  87. typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
  88. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  89. typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
  90. typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
  91. #endif
  92. typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
  93. typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
  94. typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
  95. // Creates an optional<T> uninitialized.
  96. // No-throw
  97. optional_base()
  98. :
  99. m_initialized(false) {}
  100. // Creates an optional<T> uninitialized.
  101. // No-throw
  102. optional_base ( none_t )
  103. :
  104. m_initialized(false) {}
  105. // Creates an optional<T> initialized with 'val'.
  106. // Can throw if T::T(T const&) does
  107. optional_base ( argument_type val )
  108. :
  109. m_initialized(false)
  110. {
  111. construct(val);
  112. }
  113. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  114. // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
  115. // Can throw if T::T(T&&) does
  116. optional_base ( rval_reference_type val )
  117. :
  118. m_initialized(false)
  119. {
  120. construct( boost::move(val) );
  121. }
  122. #endif
  123. // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional<T>.
  124. // Can throw if T::T(T const&) does
  125. optional_base ( bool cond, argument_type val )
  126. :
  127. m_initialized(false)
  128. {
  129. if ( cond )
  130. construct(val);
  131. }
  132. // Creates a deep copy of another optional<T>
  133. // Can throw if T::T(T const&) does
  134. optional_base ( optional_base const& rhs )
  135. :
  136. m_initialized(false)
  137. {
  138. if ( rhs.is_initialized() )
  139. construct(rhs.get_impl());
  140. }
  141. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  142. // Creates a deep move of another optional<T>
  143. // Can throw if T::T(T&&) does
  144. optional_base ( optional_base&& rhs )
  145. :
  146. m_initialized(false)
  147. {
  148. if ( rhs.is_initialized() )
  149. construct( boost::move(rhs.get_impl()) );
  150. }
  151. #endif
  152. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  153. template<class Expr, class PtrExpr>
  154. explicit optional_base ( Expr&& expr, PtrExpr const* tag )
  155. :
  156. m_initialized(false)
  157. {
  158. construct(boost::forward<Expr>(expr),tag);
  159. }
  160. #else
  161. // This is used for both converting and in-place constructions.
  162. // Derived classes use the 'tag' to select the appropriate
  163. // implementation (the correct 'construct()' overload)
  164. template<class Expr>
  165. explicit optional_base ( Expr const& expr, Expr const* tag )
  166. :
  167. m_initialized(false)
  168. {
  169. construct(expr,tag);
  170. }
  171. #endif
  172. // No-throw (assuming T::~T() doesn't)
  173. ~optional_base() { destroy() ; }
  174. // Assigns from another optional<T> (deep-copies the rhs value)
  175. void assign ( optional_base const& rhs )
  176. {
  177. if (is_initialized())
  178. {
  179. if ( rhs.is_initialized() )
  180. assign_value(rhs.get_impl(), is_reference_predicate() );
  181. else destroy();
  182. }
  183. else
  184. {
  185. if ( rhs.is_initialized() )
  186. construct(rhs.get_impl());
  187. }
  188. }
  189. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  190. // Assigns from another optional<T> (deep-moves the rhs value)
  191. void assign ( optional_base&& rhs )
  192. {
  193. if (is_initialized())
  194. {
  195. if ( rhs.is_initialized() )
  196. assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
  197. else destroy();
  198. }
  199. else
  200. {
  201. if ( rhs.is_initialized() )
  202. construct(boost::move(rhs.get_impl()));
  203. }
  204. }
  205. #endif
  206. // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
  207. template<class U>
  208. void assign ( optional<U> const& rhs )
  209. {
  210. if (is_initialized())
  211. {
  212. if ( rhs.is_initialized() )
  213. #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
  214. assign_value(rhs.get(), is_reference_predicate() );
  215. #else
  216. assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
  217. #endif
  218. else destroy();
  219. }
  220. else
  221. {
  222. if ( rhs.is_initialized() )
  223. #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
  224. construct(rhs.get());
  225. #else
  226. construct(static_cast<value_type>(rhs.get()));
  227. #endif
  228. }
  229. }
  230. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  231. // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
  232. template<class U>
  233. void assign ( optional<U>&& rhs )
  234. {
  235. typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
  236. if (is_initialized())
  237. {
  238. if ( rhs.is_initialized() )
  239. assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
  240. else destroy();
  241. }
  242. else
  243. {
  244. if ( rhs.is_initialized() )
  245. construct(static_cast<ref_type>(rhs.get()));
  246. }
  247. }
  248. #endif
  249. // Assigns from a T (deep-copies the rhs value)
  250. void assign ( argument_type val )
  251. {
  252. if (is_initialized())
  253. assign_value(val, is_reference_predicate() );
  254. else construct(val);
  255. }
  256. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  257. // Assigns from a T (deep-moves the rhs value)
  258. void assign ( rval_reference_type val )
  259. {
  260. if (is_initialized())
  261. assign_value( boost::move(val), is_reference_predicate() );
  262. else construct( boost::move(val) );
  263. }
  264. #endif
  265. // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
  266. // No-throw (assuming T::~T() doesn't)
  267. void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
  268. #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  269. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  270. template<class Expr, class ExprPtr>
  271. void assign_expr ( Expr&& expr, ExprPtr const* tag )
  272. {
  273. if (is_initialized())
  274. assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
  275. else construct(boost::forward<Expr>(expr),tag);
  276. }
  277. #else
  278. template<class Expr>
  279. void assign_expr ( Expr const& expr, Expr const* tag )
  280. {
  281. if (is_initialized())
  282. assign_expr_to_initialized(expr,tag);
  283. else construct(expr,tag);
  284. }
  285. #endif
  286. #endif
  287. public :
  288. // Destroys the current value, if any, leaving this UNINITIALIZED
  289. // No-throw (assuming T::~T() doesn't)
  290. void reset() BOOST_NOEXCEPT { destroy(); }
  291. // **DEPPRECATED** Replaces the current value -if any- with 'val'
  292. void reset ( argument_type val ) { assign(val); }
  293. // Returns a pointer to the value if this is initialized, otherwise,
  294. // returns NULL.
  295. // No-throw
  296. pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
  297. pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
  298. bool is_initialized() const { return m_initialized ; }
  299. protected :
  300. void construct ( argument_type val )
  301. {
  302. ::new (m_storage.address()) internal_type(val) ;
  303. m_initialized = true ;
  304. }
  305. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  306. void construct ( rval_reference_type val )
  307. {
  308. ::new (m_storage.address()) internal_type( types::move(val) ) ;
  309. m_initialized = true ;
  310. }
  311. #endif
  312. #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  313. // Constructs in-place
  314. // upon exception *this is always uninitialized
  315. template<class... Args>
  316. void emplace_assign ( Args&&... args )
  317. {
  318. destroy();
  319. ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
  320. m_initialized = true ;
  321. }
  322. #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
  323. template<class Arg>
  324. void emplace_assign ( Arg&& arg )
  325. {
  326. destroy();
  327. ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
  328. m_initialized = true ;
  329. }
  330. void emplace_assign ()
  331. {
  332. destroy();
  333. ::new (m_storage.address()) internal_type();
  334. m_initialized = true ;
  335. }
  336. #else
  337. template<class Arg>
  338. void emplace_assign ( const Arg& arg )
  339. {
  340. destroy();
  341. ::new (m_storage.address()) internal_type( arg );
  342. m_initialized = true ;
  343. }
  344. template<class Arg>
  345. void emplace_assign ( Arg& arg )
  346. {
  347. destroy();
  348. ::new (m_storage.address()) internal_type( arg );
  349. m_initialized = true ;
  350. }
  351. void emplace_assign ()
  352. {
  353. destroy();
  354. ::new (m_storage.address()) internal_type();
  355. m_initialized = true ;
  356. }
  357. #endif
  358. #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  359. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  360. // Constructs in-place using the given factory
  361. template<class Expr>
  362. void construct ( Expr&& factory, in_place_factory_base const* )
  363. {
  364. BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
  365. boost_optional_detail::construct<value_type>(factory, m_storage.address());
  366. m_initialized = true ;
  367. }
  368. // Constructs in-place using the given typed factory
  369. template<class Expr>
  370. void construct ( Expr&& factory, typed_in_place_factory_base const* )
  371. {
  372. BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
  373. factory.apply(m_storage.address()) ;
  374. m_initialized = true ;
  375. }
  376. template<class Expr>
  377. void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
  378. {
  379. destroy();
  380. construct(factory,tag);
  381. }
  382. // Constructs in-place using the given typed factory
  383. template<class Expr>
  384. void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
  385. {
  386. destroy();
  387. construct(factory,tag);
  388. }
  389. #else
  390. // Constructs in-place using the given factory
  391. template<class Expr>
  392. void construct ( Expr const& factory, in_place_factory_base const* )
  393. {
  394. BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
  395. boost_optional_detail::construct<value_type>(factory, m_storage.address());
  396. m_initialized = true ;
  397. }
  398. // Constructs in-place using the given typed factory
  399. template<class Expr>
  400. void construct ( Expr const& factory, typed_in_place_factory_base const* )
  401. {
  402. BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
  403. factory.apply(m_storage.address()) ;
  404. m_initialized = true ;
  405. }
  406. template<class Expr>
  407. void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
  408. {
  409. destroy();
  410. construct(factory,tag);
  411. }
  412. // Constructs in-place using the given typed factory
  413. template<class Expr>
  414. void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
  415. {
  416. destroy();
  417. construct(factory,tag);
  418. }
  419. #endif
  420. #endif
  421. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  422. // Constructs using any expression implicitly convertible to the single argument
  423. // of a one-argument T constructor.
  424. // Converting constructions of optional<T> from optional<U> uses this function with
  425. // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
  426. template<class Expr>
  427. void construct ( Expr&& expr, void const* )
  428. {
  429. new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
  430. m_initialized = true ;
  431. }
  432. // Assigns using a form any expression implicitly convertible to the single argument
  433. // of a T's assignment operator.
  434. // Converting assignments of optional<T> from optional<U> uses this function with
  435. // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
  436. template<class Expr>
  437. void assign_expr_to_initialized ( Expr&& expr, void const* )
  438. {
  439. assign_value(boost::forward<Expr>(expr), is_reference_predicate());
  440. }
  441. #else
  442. // Constructs using any expression implicitly convertible to the single argument
  443. // of a one-argument T constructor.
  444. // Converting constructions of optional<T> from optional<U> uses this function with
  445. // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
  446. template<class Expr>
  447. void construct ( Expr const& expr, void const* )
  448. {
  449. new (m_storage.address()) internal_type(expr) ;
  450. m_initialized = true ;
  451. }
  452. // Assigns using a form any expression implicitly convertible to the single argument
  453. // of a T's assignment operator.
  454. // Converting assignments of optional<T> from optional<U> uses this function with
  455. // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
  456. template<class Expr>
  457. void assign_expr_to_initialized ( Expr const& expr, void const* )
  458. {
  459. assign_value(expr, is_reference_predicate());
  460. }
  461. #endif
  462. #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
  463. // BCB5.64 (and probably lower versions) workaround.
  464. // The in-place factories are supported by means of catch-all constructors
  465. // and assignment operators (the functions are parameterized in terms of
  466. // an arbitrary 'Expr' type)
  467. // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
  468. // to the 'Expr'-taking functions even though explicit overloads are present for them.
  469. // Thus, the following overload is needed to properly handle the case when the 'lhs'
  470. // is another optional.
  471. //
  472. // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
  473. // instead of choosing the wrong overload
  474. //
  475. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  476. // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
  477. template<class Expr>
  478. void construct ( Expr&& expr, optional_tag const* )
  479. {
  480. if ( expr.is_initialized() )
  481. {
  482. // An exception can be thrown here.
  483. // It it happens, THIS will be left uninitialized.
  484. new (m_storage.address()) internal_type(types::move(expr.get())) ;
  485. m_initialized = true ;
  486. }
  487. }
  488. #else
  489. // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
  490. template<class Expr>
  491. void construct ( Expr const& expr, optional_tag const* )
  492. {
  493. if ( expr.is_initialized() )
  494. {
  495. // An exception can be thrown here.
  496. // It it happens, THIS will be left uninitialized.
  497. new (m_storage.address()) internal_type(expr.get()) ;
  498. m_initialized = true ;
  499. }
  500. }
  501. #endif
  502. #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
  503. void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
  504. void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
  505. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  506. void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
  507. void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); }
  508. #endif
  509. void destroy()
  510. {
  511. if ( m_initialized )
  512. destroy_impl(is_reference_predicate()) ;
  513. }
  514. reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
  515. reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
  516. pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
  517. pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
  518. private :
  519. // internal_type can be either T or reference_content<T>
  520. #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
  521. // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
  522. internal_type const* get_object() const
  523. {
  524. union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
  525. return caster.as_ptype;
  526. }
  527. internal_type * get_object()
  528. {
  529. union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
  530. return caster.as_ptype;
  531. }
  532. #else
  533. internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
  534. internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
  535. #endif
  536. // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
  537. reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
  538. reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
  539. reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
  540. reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
  541. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
  542. void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
  543. #else
  544. void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
  545. #endif
  546. void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
  547. // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
  548. // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
  549. // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
  550. pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
  551. pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
  552. pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
  553. pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
  554. bool m_initialized ;
  555. storage_type m_storage ;
  556. } ;
  557. } // namespace optional_detail
  558. template<class T>
  559. class optional : public optional_detail::optional_base<T>
  560. {
  561. typedef optional_detail::optional_base<T> base ;
  562. public :
  563. typedef optional<T> this_type ;
  564. typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
  565. typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
  566. typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
  567. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  568. typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
  569. typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
  570. #endif
  571. typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
  572. typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
  573. typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
  574. // Creates an optional<T> uninitialized.
  575. // No-throw
  576. optional() BOOST_NOEXCEPT : base() {}
  577. // Creates an optional<T> uninitialized.
  578. // No-throw
  579. optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
  580. // Creates an optional<T> initialized with 'val'.
  581. // Can throw if T::T(T const&) does
  582. optional ( argument_type val ) : base(val) {}
  583. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  584. // Creates an optional<T> initialized with 'move(val)'.
  585. // Can throw if T::T(T &&) does
  586. optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
  587. {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
  588. #endif
  589. // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
  590. // Can throw if T::T(T const&) does
  591. optional ( bool cond, argument_type val ) : base(cond,val) {}
  592. // NOTE: MSVC needs templated versions first
  593. // Creates a deep copy of another convertible optional<U>
  594. // Requires a valid conversion from U to T.
  595. // Can throw if T::T(U const&) does
  596. template<class U>
  597. explicit optional ( optional<U> const& rhs )
  598. :
  599. base()
  600. {
  601. if ( rhs.is_initialized() )
  602. this->construct(rhs.get());
  603. }
  604. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  605. // Creates a deep move of another convertible optional<U>
  606. // Requires a valid conversion from U to T.
  607. // Can throw if T::T(U&&) does
  608. template<class U>
  609. explicit optional ( optional<U> && rhs )
  610. :
  611. base()
  612. {
  613. if ( rhs.is_initialized() )
  614. this->construct( boost::move(rhs.get()) );
  615. }
  616. #endif
  617. #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  618. // Creates an optional<T> with an expression which can be either
  619. // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
  620. // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
  621. // (c) Any expression implicitly convertible to the single type
  622. // of a one-argument T's constructor.
  623. // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
  624. // even though explicit overloads are present for these.
  625. // Depending on the above some T ctor is called.
  626. // Can throw if the resolved T ctor throws.
  627. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  628. template<class Expr>
  629. explicit optional ( Expr&& expr,
  630. BOOST_DEDUCED_TYPENAME boost::disable_if_c<
  631. (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
  632. boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value, bool >::type = true
  633. )
  634. : base(boost::forward<Expr>(expr),boost::addressof(expr))
  635. {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
  636. #else
  637. template<class Expr>
  638. explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
  639. #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  640. #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  641. // Creates a deep copy of another optional<T>
  642. // Can throw if T::T(T const&) does
  643. optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
  644. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  645. // Creates a deep move of another optional<T>
  646. // Can throw if T::T(T&&) does
  647. optional ( optional && rhs )
  648. BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
  649. : base( boost::move(rhs) )
  650. {}
  651. #endif
  652. // No-throw (assuming T::~T() doesn't)
  653. ~optional() {}
  654. #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
  655. // Assigns from an expression. See corresponding constructor.
  656. // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
  657. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  658. template<class Expr>
  659. BOOST_DEDUCED_TYPENAME boost::disable_if_c<
  660. boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
  661. boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
  662. optional&
  663. >::type
  664. operator= ( Expr&& expr )
  665. {
  666. optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
  667. this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
  668. return *this ;
  669. }
  670. #else
  671. template<class Expr>
  672. optional& operator= ( Expr const& expr )
  673. {
  674. this->assign_expr(expr,boost::addressof(expr));
  675. return *this ;
  676. }
  677. #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  678. #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
  679. // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
  680. // Requires a valid conversion from U to T.
  681. // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
  682. template<class U>
  683. optional& operator= ( optional<U> const& rhs )
  684. {
  685. this->assign(rhs);
  686. return *this ;
  687. }
  688. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  689. // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
  690. // Requires a valid conversion from U to T.
  691. // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
  692. template<class U>
  693. optional& operator= ( optional<U> && rhs )
  694. {
  695. this->assign(boost::move(rhs));
  696. return *this ;
  697. }
  698. #endif
  699. // Assigns from another optional<T> (deep-copies the rhs value)
  700. // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
  701. // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
  702. optional& operator= ( optional const& rhs )
  703. {
  704. this->assign( static_cast<base const&>(rhs) ) ;
  705. return *this ;
  706. }
  707. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  708. // Assigns from another optional<T> (deep-moves the rhs value)
  709. optional& operator= ( optional && rhs )
  710. BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
  711. {
  712. this->assign( static_cast<base &&>(rhs) ) ;
  713. return *this ;
  714. }
  715. #endif
  716. // Assigns from a T (deep-copies the rhs value)
  717. // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
  718. optional& operator= ( argument_type val )
  719. {
  720. this->assign( val ) ;
  721. return *this ;
  722. }
  723. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  724. // Assigns from a T (deep-moves the rhs value)
  725. optional& operator= ( rval_reference_type val )
  726. {
  727. optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
  728. this->assign( boost::move(val) ) ;
  729. return *this ;
  730. }
  731. #endif
  732. // Assigns from a "none"
  733. // Which destroys the current value, if any, leaving this UNINITIALIZED
  734. // No-throw (assuming T::~T() doesn't)
  735. optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
  736. {
  737. this->assign( none_ ) ;
  738. return *this ;
  739. }
  740. #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  741. // Constructs in-place
  742. // upon exception *this is always uninitialized
  743. template<class... Args>
  744. void emplace ( Args&&... args )
  745. {
  746. this->emplace_assign( boost::forward<Args>(args)... );
  747. }
  748. #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
  749. template<class Arg>
  750. void emplace ( Arg&& arg )
  751. {
  752. this->emplace_assign( boost::forward<Arg>(arg) );
  753. }
  754. void emplace ()
  755. {
  756. this->emplace_assign();
  757. }
  758. #else
  759. template<class Arg>
  760. void emplace ( const Arg& arg )
  761. {
  762. this->emplace_assign( arg );
  763. }
  764. template<class Arg>
  765. void emplace ( Arg& arg )
  766. {
  767. this->emplace_assign( arg );
  768. }
  769. void emplace ()
  770. {
  771. this->emplace_assign();
  772. }
  773. #endif
  774. void swap( optional & arg )
  775. BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
  776. {
  777. // allow for Koenig lookup
  778. boost::swap(*this, arg);
  779. }
  780. // Returns a reference to the value if this is initialized, otherwise,
  781. // the behaviour is UNDEFINED
  782. // No-throw
  783. reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
  784. reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
  785. // Returns a copy of the value if this is initialized, 'v' otherwise
  786. reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
  787. reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
  788. // Returns a pointer to the value if this is initialized, otherwise,
  789. // the behaviour is UNDEFINED
  790. // No-throw
  791. pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
  792. pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
  793. // Returns a reference to the value if this is initialized, otherwise,
  794. // the behaviour is UNDEFINED
  795. // No-throw
  796. #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
  797. reference_const_type operator *() const& { return this->get() ; }
  798. reference_type operator *() & { return this->get() ; }
  799. reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; }
  800. #else
  801. reference_const_type operator *() const { return this->get() ; }
  802. reference_type operator *() { return this->get() ; }
  803. #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
  804. #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
  805. reference_const_type value() const&
  806. {
  807. if (this->is_initialized())
  808. return this->get() ;
  809. else
  810. throw_exception(bad_optional_access());
  811. }
  812. reference_type value() &
  813. {
  814. if (this->is_initialized())
  815. return this->get() ;
  816. else
  817. throw_exception(bad_optional_access());
  818. }
  819. reference_type_of_temporary_wrapper value() &&
  820. {
  821. if (this->is_initialized())
  822. return base::types::move(this->get()) ;
  823. else
  824. throw_exception(bad_optional_access());
  825. }
  826. #else
  827. reference_const_type value() const
  828. {
  829. if (this->is_initialized())
  830. return this->get() ;
  831. else
  832. throw_exception(bad_optional_access());
  833. }
  834. reference_type value()
  835. {
  836. if (this->is_initialized())
  837. return this->get() ;
  838. else
  839. throw_exception(bad_optional_access());
  840. }
  841. #endif
  842. #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
  843. template <class U>
  844. value_type value_or ( U&& v ) const&
  845. {
  846. if (this->is_initialized())
  847. return get();
  848. else
  849. return boost::forward<U>(v);
  850. }
  851. template <class U>
  852. value_type value_or ( U&& v ) &&
  853. {
  854. if (this->is_initialized())
  855. return base::types::move(get());
  856. else
  857. return boost::forward<U>(v);
  858. }
  859. #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  860. template <class U>
  861. value_type value_or ( U&& v ) const
  862. {
  863. if (this->is_initialized())
  864. return get();
  865. else
  866. return boost::forward<U>(v);
  867. }
  868. #else
  869. template <class U>
  870. value_type value_or ( U const& v ) const
  871. {
  872. if (this->is_initialized())
  873. return get();
  874. else
  875. return v;
  876. }
  877. template <class U>
  878. value_type value_or ( U& v ) const
  879. {
  880. if (this->is_initialized())
  881. return get();
  882. else
  883. return v;
  884. }
  885. #endif
  886. #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
  887. template <typename F>
  888. value_type value_or_eval ( F f ) const&
  889. {
  890. if (this->is_initialized())
  891. return get();
  892. else
  893. return f();
  894. }
  895. template <typename F>
  896. value_type value_or_eval ( F f ) &&
  897. {
  898. if (this->is_initialized())
  899. return base::types::move(get());
  900. else
  901. return f();
  902. }
  903. #else
  904. template <typename F>
  905. value_type value_or_eval ( F f ) const
  906. {
  907. if (this->is_initialized())
  908. return get();
  909. else
  910. return f();
  911. }
  912. #endif
  913. bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
  914. BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
  915. } ;
  916. } // namespace boost
  917. #endif // header guard