optional.hpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  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/libs/optional for documentation.
  8. //
  9. // You are welcome to contact the author at:
  10. // fernando_cacciola@hotmail.com
  11. //
  12. // Revisions:
  13. // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
  14. //
  15. #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
  16. #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
  17. #include <new>
  18. #include <algorithm>
  19. #include <boost/config.hpp>
  20. #include <boost/assert.hpp>
  21. #include <boost/type.hpp>
  22. #include <boost/type_traits/alignment_of.hpp>
  23. #include <boost/type_traits/has_nothrow_constructor.hpp>
  24. #include <boost/type_traits/type_with_alignment.hpp>
  25. #include <boost/type_traits/remove_reference.hpp>
  26. #include <boost/type_traits/is_reference.hpp>
  27. #include <boost/mpl/if.hpp>
  28. #include <boost/mpl/bool.hpp>
  29. #include <boost/mpl/not.hpp>
  30. #include <boost/detail/reference_content.hpp>
  31. #include <boost/none.hpp>
  32. #include <boost/utility/swap.hpp>
  33. #include <boost/utility/addressof.hpp>
  34. #include <boost/utility/compare_pointees.hpp>
  35. #include <boost/utility/in_place_factory.hpp>
  36. #include <boost/optional/optional_fwd.hpp>
  37. #if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
  38. // VC6.0 has the following bug:
  39. // When a templated assignment operator exist, an implicit conversion
  40. // constructing an optional<T> is used when assigment of the form:
  41. // optional<T> opt ; opt = T(...);
  42. // is compiled.
  43. // However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
  44. // Therefore, for VC6.0 templated assignment is disabled.
  45. //
  46. #define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
  47. #endif
  48. #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
  49. // VC7.0 has the following bug:
  50. // When both a non-template and a template copy-ctor exist
  51. // and the templated version is made 'explicit', the explicit is also
  52. // given to the non-templated version, making the class non-implicitely-copyable.
  53. //
  54. #define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
  55. #endif
  56. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
  57. // AFAICT only VC7.1 correctly resolves the overload set
  58. // that includes the in-place factory taking functions,
  59. // so for the other VC versions, in-place factory support
  60. // is disabled
  61. #define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  62. #endif
  63. #if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
  64. // BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
  65. #define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  66. #endif
  67. #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
  68. && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581) )
  69. // BCB (up to 5.64) has the following bug:
  70. // If there is a member function/operator template of the form
  71. // template<class Expr> mfunc( Expr expr ) ;
  72. // some calls are resolved to this even if there are other better matches.
  73. // The effect of this bug is that calls to converting ctors and assignments
  74. // are incrorrectly sink to this general catch-all member function template as shown above.
  75. #define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
  76. #endif
  77. #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
  78. && !defined(__INTEL_COMPILER)
  79. // GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
  80. // regard to violation of the strict aliasing rules. The optional< T > storage type is marked
  81. // with this attribute in order to let the compiler know that it will alias objects of type T
  82. // and silence compilation warnings.
  83. #define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
  84. #endif
  85. // Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
  86. // member template of a factory as used in the optional<> implementation.
  87. // He proposed this simple fix which is to move the call to apply<> outside
  88. // namespace boost.
  89. namespace boost_optional_detail
  90. {
  91. template <class T, class Factory>
  92. inline void construct(Factory const& factory, void* address)
  93. {
  94. factory.BOOST_NESTED_TEMPLATE apply<T>(address);
  95. }
  96. }
  97. namespace boost {
  98. class in_place_factory_base ;
  99. class typed_in_place_factory_base ;
  100. // This forward is needed to refer to namespace scope swap from the member swap
  101. template<class T> void swap ( optional<T>& x, optional<T>& y );
  102. namespace optional_detail {
  103. // This local class is used instead of that in "aligned_storage.hpp"
  104. // because I've found the 'official' class to ICE BCB5.5
  105. // when some types are used with optional<>
  106. // (due to sizeof() passed down as a non-type template parameter)
  107. template <class T>
  108. class aligned_storage
  109. {
  110. // Borland ICEs if unnamed unions are used for this!
  111. union
  112. // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
  113. #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
  114. __attribute__((may_alias))
  115. #endif
  116. dummy_u
  117. {
  118. char data[ sizeof(T) ];
  119. BOOST_DEDUCED_TYPENAME type_with_alignment<
  120. ::boost::alignment_of<T>::value >::type aligner_;
  121. } dummy_ ;
  122. public:
  123. #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
  124. void const* address() const { return &dummy_; }
  125. void * address() { return &dummy_; }
  126. #else
  127. void const* address() const { return dummy_.data; }
  128. void * address() { return dummy_.data; }
  129. #endif
  130. } ;
  131. template<class T>
  132. struct types_when_isnt_ref
  133. {
  134. typedef T const& reference_const_type ;
  135. typedef T & reference_type ;
  136. typedef T const* pointer_const_type ;
  137. typedef T * pointer_type ;
  138. typedef T const& argument_type ;
  139. } ;
  140. template<class T>
  141. struct types_when_is_ref
  142. {
  143. typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
  144. typedef raw_type& reference_const_type ;
  145. typedef raw_type& reference_type ;
  146. typedef raw_type* pointer_const_type ;
  147. typedef raw_type* pointer_type ;
  148. typedef raw_type& argument_type ;
  149. } ;
  150. struct optional_tag {} ;
  151. template<class T>
  152. class optional_base : public optional_tag
  153. {
  154. private :
  155. typedef
  156. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  157. BOOST_DEDUCED_TYPENAME
  158. #endif
  159. ::boost::detail::make_reference_content<T>::type internal_type ;
  160. typedef aligned_storage<internal_type> storage_type ;
  161. typedef types_when_isnt_ref<T> types_when_not_ref ;
  162. typedef types_when_is_ref<T> types_when_ref ;
  163. typedef optional_base<T> this_type ;
  164. protected :
  165. typedef T value_type ;
  166. typedef mpl::true_ is_reference_tag ;
  167. typedef mpl::false_ is_not_reference_tag ;
  168. typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
  169. public:
  170. typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
  171. protected:
  172. typedef bool (this_type::*unspecified_bool_type)() const;
  173. typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
  174. typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
  175. typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
  176. typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
  177. typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
  178. // Creates an optional<T> uninitialized.
  179. // No-throw
  180. optional_base()
  181. :
  182. m_initialized(false) {}
  183. // Creates an optional<T> uninitialized.
  184. // No-throw
  185. optional_base ( none_t )
  186. :
  187. m_initialized(false) {}
  188. // Creates an optional<T> initialized with 'val'.
  189. // Can throw if T::T(T const&) does
  190. optional_base ( argument_type val )
  191. :
  192. m_initialized(false)
  193. {
  194. construct(val);
  195. }
  196. // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
  197. // Can throw if T::T(T const&) does
  198. optional_base ( bool cond, argument_type val )
  199. :
  200. m_initialized(false)
  201. {
  202. if ( cond )
  203. construct(val);
  204. }
  205. // Creates a deep copy of another optional<T>
  206. // Can throw if T::T(T const&) does
  207. optional_base ( optional_base const& rhs )
  208. :
  209. m_initialized(false)
  210. {
  211. if ( rhs.is_initialized() )
  212. construct(rhs.get_impl());
  213. }
  214. // This is used for both converting and in-place constructions.
  215. // Derived classes use the 'tag' to select the appropriate
  216. // implementation (the correct 'construct()' overload)
  217. template<class Expr>
  218. explicit optional_base ( Expr const& expr, Expr const* tag )
  219. :
  220. m_initialized(false)
  221. {
  222. construct(expr,tag);
  223. }
  224. // No-throw (assuming T::~T() doesn't)
  225. ~optional_base() { destroy() ; }
  226. // Assigns from another optional<T> (deep-copies the rhs value)
  227. void assign ( optional_base const& rhs )
  228. {
  229. if (is_initialized())
  230. {
  231. if ( rhs.is_initialized() )
  232. assign_value(rhs.get_impl(), is_reference_predicate() );
  233. else destroy();
  234. }
  235. else
  236. {
  237. if ( rhs.is_initialized() )
  238. construct(rhs.get_impl());
  239. }
  240. }
  241. // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
  242. template<class U>
  243. void assign ( optional<U> const& rhs )
  244. {
  245. if (is_initialized())
  246. {
  247. if ( rhs.is_initialized() )
  248. assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
  249. else destroy();
  250. }
  251. else
  252. {
  253. if ( rhs.is_initialized() )
  254. construct(static_cast<value_type>(rhs.get()));
  255. }
  256. }
  257. // Assigns from a T (deep-copies the rhs value)
  258. void assign ( argument_type val )
  259. {
  260. if (is_initialized())
  261. assign_value(val, is_reference_predicate() );
  262. else construct(val);
  263. }
  264. // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
  265. // No-throw (assuming T::~T() doesn't)
  266. void assign ( none_t ) { destroy(); }
  267. #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  268. template<class Expr>
  269. void assign_expr ( Expr const& expr, Expr const* tag )
  270. {
  271. if (is_initialized())
  272. assign_expr_to_initialized(expr,tag);
  273. else construct(expr,tag);
  274. }
  275. #endif
  276. public :
  277. // Destroys the current value, if any, leaving this UNINITIALIZED
  278. // No-throw (assuming T::~T() doesn't)
  279. void reset() { destroy(); }
  280. // Replaces the current value -if any- with 'val'
  281. void reset ( argument_type val ) { assign(val); }
  282. // Returns a pointer to the value if this is initialized, otherwise,
  283. // returns NULL.
  284. // No-throw
  285. pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
  286. pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
  287. bool is_initialized() const { return m_initialized ; }
  288. protected :
  289. void construct ( argument_type val )
  290. {
  291. new (m_storage.address()) internal_type(val) ;
  292. m_initialized = true ;
  293. }
  294. #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  295. // Constructs in-place using the given factory
  296. template<class Expr>
  297. void construct ( Expr const& factory, in_place_factory_base const* )
  298. {
  299. BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
  300. boost_optional_detail::construct<value_type>(factory, m_storage.address());
  301. m_initialized = true ;
  302. }
  303. // Constructs in-place using the given typed factory
  304. template<class Expr>
  305. void construct ( Expr const& factory, typed_in_place_factory_base const* )
  306. {
  307. BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
  308. factory.apply(m_storage.address()) ;
  309. m_initialized = true ;
  310. }
  311. template<class Expr>
  312. void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
  313. {
  314. destroy();
  315. construct(factory,tag);
  316. }
  317. // Constructs in-place using the given typed factory
  318. template<class Expr>
  319. void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
  320. {
  321. destroy();
  322. construct(factory,tag);
  323. }
  324. #endif
  325. // Constructs using any expression implicitely convertible to the single argument
  326. // of a one-argument T constructor.
  327. // Converting constructions of optional<T> from optional<U> uses this function with
  328. // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
  329. template<class Expr>
  330. void construct ( Expr const& expr, void const* )
  331. {
  332. new (m_storage.address()) internal_type(expr) ;
  333. m_initialized = true ;
  334. }
  335. // Assigns using a form any expression implicitely convertible to the single argument
  336. // of a T's assignment operator.
  337. // Converting assignments of optional<T> from optional<U> uses this function with
  338. // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
  339. template<class Expr>
  340. void assign_expr_to_initialized ( Expr const& expr, void const* )
  341. {
  342. assign_value(expr, is_reference_predicate());
  343. }
  344. #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
  345. // BCB5.64 (and probably lower versions) workaround.
  346. // The in-place factories are supported by means of catch-all constructors
  347. // and assignment operators (the functions are parameterized in terms of
  348. // an arbitrary 'Expr' type)
  349. // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
  350. // to the 'Expr'-taking functions even though explicit overloads are present for them.
  351. // Thus, the following overload is needed to properly handle the case when the 'lhs'
  352. // is another optional.
  353. //
  354. // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
  355. // instead of choosing the wrong overload
  356. //
  357. // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
  358. template<class Expr>
  359. void construct ( Expr const& expr, optional_tag const* )
  360. {
  361. if ( expr.is_initialized() )
  362. {
  363. // An exception can be thrown here.
  364. // It it happens, THIS will be left uninitialized.
  365. new (m_storage.address()) internal_type(expr.get()) ;
  366. m_initialized = true ;
  367. }
  368. }
  369. #endif
  370. void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
  371. void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
  372. void destroy()
  373. {
  374. if ( m_initialized )
  375. destroy_impl(is_reference_predicate()) ;
  376. }
  377. unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
  378. reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
  379. reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
  380. pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
  381. pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
  382. private :
  383. // internal_type can be either T or reference_content<T>
  384. #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
  385. // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
  386. internal_type const* get_object() const
  387. {
  388. union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
  389. return caster.as_ptype;
  390. }
  391. internal_type * get_object()
  392. {
  393. union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
  394. return caster.as_ptype;
  395. }
  396. #else
  397. internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
  398. internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
  399. #endif
  400. // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
  401. reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
  402. reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
  403. reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
  404. reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
  405. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
  406. void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
  407. #else
  408. void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; }
  409. #endif
  410. void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
  411. // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
  412. // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
  413. // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
  414. pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
  415. pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
  416. pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
  417. pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
  418. bool m_initialized ;
  419. storage_type m_storage ;
  420. } ;
  421. } // namespace optional_detail
  422. template<class T>
  423. class optional : public optional_detail::optional_base<T>
  424. {
  425. typedef optional_detail::optional_base<T> base ;
  426. typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
  427. public :
  428. typedef optional<T> this_type ;
  429. typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
  430. typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
  431. typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
  432. typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
  433. typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
  434. typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
  435. // Creates an optional<T> uninitialized.
  436. // No-throw
  437. optional() : base() {}
  438. // Creates an optional<T> uninitialized.
  439. // No-throw
  440. optional( none_t none_ ) : base(none_) {}
  441. // Creates an optional<T> initialized with 'val'.
  442. // Can throw if T::T(T const&) does
  443. optional ( argument_type val ) : base(val) {}
  444. // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
  445. // Can throw if T::T(T const&) does
  446. optional ( bool cond, argument_type val ) : base(cond,val) {}
  447. #ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
  448. // NOTE: MSVC needs templated versions first
  449. // Creates a deep copy of another convertible optional<U>
  450. // Requires a valid conversion from U to T.
  451. // Can throw if T::T(U const&) does
  452. template<class U>
  453. explicit optional ( optional<U> const& rhs )
  454. :
  455. base()
  456. {
  457. if ( rhs.is_initialized() )
  458. this->construct(rhs.get());
  459. }
  460. #endif
  461. #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
  462. // Creates an optional<T> with an expression which can be either
  463. // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
  464. // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
  465. // (c) Any expression implicitely convertible to the single type
  466. // of a one-argument T's constructor.
  467. // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
  468. // even though explicit overloads are present for these.
  469. // Depending on the above some T ctor is called.
  470. // Can throw is the resolved T ctor throws.
  471. template<class Expr>
  472. explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
  473. #endif
  474. // Creates a deep copy of another optional<T>
  475. // Can throw if T::T(T const&) does
  476. optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
  477. // No-throw (assuming T::~T() doesn't)
  478. ~optional() {}
  479. #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
  480. // Assigns from an expression. See corresponding constructor.
  481. // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
  482. template<class Expr>
  483. optional& operator= ( Expr const& expr )
  484. {
  485. this->assign_expr(expr,boost::addressof(expr));
  486. return *this ;
  487. }
  488. #endif
  489. #ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
  490. // Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
  491. // Requires a valid conversion from U to T.
  492. // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
  493. template<class U>
  494. optional& operator= ( optional<U> const& rhs )
  495. {
  496. this->assign(rhs);
  497. return *this ;
  498. }
  499. #endif
  500. // Assigns from another optional<T> (deep-copies the rhs value)
  501. // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
  502. // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
  503. optional& operator= ( optional const& rhs )
  504. {
  505. this->assign( static_cast<base const&>(rhs) ) ;
  506. return *this ;
  507. }
  508. // Assigns from a T (deep-copies the rhs value)
  509. // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
  510. optional& operator= ( argument_type val )
  511. {
  512. this->assign( val ) ;
  513. return *this ;
  514. }
  515. // Assigns from a "none"
  516. // Which destroys the current value, if any, leaving this UNINITIALIZED
  517. // No-throw (assuming T::~T() doesn't)
  518. optional& operator= ( none_t none_ )
  519. {
  520. this->assign( none_ ) ;
  521. return *this ;
  522. }
  523. void swap( optional & arg )
  524. {
  525. // allow for Koenig lookup
  526. using boost::swap;
  527. swap(*this, arg);
  528. }
  529. // Returns a reference to the value if this is initialized, otherwise,
  530. // the behaviour is UNDEFINED
  531. // No-throw
  532. reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
  533. reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
  534. // Returns a copy of the value if this is initialized, 'v' otherwise
  535. reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
  536. reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
  537. // Returns a pointer to the value if this is initialized, otherwise,
  538. // the behaviour is UNDEFINED
  539. // No-throw
  540. pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
  541. pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
  542. // Returns a reference to the value if this is initialized, otherwise,
  543. // the behaviour is UNDEFINED
  544. // No-throw
  545. reference_const_type operator *() const { return this->get() ; }
  546. reference_type operator *() { return this->get() ; }
  547. // implicit conversion to "bool"
  548. // No-throw
  549. operator unspecified_bool_type() const { return this->safe_bool() ; }
  550. // This is provided for those compilers which don't like the conversion to bool
  551. // on some contexts.
  552. bool operator!() const { return !this->is_initialized() ; }
  553. } ;
  554. // Returns optional<T>(v)
  555. template<class T>
  556. inline
  557. optional<T> make_optional ( T const& v )
  558. {
  559. return optional<T>(v);
  560. }
  561. // Returns optional<T>(cond,v)
  562. template<class T>
  563. inline
  564. optional<T> make_optional ( bool cond, T const& v )
  565. {
  566. return optional<T>(cond,v);
  567. }
  568. // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
  569. // No-throw
  570. template<class T>
  571. inline
  572. BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
  573. get ( optional<T> const& opt )
  574. {
  575. return opt.get() ;
  576. }
  577. template<class T>
  578. inline
  579. BOOST_DEDUCED_TYPENAME optional<T>::reference_type
  580. get ( optional<T>& opt )
  581. {
  582. return opt.get() ;
  583. }
  584. // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
  585. // No-throw
  586. template<class T>
  587. inline
  588. BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
  589. get ( optional<T> const* opt )
  590. {
  591. return opt->get_ptr() ;
  592. }
  593. template<class T>
  594. inline
  595. BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
  596. get ( optional<T>* opt )
  597. {
  598. return opt->get_ptr() ;
  599. }
  600. // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
  601. // No-throw
  602. template<class T>
  603. inline
  604. BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
  605. get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
  606. {
  607. return opt.get_value_or(v) ;
  608. }
  609. template<class T>
  610. inline
  611. BOOST_DEDUCED_TYPENAME optional<T>::reference_type
  612. get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
  613. {
  614. return opt.get_value_or(v) ;
  615. }
  616. // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
  617. // No-throw
  618. template<class T>
  619. inline
  620. BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
  621. get_pointer ( optional<T> const& opt )
  622. {
  623. return opt.get_ptr() ;
  624. }
  625. template<class T>
  626. inline
  627. BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
  628. get_pointer ( optional<T>& opt )
  629. {
  630. return opt.get_ptr() ;
  631. }
  632. // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
  633. // WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
  634. //
  635. // optional<T> vs optional<T> cases
  636. //
  637. template<class T>
  638. inline
  639. bool operator == ( optional<T> const& x, optional<T> const& y )
  640. { return equal_pointees(x,y); }
  641. template<class T>
  642. inline
  643. bool operator < ( optional<T> const& x, optional<T> const& y )
  644. { return less_pointees(x,y); }
  645. template<class T>
  646. inline
  647. bool operator != ( optional<T> const& x, optional<T> const& y )
  648. { return !( x == y ) ; }
  649. template<class T>
  650. inline
  651. bool operator > ( optional<T> const& x, optional<T> const& y )
  652. { return y < x ; }
  653. template<class T>
  654. inline
  655. bool operator <= ( optional<T> const& x, optional<T> const& y )
  656. { return !( y < x ) ; }
  657. template<class T>
  658. inline
  659. bool operator >= ( optional<T> const& x, optional<T> const& y )
  660. { return !( x < y ) ; }
  661. //
  662. // optional<T> vs T cases
  663. //
  664. template<class T>
  665. inline
  666. bool operator == ( optional<T> const& x, T const& y )
  667. { return equal_pointees(x, optional<T>(y)); }
  668. template<class T>
  669. inline
  670. bool operator < ( optional<T> const& x, T const& y )
  671. { return less_pointees(x, optional<T>(y)); }
  672. template<class T>
  673. inline
  674. bool operator != ( optional<T> const& x, T const& y )
  675. { return !( x == y ) ; }
  676. template<class T>
  677. inline
  678. bool operator > ( optional<T> const& x, T const& y )
  679. { return y < x ; }
  680. template<class T>
  681. inline
  682. bool operator <= ( optional<T> const& x, T const& y )
  683. { return !( y < x ) ; }
  684. template<class T>
  685. inline
  686. bool operator >= ( optional<T> const& x, T const& y )
  687. { return !( x < y ) ; }
  688. //
  689. // T vs optional<T> cases
  690. //
  691. template<class T>
  692. inline
  693. bool operator == ( T const& x, optional<T> const& y )
  694. { return equal_pointees( optional<T>(x), y ); }
  695. template<class T>
  696. inline
  697. bool operator < ( T const& x, optional<T> const& y )
  698. { return less_pointees( optional<T>(x), y ); }
  699. template<class T>
  700. inline
  701. bool operator != ( T const& x, optional<T> const& y )
  702. { return !( x == y ) ; }
  703. template<class T>
  704. inline
  705. bool operator > ( T const& x, optional<T> const& y )
  706. { return y < x ; }
  707. template<class T>
  708. inline
  709. bool operator <= ( T const& x, optional<T> const& y )
  710. { return !( y < x ) ; }
  711. template<class T>
  712. inline
  713. bool operator >= ( T const& x, optional<T> const& y )
  714. { return !( x < y ) ; }
  715. //
  716. // optional<T> vs none cases
  717. //
  718. template<class T>
  719. inline
  720. bool operator == ( optional<T> const& x, none_t )
  721. { return equal_pointees(x, optional<T>() ); }
  722. template<class T>
  723. inline
  724. bool operator < ( optional<T> const& x, none_t )
  725. { return less_pointees(x,optional<T>() ); }
  726. template<class T>
  727. inline
  728. bool operator != ( optional<T> const& x, none_t y )
  729. { return !( x == y ) ; }
  730. template<class T>
  731. inline
  732. bool operator > ( optional<T> const& x, none_t y )
  733. { return y < x ; }
  734. template<class T>
  735. inline
  736. bool operator <= ( optional<T> const& x, none_t y )
  737. { return !( y < x ) ; }
  738. template<class T>
  739. inline
  740. bool operator >= ( optional<T> const& x, none_t y )
  741. { return !( x < y ) ; }
  742. //
  743. // none vs optional<T> cases
  744. //
  745. template<class T>
  746. inline
  747. bool operator == ( none_t , optional<T> const& y )
  748. { return equal_pointees(optional<T>() ,y); }
  749. template<class T>
  750. inline
  751. bool operator < ( none_t , optional<T> const& y )
  752. { return less_pointees(optional<T>() ,y); }
  753. template<class T>
  754. inline
  755. bool operator != ( none_t x, optional<T> const& y )
  756. { return !( x == y ) ; }
  757. template<class T>
  758. inline
  759. bool operator > ( none_t x, optional<T> const& y )
  760. { return y < x ; }
  761. template<class T>
  762. inline
  763. bool operator <= ( none_t x, optional<T> const& y )
  764. { return !( y < x ) ; }
  765. template<class T>
  766. inline
  767. bool operator >= ( none_t x, optional<T> const& y )
  768. { return !( x < y ) ; }
  769. namespace optional_detail {
  770. template<bool use_default_constructor> struct swap_selector;
  771. template<>
  772. struct swap_selector<true>
  773. {
  774. template<class T>
  775. static void optional_swap ( optional<T>& x, optional<T>& y )
  776. {
  777. const bool hasX = !!x;
  778. const bool hasY = !!y;
  779. if ( !hasX && !hasY )
  780. return;
  781. if( !hasX )
  782. x = boost::in_place();
  783. else if ( !hasY )
  784. y = boost::in_place();
  785. // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
  786. boost::swap(x.get(),y.get());
  787. if( !hasX )
  788. y = boost::none ;
  789. else if( !hasY )
  790. x = boost::none ;
  791. }
  792. };
  793. template<>
  794. struct swap_selector<false>
  795. {
  796. template<class T>
  797. static void optional_swap ( optional<T>& x, optional<T>& y )
  798. {
  799. const bool hasX = !!x;
  800. const bool hasY = !!y;
  801. if ( !hasX && hasY )
  802. {
  803. x = y.get();
  804. y = boost::none ;
  805. }
  806. else if ( hasX && !hasY )
  807. {
  808. y = x.get();
  809. x = boost::none ;
  810. }
  811. else if ( hasX && hasY )
  812. {
  813. // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
  814. boost::swap(x.get(),y.get());
  815. }
  816. }
  817. };
  818. } // namespace optional_detail
  819. template<class T>
  820. struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
  821. template<class T> inline void swap ( optional<T>& x, optional<T>& y )
  822. {
  823. optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
  824. }
  825. } // namespace boost
  826. #endif