annotate DEPENDENCIES/generic/include/boost/optional/optional.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
Chris@101 2 // Copyright (C) 2014, 2015 Andrzej Krzemienski.
Chris@16 3 //
Chris@16 4 // Use, modification, and distribution is subject to the Boost Software
Chris@16 5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7 //
Chris@16 8 // See http://www.boost.org/libs/optional for documentation.
Chris@16 9 //
Chris@16 10 // You are welcome to contact the author at:
Chris@16 11 // fernando_cacciola@hotmail.com
Chris@16 12 //
Chris@16 13 // Revisions:
Chris@16 14 // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
Chris@101 15 // 05 May 2014 (Added move semantics) Andrzej Krzemienski
Chris@16 16 //
Chris@16 17 #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
Chris@16 18 #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
Chris@16 19
Chris@16 20 #include <new>
Chris@16 21 #include <algorithm>
Chris@101 22 #include <iosfwd>
Chris@16 23
Chris@16 24 #include <boost/config.hpp>
Chris@16 25 #include <boost/assert.hpp>
Chris@101 26 #include <boost/core/explicit_operator_bool.hpp>
Chris@101 27 #include <boost/optional/bad_optional_access.hpp>
Chris@101 28 #include <boost/static_assert.hpp>
Chris@101 29 #include <boost/throw_exception.hpp>
Chris@16 30 #include <boost/type.hpp>
Chris@16 31 #include <boost/type_traits/alignment_of.hpp>
Chris@16 32 #include <boost/type_traits/has_nothrow_constructor.hpp>
Chris@16 33 #include <boost/type_traits/type_with_alignment.hpp>
Chris@101 34 #include <boost/type_traits/remove_const.hpp>
Chris@16 35 #include <boost/type_traits/remove_reference.hpp>
Chris@101 36 #include <boost/type_traits/decay.hpp>
Chris@101 37 #include <boost/type_traits/is_base_of.hpp>
Chris@101 38 #include <boost/type_traits/is_lvalue_reference.hpp>
Chris@101 39 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
Chris@101 40 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
Chris@16 41 #include <boost/type_traits/is_reference.hpp>
Chris@101 42 #include <boost/type_traits/is_rvalue_reference.hpp>
Chris@101 43 #include <boost/type_traits/is_same.hpp>
Chris@16 44 #include <boost/mpl/if.hpp>
Chris@16 45 #include <boost/mpl/bool.hpp>
Chris@16 46 #include <boost/mpl/not.hpp>
Chris@16 47 #include <boost/detail/reference_content.hpp>
Chris@101 48 #include <boost/move/utility.hpp>
Chris@16 49 #include <boost/none.hpp>
Chris@16 50 #include <boost/utility/addressof.hpp>
Chris@16 51 #include <boost/utility/compare_pointees.hpp>
Chris@101 52 #include <boost/utility/enable_if.hpp>
Chris@16 53 #include <boost/utility/in_place_factory.hpp>
Chris@101 54 #include <boost/utility/swap.hpp>
Chris@101 55
Chris@101 56
Chris@16 57
Chris@16 58 #include <boost/optional/optional_fwd.hpp>
Chris@16 59
Chris@101 60 #if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES)
Chris@101 61 #define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@16 62 #endif
Chris@16 63
Chris@101 64 #if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
Chris@101 65 // AFAICT only Intel 7 correctly resolves the overload set
Chris@16 66 // that includes the in-place factory taking functions,
Chris@101 67 // so for the other icc versions, in-place factory support
Chris@16 68 // is disabled
Chris@16 69 #define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
Chris@16 70 #endif
Chris@16 71
Chris@16 72 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
Chris@16 73 // BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
Chris@16 74 #define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
Chris@16 75 #endif
Chris@16 76
Chris@16 77 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
Chris@16 78 && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581) )
Chris@16 79 // BCB (up to 5.64) has the following bug:
Chris@16 80 // If there is a member function/operator template of the form
Chris@16 81 // template<class Expr> mfunc( Expr expr ) ;
Chris@16 82 // some calls are resolved to this even if there are other better matches.
Chris@16 83 // The effect of this bug is that calls to converting ctors and assignments
Chris@16 84 // are incrorrectly sink to this general catch-all member function template as shown above.
Chris@16 85 #define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
Chris@16 86 #endif
Chris@16 87
Chris@101 88 #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
Chris@16 89 // GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
Chris@16 90 // regard to violation of the strict aliasing rules. The optional< T > storage type is marked
Chris@16 91 // with this attribute in order to let the compiler know that it will alias objects of type T
Chris@16 92 // and silence compilation warnings.
Chris@16 93 #define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
Chris@16 94 #endif
Chris@16 95
Chris@16 96 // Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
Chris@16 97 // member template of a factory as used in the optional<> implementation.
Chris@16 98 // He proposed this simple fix which is to move the call to apply<> outside
Chris@16 99 // namespace boost.
Chris@16 100 namespace boost_optional_detail
Chris@16 101 {
Chris@16 102 template <class T, class Factory>
Chris@16 103 inline void construct(Factory const& factory, void* address)
Chris@16 104 {
Chris@16 105 factory.BOOST_NESTED_TEMPLATE apply<T>(address);
Chris@16 106 }
Chris@16 107 }
Chris@16 108
Chris@16 109
Chris@16 110 namespace boost {
Chris@16 111
Chris@16 112 class in_place_factory_base ;
Chris@16 113 class typed_in_place_factory_base ;
Chris@16 114
Chris@16 115 // This forward is needed to refer to namespace scope swap from the member swap
Chris@16 116 template<class T> void swap ( optional<T>& x, optional<T>& y );
Chris@16 117
Chris@16 118 namespace optional_detail {
Chris@16 119 // This local class is used instead of that in "aligned_storage.hpp"
Chris@16 120 // because I've found the 'official' class to ICE BCB5.5
Chris@16 121 // when some types are used with optional<>
Chris@16 122 // (due to sizeof() passed down as a non-type template parameter)
Chris@16 123 template <class T>
Chris@16 124 class aligned_storage
Chris@16 125 {
Chris@16 126 // Borland ICEs if unnamed unions are used for this!
Chris@16 127 union
Chris@16 128 // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
Chris@16 129 #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
Chris@101 130 __attribute__((__may_alias__))
Chris@16 131 #endif
Chris@16 132 dummy_u
Chris@16 133 {
Chris@16 134 char data[ sizeof(T) ];
Chris@16 135 BOOST_DEDUCED_TYPENAME type_with_alignment<
Chris@16 136 ::boost::alignment_of<T>::value >::type aligner_;
Chris@16 137 } dummy_ ;
Chris@16 138
Chris@16 139 public:
Chris@16 140
Chris@16 141 #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
Chris@16 142 void const* address() const { return &dummy_; }
Chris@16 143 void * address() { return &dummy_; }
Chris@16 144 #else
Chris@16 145 void const* address() const { return dummy_.data; }
Chris@16 146 void * address() { return dummy_.data; }
Chris@16 147 #endif
Chris@16 148 } ;
Chris@16 149
Chris@16 150 template<class T>
Chris@16 151 struct types_when_isnt_ref
Chris@16 152 {
Chris@16 153 typedef T const& reference_const_type ;
Chris@16 154 typedef T & reference_type ;
Chris@101 155 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 156 typedef T && rval_reference_type ;
Chris@101 157 typedef T && reference_type_of_temporary_wrapper;
Chris@101 158 #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
Chris@101 159 // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
Chris@101 160 // causes warnings about returning references to a temporary.
Chris@101 161 static T&& move(T&& r) { return r; }
Chris@101 162 #else
Chris@101 163 static rval_reference_type move(reference_type r) { return boost::move(r); }
Chris@101 164 #endif
Chris@101 165 #endif
Chris@16 166 typedef T const* pointer_const_type ;
Chris@16 167 typedef T * pointer_type ;
Chris@16 168 typedef T const& argument_type ;
Chris@16 169 } ;
Chris@101 170
Chris@16 171 template<class T>
Chris@16 172 struct types_when_is_ref
Chris@16 173 {
Chris@16 174 typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
Chris@16 175
Chris@101 176 typedef raw_type& reference_const_type ;
Chris@101 177 typedef raw_type& reference_type ;
Chris@101 178 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 179 typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
Chris@101 180 typedef raw_type& reference_type_of_temporary_wrapper;
Chris@101 181 static reference_type move(reference_type r) { return r; }
Chris@101 182 #endif
Chris@101 183 typedef raw_type* pointer_const_type ;
Chris@101 184 typedef raw_type* pointer_type ;
Chris@101 185 typedef raw_type& argument_type ;
Chris@16 186 } ;
Chris@16 187
Chris@101 188 template <class To, class From>
Chris@101 189 void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
Chris@101 190 {
Chris@101 191 #ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
Chris@101 192 BOOST_STATIC_ASSERT_MSG(
Chris@101 193 !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value,
Chris@101 194 "binding rvalue references to optional lvalue references is disallowed");
Chris@101 195 #endif
Chris@101 196 }
Chris@101 197
Chris@16 198 struct optional_tag {} ;
Chris@16 199
Chris@16 200 template<class T>
Chris@16 201 class optional_base : public optional_tag
Chris@16 202 {
Chris@16 203 private :
Chris@16 204
Chris@16 205 typedef
Chris@16 206 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
Chris@16 207 BOOST_DEDUCED_TYPENAME
Chris@16 208 #endif
Chris@16 209 ::boost::detail::make_reference_content<T>::type internal_type ;
Chris@16 210
Chris@16 211 typedef aligned_storage<internal_type> storage_type ;
Chris@16 212
Chris@16 213 typedef types_when_isnt_ref<T> types_when_not_ref ;
Chris@16 214 typedef types_when_is_ref<T> types_when_ref ;
Chris@16 215
Chris@16 216 typedef optional_base<T> this_type ;
Chris@16 217
Chris@16 218 protected :
Chris@16 219
Chris@16 220 typedef T value_type ;
Chris@16 221
Chris@16 222 typedef mpl::true_ is_reference_tag ;
Chris@16 223 typedef mpl::false_ is_not_reference_tag ;
Chris@16 224
Chris@16 225 typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
Chris@16 226
Chris@16 227 public:
Chris@16 228 typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
Chris@16 229
Chris@16 230 protected:
Chris@16 231 typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
Chris@16 232 typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
Chris@101 233 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 234 typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
Chris@101 235 typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
Chris@101 236 #endif
Chris@16 237 typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
Chris@16 238 typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
Chris@16 239 typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
Chris@16 240
Chris@16 241 // Creates an optional<T> uninitialized.
Chris@16 242 // No-throw
Chris@16 243 optional_base()
Chris@16 244 :
Chris@16 245 m_initialized(false) {}
Chris@16 246
Chris@16 247 // Creates an optional<T> uninitialized.
Chris@16 248 // No-throw
Chris@16 249 optional_base ( none_t )
Chris@16 250 :
Chris@16 251 m_initialized(false) {}
Chris@16 252
Chris@16 253 // Creates an optional<T> initialized with 'val'.
Chris@16 254 // Can throw if T::T(T const&) does
Chris@16 255 optional_base ( argument_type val )
Chris@16 256 :
Chris@16 257 m_initialized(false)
Chris@16 258 {
Chris@16 259 construct(val);
Chris@16 260 }
Chris@16 261
Chris@101 262 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 263 // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
Chris@101 264 // Can throw if T::T(T&&) does
Chris@101 265 optional_base ( rval_reference_type val )
Chris@101 266 :
Chris@101 267 m_initialized(false)
Chris@101 268 {
Chris@101 269 construct( boost::move(val) );
Chris@101 270 }
Chris@101 271 #endif
Chris@101 272
Chris@16 273 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
Chris@16 274 // Can throw if T::T(T const&) does
Chris@16 275 optional_base ( bool cond, argument_type val )
Chris@16 276 :
Chris@16 277 m_initialized(false)
Chris@16 278 {
Chris@16 279 if ( cond )
Chris@16 280 construct(val);
Chris@16 281 }
Chris@16 282
Chris@16 283 // Creates a deep copy of another optional<T>
Chris@16 284 // Can throw if T::T(T const&) does
Chris@16 285 optional_base ( optional_base const& rhs )
Chris@16 286 :
Chris@16 287 m_initialized(false)
Chris@16 288 {
Chris@16 289 if ( rhs.is_initialized() )
Chris@16 290 construct(rhs.get_impl());
Chris@16 291 }
Chris@16 292
Chris@101 293 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 294 // Creates a deep move of another optional<T>
Chris@101 295 // Can throw if T::T(T&&) does
Chris@101 296 optional_base ( optional_base&& rhs )
Chris@101 297 :
Chris@101 298 m_initialized(false)
Chris@101 299 {
Chris@101 300 if ( rhs.is_initialized() )
Chris@101 301 construct( boost::move(rhs.get_impl()) );
Chris@101 302 }
Chris@101 303 #endif
Chris@16 304
Chris@101 305 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 306
Chris@101 307 template<class Expr, class PtrExpr>
Chris@101 308 explicit optional_base ( Expr&& expr, PtrExpr const* tag )
Chris@101 309 :
Chris@101 310 m_initialized(false)
Chris@101 311 {
Chris@101 312 construct(boost::forward<Expr>(expr),tag);
Chris@101 313 }
Chris@101 314
Chris@101 315 #else
Chris@16 316 // This is used for both converting and in-place constructions.
Chris@16 317 // Derived classes use the 'tag' to select the appropriate
Chris@16 318 // implementation (the correct 'construct()' overload)
Chris@16 319 template<class Expr>
Chris@16 320 explicit optional_base ( Expr const& expr, Expr const* tag )
Chris@16 321 :
Chris@16 322 m_initialized(false)
Chris@16 323 {
Chris@16 324 construct(expr,tag);
Chris@16 325 }
Chris@16 326
Chris@101 327 #endif
Chris@16 328
Chris@16 329
Chris@16 330 // No-throw (assuming T::~T() doesn't)
Chris@16 331 ~optional_base() { destroy() ; }
Chris@16 332
Chris@16 333 // Assigns from another optional<T> (deep-copies the rhs value)
Chris@16 334 void assign ( optional_base const& rhs )
Chris@16 335 {
Chris@16 336 if (is_initialized())
Chris@16 337 {
Chris@16 338 if ( rhs.is_initialized() )
Chris@16 339 assign_value(rhs.get_impl(), is_reference_predicate() );
Chris@16 340 else destroy();
Chris@16 341 }
Chris@16 342 else
Chris@16 343 {
Chris@16 344 if ( rhs.is_initialized() )
Chris@16 345 construct(rhs.get_impl());
Chris@16 346 }
Chris@16 347 }
Chris@101 348
Chris@101 349 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 350 // Assigns from another optional<T> (deep-moves the rhs value)
Chris@101 351 void assign ( optional_base&& rhs )
Chris@101 352 {
Chris@101 353 if (is_initialized())
Chris@101 354 {
Chris@101 355 if ( rhs.is_initialized() )
Chris@101 356 assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
Chris@101 357 else destroy();
Chris@101 358 }
Chris@101 359 else
Chris@101 360 {
Chris@101 361 if ( rhs.is_initialized() )
Chris@101 362 construct(boost::move(rhs.get_impl()));
Chris@101 363 }
Chris@101 364 }
Chris@101 365 #endif
Chris@16 366
Chris@16 367 // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
Chris@16 368 template<class U>
Chris@16 369 void assign ( optional<U> const& rhs )
Chris@16 370 {
Chris@16 371 if (is_initialized())
Chris@16 372 {
Chris@16 373 if ( rhs.is_initialized() )
Chris@101 374 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
Chris@101 375 assign_value(rhs.get(), is_reference_predicate() );
Chris@101 376 #else
Chris@101 377 assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
Chris@101 378 #endif
Chris@101 379
Chris@16 380 else destroy();
Chris@16 381 }
Chris@16 382 else
Chris@16 383 {
Chris@16 384 if ( rhs.is_initialized() )
Chris@101 385 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
Chris@101 386 construct(rhs.get());
Chris@101 387 #else
Chris@16 388 construct(static_cast<value_type>(rhs.get()));
Chris@101 389 #endif
Chris@16 390 }
Chris@16 391 }
Chris@16 392
Chris@101 393 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 394 // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
Chris@101 395 template<class U>
Chris@101 396 void assign ( optional<U>&& rhs )
Chris@101 397 {
Chris@101 398 typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
Chris@101 399 if (is_initialized())
Chris@101 400 {
Chris@101 401 if ( rhs.is_initialized() )
Chris@101 402 assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
Chris@101 403 else destroy();
Chris@101 404 }
Chris@101 405 else
Chris@101 406 {
Chris@101 407 if ( rhs.is_initialized() )
Chris@101 408 construct(static_cast<ref_type>(rhs.get()));
Chris@101 409 }
Chris@101 410 }
Chris@101 411 #endif
Chris@101 412
Chris@16 413 // Assigns from a T (deep-copies the rhs value)
Chris@16 414 void assign ( argument_type val )
Chris@16 415 {
Chris@16 416 if (is_initialized())
Chris@16 417 assign_value(val, is_reference_predicate() );
Chris@16 418 else construct(val);
Chris@16 419 }
Chris@101 420
Chris@101 421 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 422 // Assigns from a T (deep-moves the rhs value)
Chris@101 423 void assign ( rval_reference_type val )
Chris@101 424 {
Chris@101 425 if (is_initialized())
Chris@101 426 assign_value( boost::move(val), is_reference_predicate() );
Chris@101 427 else construct( boost::move(val) );
Chris@101 428 }
Chris@101 429 #endif
Chris@16 430
Chris@16 431 // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
Chris@16 432 // No-throw (assuming T::~T() doesn't)
Chris@101 433 void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
Chris@16 434
Chris@16 435 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
Chris@101 436
Chris@101 437 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 438 template<class Expr, class ExprPtr>
Chris@101 439 void assign_expr ( Expr&& expr, ExprPtr const* tag )
Chris@101 440 {
Chris@101 441 if (is_initialized())
Chris@101 442 assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
Chris@101 443 else construct(boost::forward<Expr>(expr),tag);
Chris@101 444 }
Chris@101 445 #else
Chris@16 446 template<class Expr>
Chris@16 447 void assign_expr ( Expr const& expr, Expr const* tag )
Chris@101 448 {
Chris@101 449 if (is_initialized())
Chris@101 450 assign_expr_to_initialized(expr,tag);
Chris@101 451 else construct(expr,tag);
Chris@101 452 }
Chris@101 453 #endif
Chris@101 454
Chris@16 455 #endif
Chris@16 456
Chris@16 457 public :
Chris@16 458
Chris@101 459 // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
Chris@16 460 // No-throw (assuming T::~T() doesn't)
Chris@101 461 void reset() BOOST_NOEXCEPT { destroy(); }
Chris@16 462
Chris@101 463 // **DEPPRECATED** Replaces the current value -if any- with 'val'
Chris@16 464 void reset ( argument_type val ) { assign(val); }
Chris@16 465
Chris@16 466 // Returns a pointer to the value if this is initialized, otherwise,
Chris@16 467 // returns NULL.
Chris@16 468 // No-throw
Chris@16 469 pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
Chris@16 470 pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
Chris@16 471
Chris@16 472 bool is_initialized() const { return m_initialized ; }
Chris@16 473
Chris@16 474 protected :
Chris@16 475
Chris@16 476 void construct ( argument_type val )
Chris@16 477 {
Chris@101 478 ::new (m_storage.address()) internal_type(val) ;
Chris@101 479 m_initialized = true ;
Chris@101 480 }
Chris@101 481
Chris@101 482 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 483 void construct ( rval_reference_type val )
Chris@101 484 {
Chris@101 485 ::new (m_storage.address()) internal_type( types::move(val) ) ;
Chris@101 486 m_initialized = true ;
Chris@101 487 }
Chris@101 488 #endif
Chris@101 489
Chris@101 490
Chris@101 491 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@101 492 // Constructs in-place
Chris@101 493 // upon exception *this is always uninitialized
Chris@101 494 template<class... Args>
Chris@101 495 void emplace_assign ( Args&&... args )
Chris@101 496 {
Chris@101 497 destroy();
Chris@101 498 ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
Chris@101 499 m_initialized = true ;
Chris@101 500 }
Chris@101 501 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
Chris@101 502 template<class Arg>
Chris@101 503 void emplace_assign ( Arg&& arg )
Chris@101 504 {
Chris@101 505 destroy();
Chris@101 506 ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
Chris@101 507 m_initialized = true ;
Chris@101 508 }
Chris@101 509 #else
Chris@101 510 template<class Arg>
Chris@101 511 void emplace_assign ( const Arg& arg )
Chris@101 512 {
Chris@101 513 destroy();
Chris@101 514 ::new (m_storage.address()) internal_type( arg );
Chris@101 515 m_initialized = true ;
Chris@101 516 }
Chris@101 517
Chris@101 518 template<class Arg>
Chris@101 519 void emplace_assign ( Arg& arg )
Chris@101 520 {
Chris@101 521 destroy();
Chris@101 522 ::new (m_storage.address()) internal_type( arg );
Chris@101 523 m_initialized = true ;
Chris@101 524 }
Chris@101 525 #endif
Chris@101 526
Chris@101 527 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
Chris@101 528
Chris@101 529 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 530 // Constructs in-place using the given factory
Chris@101 531 template<class Expr>
Chris@101 532 void construct ( Expr&& factory, in_place_factory_base const* )
Chris@101 533 {
Chris@101 534 BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
Chris@101 535 boost_optional_detail::construct<value_type>(factory, m_storage.address());
Chris@16 536 m_initialized = true ;
Chris@16 537 }
Chris@16 538
Chris@101 539 // Constructs in-place using the given typed factory
Chris@101 540 template<class Expr>
Chris@101 541 void construct ( Expr&& factory, typed_in_place_factory_base const* )
Chris@101 542 {
Chris@101 543 BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
Chris@101 544 factory.apply(m_storage.address()) ;
Chris@101 545 m_initialized = true ;
Chris@101 546 }
Chris@101 547
Chris@101 548 template<class Expr>
Chris@101 549 void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
Chris@101 550 {
Chris@101 551 destroy();
Chris@101 552 construct(factory,tag);
Chris@101 553 }
Chris@101 554
Chris@101 555 // Constructs in-place using the given typed factory
Chris@101 556 template<class Expr>
Chris@101 557 void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
Chris@101 558 {
Chris@101 559 destroy();
Chris@101 560 construct(factory,tag);
Chris@101 561 }
Chris@101 562
Chris@101 563 #else
Chris@16 564 // Constructs in-place using the given factory
Chris@16 565 template<class Expr>
Chris@16 566 void construct ( Expr const& factory, in_place_factory_base const* )
Chris@16 567 {
Chris@16 568 BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
Chris@16 569 boost_optional_detail::construct<value_type>(factory, m_storage.address());
Chris@16 570 m_initialized = true ;
Chris@16 571 }
Chris@16 572
Chris@16 573 // Constructs in-place using the given typed factory
Chris@16 574 template<class Expr>
Chris@16 575 void construct ( Expr const& factory, typed_in_place_factory_base const* )
Chris@16 576 {
Chris@16 577 BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
Chris@16 578 factory.apply(m_storage.address()) ;
Chris@16 579 m_initialized = true ;
Chris@16 580 }
Chris@16 581
Chris@16 582 template<class Expr>
Chris@16 583 void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
Chris@16 584 {
Chris@16 585 destroy();
Chris@16 586 construct(factory,tag);
Chris@16 587 }
Chris@16 588
Chris@16 589 // Constructs in-place using the given typed factory
Chris@16 590 template<class Expr>
Chris@16 591 void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
Chris@16 592 {
Chris@16 593 destroy();
Chris@16 594 construct(factory,tag);
Chris@16 595 }
Chris@16 596 #endif
Chris@16 597
Chris@101 598 #endif
Chris@101 599
Chris@101 600 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 601 // Constructs using any expression implicitly convertible to the single argument
Chris@101 602 // of a one-argument T constructor.
Chris@101 603 // Converting constructions of optional<T> from optional<U> uses this function with
Chris@101 604 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
Chris@101 605 template<class Expr>
Chris@101 606 void construct ( Expr&& expr, void const* )
Chris@101 607 {
Chris@101 608 new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
Chris@101 609 m_initialized = true ;
Chris@101 610 }
Chris@101 611
Chris@101 612 // Assigns using a form any expression implicitly convertible to the single argument
Chris@101 613 // of a T's assignment operator.
Chris@101 614 // Converting assignments of optional<T> from optional<U> uses this function with
Chris@101 615 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
Chris@101 616 template<class Expr>
Chris@101 617 void assign_expr_to_initialized ( Expr&& expr, void const* )
Chris@101 618 {
Chris@101 619 assign_value(boost::forward<Expr>(expr), is_reference_predicate());
Chris@101 620 }
Chris@101 621 #else
Chris@101 622 // Constructs using any expression implicitly convertible to the single argument
Chris@16 623 // of a one-argument T constructor.
Chris@16 624 // Converting constructions of optional<T> from optional<U> uses this function with
Chris@16 625 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
Chris@16 626 template<class Expr>
Chris@16 627 void construct ( Expr const& expr, void const* )
Chris@16 628 {
Chris@16 629 new (m_storage.address()) internal_type(expr) ;
Chris@16 630 m_initialized = true ;
Chris@16 631 }
Chris@16 632
Chris@101 633 // Assigns using a form any expression implicitly convertible to the single argument
Chris@16 634 // of a T's assignment operator.
Chris@16 635 // Converting assignments of optional<T> from optional<U> uses this function with
Chris@16 636 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
Chris@16 637 template<class Expr>
Chris@16 638 void assign_expr_to_initialized ( Expr const& expr, void const* )
Chris@16 639 {
Chris@16 640 assign_value(expr, is_reference_predicate());
Chris@16 641 }
Chris@16 642
Chris@101 643 #endif
Chris@101 644
Chris@16 645 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
Chris@16 646 // BCB5.64 (and probably lower versions) workaround.
Chris@16 647 // The in-place factories are supported by means of catch-all constructors
Chris@16 648 // and assignment operators (the functions are parameterized in terms of
Chris@16 649 // an arbitrary 'Expr' type)
Chris@16 650 // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
Chris@16 651 // to the 'Expr'-taking functions even though explicit overloads are present for them.
Chris@16 652 // Thus, the following overload is needed to properly handle the case when the 'lhs'
Chris@16 653 // is another optional.
Chris@16 654 //
Chris@16 655 // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
Chris@16 656 // instead of choosing the wrong overload
Chris@16 657 //
Chris@101 658 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 659 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
Chris@101 660 template<class Expr>
Chris@101 661 void construct ( Expr&& expr, optional_tag const* )
Chris@101 662 {
Chris@101 663 if ( expr.is_initialized() )
Chris@101 664 {
Chris@101 665 // An exception can be thrown here.
Chris@101 666 // It it happens, THIS will be left uninitialized.
Chris@101 667 new (m_storage.address()) internal_type(types::move(expr.get())) ;
Chris@101 668 m_initialized = true ;
Chris@101 669 }
Chris@101 670 }
Chris@101 671 #else
Chris@16 672 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
Chris@16 673 template<class Expr>
Chris@16 674 void construct ( Expr const& expr, optional_tag const* )
Chris@16 675 {
Chris@16 676 if ( expr.is_initialized() )
Chris@16 677 {
Chris@16 678 // An exception can be thrown here.
Chris@16 679 // It it happens, THIS will be left uninitialized.
Chris@16 680 new (m_storage.address()) internal_type(expr.get()) ;
Chris@16 681 m_initialized = true ;
Chris@16 682 }
Chris@16 683 }
Chris@16 684 #endif
Chris@101 685 #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
Chris@16 686
Chris@16 687 void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
Chris@16 688 void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
Chris@101 689 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 690 void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
Chris@101 691 void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); }
Chris@101 692 #endif
Chris@16 693
Chris@16 694 void destroy()
Chris@16 695 {
Chris@16 696 if ( m_initialized )
Chris@16 697 destroy_impl(is_reference_predicate()) ;
Chris@16 698 }
Chris@16 699
Chris@16 700 reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
Chris@16 701 reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
Chris@16 702
Chris@16 703 pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
Chris@16 704 pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
Chris@16 705
Chris@16 706 private :
Chris@16 707
Chris@16 708 // internal_type can be either T or reference_content<T>
Chris@16 709 #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
Chris@16 710 // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
Chris@16 711 internal_type const* get_object() const
Chris@16 712 {
Chris@16 713 union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
Chris@16 714 return caster.as_ptype;
Chris@16 715 }
Chris@16 716 internal_type * get_object()
Chris@16 717 {
Chris@16 718 union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
Chris@16 719 return caster.as_ptype;
Chris@16 720 }
Chris@16 721 #else
Chris@16 722 internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
Chris@16 723 internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
Chris@16 724 #endif
Chris@16 725
Chris@16 726 // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
Chris@16 727 reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
Chris@16 728 reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
Chris@16 729 reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
Chris@16 730 reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
Chris@16 731
Chris@16 732 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
Chris@16 733 void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
Chris@16 734 #else
Chris@101 735 void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
Chris@16 736 #endif
Chris@16 737
Chris@16 738 void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
Chris@16 739
Chris@16 740 // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
Chris@16 741 // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
Chris@16 742 // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
Chris@16 743 pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
Chris@16 744 pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
Chris@16 745 pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
Chris@16 746 pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
Chris@16 747
Chris@16 748 bool m_initialized ;
Chris@16 749 storage_type m_storage ;
Chris@16 750 } ;
Chris@16 751
Chris@16 752 } // namespace optional_detail
Chris@16 753
Chris@16 754 template<class T>
Chris@16 755 class optional : public optional_detail::optional_base<T>
Chris@16 756 {
Chris@16 757 typedef optional_detail::optional_base<T> base ;
Chris@16 758
Chris@16 759 public :
Chris@16 760
Chris@16 761 typedef optional<T> this_type ;
Chris@16 762
Chris@16 763 typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
Chris@16 764 typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
Chris@16 765 typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
Chris@101 766 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 767 typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
Chris@101 768 typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
Chris@101 769 #endif
Chris@16 770 typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
Chris@16 771 typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
Chris@16 772 typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
Chris@16 773
Chris@16 774 // Creates an optional<T> uninitialized.
Chris@16 775 // No-throw
Chris@101 776 optional() BOOST_NOEXCEPT : base() {}
Chris@16 777
Chris@16 778 // Creates an optional<T> uninitialized.
Chris@16 779 // No-throw
Chris@101 780 optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
Chris@16 781
Chris@16 782 // Creates an optional<T> initialized with 'val'.
Chris@16 783 // Can throw if T::T(T const&) does
Chris@16 784 optional ( argument_type val ) : base(val) {}
Chris@16 785
Chris@101 786 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 787 // Creates an optional<T> initialized with 'move(val)'.
Chris@101 788 // Can throw if T::T(T &&) does
Chris@101 789 optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
Chris@101 790 {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
Chris@101 791 #endif
Chris@101 792
Chris@16 793 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
Chris@16 794 // Can throw if T::T(T const&) does
Chris@16 795 optional ( bool cond, argument_type val ) : base(cond,val) {}
Chris@16 796
Chris@16 797 // NOTE: MSVC needs templated versions first
Chris@16 798
Chris@16 799 // Creates a deep copy of another convertible optional<U>
Chris@16 800 // Requires a valid conversion from U to T.
Chris@16 801 // Can throw if T::T(U const&) does
Chris@16 802 template<class U>
Chris@16 803 explicit optional ( optional<U> const& rhs )
Chris@16 804 :
Chris@16 805 base()
Chris@16 806 {
Chris@16 807 if ( rhs.is_initialized() )
Chris@16 808 this->construct(rhs.get());
Chris@16 809 }
Chris@101 810
Chris@101 811 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 812 // Creates a deep move of another convertible optional<U>
Chris@101 813 // Requires a valid conversion from U to T.
Chris@101 814 // Can throw if T::T(U&&) does
Chris@101 815 template<class U>
Chris@101 816 explicit optional ( optional<U> && rhs )
Chris@101 817 :
Chris@101 818 base()
Chris@101 819 {
Chris@101 820 if ( rhs.is_initialized() )
Chris@101 821 this->construct( boost::move(rhs.get()) );
Chris@101 822 }
Chris@16 823 #endif
Chris@16 824
Chris@16 825 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
Chris@16 826 // Creates an optional<T> with an expression which can be either
Chris@16 827 // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
Chris@16 828 // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
Chris@101 829 // (c) Any expression implicitly convertible to the single type
Chris@16 830 // of a one-argument T's constructor.
Chris@16 831 // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
Chris@16 832 // even though explicit overloads are present for these.
Chris@16 833 // Depending on the above some T ctor is called.
Chris@101 834 // Can throw if the resolved T ctor throws.
Chris@101 835 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 836
Chris@101 837
Chris@101 838 template<class Expr>
Chris@101 839 explicit optional ( Expr&& expr,
Chris@101 840 BOOST_DEDUCED_TYPENAME boost::disable_if_c<
Chris@101 841 (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
Chris@101 842 boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value >::type* = 0
Chris@101 843 )
Chris@101 844 : base(boost::forward<Expr>(expr),boost::addressof(expr))
Chris@101 845 {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
Chris@101 846
Chris@101 847 #else
Chris@16 848 template<class Expr>
Chris@16 849 explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
Chris@101 850 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 851 #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
Chris@16 852
Chris@16 853 // Creates a deep copy of another optional<T>
Chris@16 854 // Can throw if T::T(T const&) does
Chris@16 855 optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
Chris@16 856
Chris@101 857 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 858 // Creates a deep move of another optional<T>
Chris@101 859 // Can throw if T::T(T&&) does
Chris@101 860 optional ( optional && rhs )
Chris@101 861 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
Chris@101 862 : base( boost::move(rhs) )
Chris@101 863 {}
Chris@101 864
Chris@101 865 #endif
Chris@16 866 // No-throw (assuming T::~T() doesn't)
Chris@16 867 ~optional() {}
Chris@16 868
Chris@16 869 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
Chris@16 870 // Assigns from an expression. See corresponding constructor.
Chris@16 871 // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
Chris@101 872 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 873
Chris@101 874 template<class Expr>
Chris@101 875 BOOST_DEDUCED_TYPENAME boost::disable_if_c<
Chris@101 876 boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
Chris@101 877 boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
Chris@101 878 optional&
Chris@101 879 >::type
Chris@101 880 operator= ( Expr&& expr )
Chris@101 881 {
Chris@101 882 optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
Chris@101 883 this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
Chris@101 884 return *this ;
Chris@101 885 }
Chris@101 886
Chris@101 887 #else
Chris@16 888 template<class Expr>
Chris@16 889 optional& operator= ( Expr const& expr )
Chris@16 890 {
Chris@16 891 this->assign_expr(expr,boost::addressof(expr));
Chris@16 892 return *this ;
Chris@16 893 }
Chris@101 894 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 895 #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
Chris@16 896
Chris@101 897 // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
Chris@16 898 // Requires a valid conversion from U to T.
Chris@16 899 // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
Chris@16 900 template<class U>
Chris@16 901 optional& operator= ( optional<U> const& rhs )
Chris@16 902 {
Chris@16 903 this->assign(rhs);
Chris@16 904 return *this ;
Chris@16 905 }
Chris@101 906
Chris@101 907 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 908 // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
Chris@101 909 // Requires a valid conversion from U to T.
Chris@101 910 // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
Chris@101 911 template<class U>
Chris@101 912 optional& operator= ( optional<U> && rhs )
Chris@101 913 {
Chris@101 914 this->assign(boost::move(rhs));
Chris@101 915 return *this ;
Chris@101 916 }
Chris@16 917 #endif
Chris@16 918
Chris@16 919 // Assigns from another optional<T> (deep-copies the rhs value)
Chris@16 920 // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
Chris@16 921 // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
Chris@16 922 optional& operator= ( optional const& rhs )
Chris@16 923 {
Chris@16 924 this->assign( static_cast<base const&>(rhs) ) ;
Chris@16 925 return *this ;
Chris@16 926 }
Chris@16 927
Chris@101 928 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 929 // Assigns from another optional<T> (deep-moves the rhs value)
Chris@101 930 optional& operator= ( optional && rhs )
Chris@101 931 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
Chris@101 932 {
Chris@101 933 this->assign( static_cast<base &&>(rhs) ) ;
Chris@101 934 return *this ;
Chris@101 935 }
Chris@101 936 #endif
Chris@101 937
Chris@16 938 // Assigns from a T (deep-copies the rhs value)
Chris@16 939 // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
Chris@16 940 optional& operator= ( argument_type val )
Chris@16 941 {
Chris@16 942 this->assign( val ) ;
Chris@16 943 return *this ;
Chris@16 944 }
Chris@16 945
Chris@101 946 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 947 // Assigns from a T (deep-moves the rhs value)
Chris@101 948 optional& operator= ( rval_reference_type val )
Chris@101 949 {
Chris@101 950 optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
Chris@101 951 this->assign( boost::move(val) ) ;
Chris@101 952 return *this ;
Chris@101 953 }
Chris@101 954 #endif
Chris@101 955
Chris@16 956 // Assigns from a "none"
Chris@16 957 // Which destroys the current value, if any, leaving this UNINITIALIZED
Chris@16 958 // No-throw (assuming T::~T() doesn't)
Chris@101 959 optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
Chris@16 960 {
Chris@16 961 this->assign( none_ ) ;
Chris@16 962 return *this ;
Chris@16 963 }
Chris@101 964
Chris@101 965 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@101 966 // Constructs in-place
Chris@101 967 // upon exception *this is always uninitialized
Chris@101 968 template<class... Args>
Chris@101 969 void emplace ( Args&&... args )
Chris@101 970 {
Chris@101 971 this->emplace_assign( boost::forward<Args>(args)... );
Chris@101 972 }
Chris@101 973 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
Chris@101 974 template<class Arg>
Chris@101 975 void emplace ( Arg&& arg )
Chris@101 976 {
Chris@101 977 this->emplace_assign( boost::forward<Arg>(arg) );
Chris@101 978 }
Chris@101 979 #else
Chris@101 980 template<class Arg>
Chris@101 981 void emplace ( const Arg& arg )
Chris@101 982 {
Chris@101 983 this->emplace_assign( arg );
Chris@101 984 }
Chris@101 985
Chris@101 986 template<class Arg>
Chris@101 987 void emplace ( Arg& arg )
Chris@101 988 {
Chris@101 989 this->emplace_assign( arg );
Chris@101 990 }
Chris@101 991 #endif
Chris@16 992
Chris@16 993 void swap( optional & arg )
Chris@101 994 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
Chris@16 995 {
Chris@16 996 // allow for Koenig lookup
Chris@101 997 boost::swap(*this, arg);
Chris@16 998 }
Chris@16 999
Chris@16 1000
Chris@16 1001 // Returns a reference to the value if this is initialized, otherwise,
Chris@16 1002 // the behaviour is UNDEFINED
Chris@16 1003 // No-throw
Chris@16 1004 reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
Chris@16 1005 reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
Chris@16 1006
Chris@16 1007 // Returns a copy of the value if this is initialized, 'v' otherwise
Chris@16 1008 reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
Chris@16 1009 reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
Chris@16 1010
Chris@16 1011 // Returns a pointer to the value if this is initialized, otherwise,
Chris@16 1012 // the behaviour is UNDEFINED
Chris@16 1013 // No-throw
Chris@16 1014 pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
Chris@16 1015 pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
Chris@16 1016
Chris@16 1017 // Returns a reference to the value if this is initialized, otherwise,
Chris@16 1018 // the behaviour is UNDEFINED
Chris@16 1019 // No-throw
Chris@101 1020 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
Chris@101 1021 reference_const_type operator *() const& { return this->get() ; }
Chris@101 1022 reference_type operator *() & { return this->get() ; }
Chris@101 1023 reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; }
Chris@101 1024 #else
Chris@16 1025 reference_const_type operator *() const { return this->get() ; }
Chris@16 1026 reference_type operator *() { return this->get() ; }
Chris@101 1027 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
Chris@16 1028
Chris@101 1029 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
Chris@101 1030 reference_const_type value() const&
Chris@101 1031 {
Chris@101 1032 if (this->is_initialized())
Chris@101 1033 return this->get() ;
Chris@101 1034 else
Chris@101 1035 throw_exception(bad_optional_access());
Chris@101 1036 }
Chris@101 1037
Chris@101 1038 reference_type value() &
Chris@101 1039 {
Chris@101 1040 if (this->is_initialized())
Chris@101 1041 return this->get() ;
Chris@101 1042 else
Chris@101 1043 throw_exception(bad_optional_access());
Chris@101 1044 }
Chris@101 1045
Chris@101 1046 reference_type_of_temporary_wrapper value() &&
Chris@101 1047 {
Chris@101 1048 if (this->is_initialized())
Chris@101 1049 return base::types::move(this->get()) ;
Chris@101 1050 else
Chris@101 1051 throw_exception(bad_optional_access());
Chris@101 1052 }
Chris@16 1053
Chris@101 1054 #else
Chris@101 1055 reference_const_type value() const
Chris@101 1056 {
Chris@101 1057 if (this->is_initialized())
Chris@101 1058 return this->get() ;
Chris@101 1059 else
Chris@101 1060 throw_exception(bad_optional_access());
Chris@101 1061 }
Chris@101 1062
Chris@101 1063 reference_type value()
Chris@101 1064 {
Chris@101 1065 if (this->is_initialized())
Chris@101 1066 return this->get() ;
Chris@101 1067 else
Chris@101 1068 throw_exception(bad_optional_access());
Chris@101 1069 }
Chris@101 1070 #endif
Chris@101 1071
Chris@101 1072
Chris@101 1073 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
Chris@101 1074 template <class U>
Chris@101 1075 value_type value_or ( U&& v ) const&
Chris@101 1076 {
Chris@101 1077 if (this->is_initialized())
Chris@101 1078 return get();
Chris@101 1079 else
Chris@101 1080 return boost::forward<U>(v);
Chris@101 1081 }
Chris@101 1082
Chris@101 1083 template <class U>
Chris@101 1084 value_type value_or ( U&& v ) &&
Chris@101 1085 {
Chris@101 1086 if (this->is_initialized())
Chris@101 1087 return base::types::move(get());
Chris@101 1088 else
Chris@101 1089 return boost::forward<U>(v);
Chris@101 1090 }
Chris@101 1091 #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 1092 template <class U>
Chris@101 1093 value_type value_or ( U&& v ) const
Chris@101 1094 {
Chris@101 1095 if (this->is_initialized())
Chris@101 1096 return get();
Chris@101 1097 else
Chris@101 1098 return boost::forward<U>(v);
Chris@101 1099 }
Chris@101 1100 #else
Chris@101 1101 template <class U>
Chris@101 1102 value_type value_or ( U const& v ) const
Chris@101 1103 {
Chris@101 1104 if (this->is_initialized())
Chris@101 1105 return get();
Chris@101 1106 else
Chris@101 1107 return v;
Chris@101 1108 }
Chris@101 1109
Chris@101 1110 template <class U>
Chris@101 1111 value_type value_or ( U& v ) const
Chris@101 1112 {
Chris@101 1113 if (this->is_initialized())
Chris@101 1114 return get();
Chris@101 1115 else
Chris@101 1116 return v;
Chris@101 1117 }
Chris@101 1118 #endif
Chris@101 1119
Chris@101 1120
Chris@101 1121 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
Chris@101 1122 template <typename F>
Chris@101 1123 value_type value_or_eval ( F f ) const&
Chris@101 1124 {
Chris@101 1125 if (this->is_initialized())
Chris@101 1126 return get();
Chris@101 1127 else
Chris@101 1128 return f();
Chris@101 1129 }
Chris@101 1130
Chris@101 1131 template <typename F>
Chris@101 1132 value_type value_or_eval ( F f ) &&
Chris@101 1133 {
Chris@101 1134 if (this->is_initialized())
Chris@101 1135 return base::types::move(get());
Chris@101 1136 else
Chris@101 1137 return f();
Chris@101 1138 }
Chris@101 1139 #else
Chris@101 1140 template <typename F>
Chris@101 1141 value_type value_or_eval ( F f ) const
Chris@101 1142 {
Chris@101 1143 if (this->is_initialized())
Chris@101 1144 return get();
Chris@101 1145 else
Chris@101 1146 return f();
Chris@101 1147 }
Chris@101 1148 #endif
Chris@101 1149
Chris@101 1150 bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
Chris@101 1151
Chris@101 1152 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
Chris@16 1153 } ;
Chris@16 1154
Chris@101 1155 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 1156 template<class T>
Chris@101 1157 class optional<T&&>
Chris@101 1158 {
Chris@101 1159 BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
Chris@101 1160 } ;
Chris@101 1161 #endif
Chris@101 1162
Chris@16 1163 // Returns optional<T>(v)
Chris@16 1164 template<class T>
Chris@16 1165 inline
Chris@16 1166 optional<T> make_optional ( T const& v )
Chris@16 1167 {
Chris@16 1168 return optional<T>(v);
Chris@16 1169 }
Chris@16 1170
Chris@16 1171 // Returns optional<T>(cond,v)
Chris@16 1172 template<class T>
Chris@16 1173 inline
Chris@16 1174 optional<T> make_optional ( bool cond, T const& v )
Chris@16 1175 {
Chris@16 1176 return optional<T>(cond,v);
Chris@16 1177 }
Chris@16 1178
Chris@16 1179 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
Chris@16 1180 // No-throw
Chris@16 1181 template<class T>
Chris@16 1182 inline
Chris@16 1183 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
Chris@16 1184 get ( optional<T> const& opt )
Chris@16 1185 {
Chris@16 1186 return opt.get() ;
Chris@16 1187 }
Chris@16 1188
Chris@16 1189 template<class T>
Chris@16 1190 inline
Chris@16 1191 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
Chris@16 1192 get ( optional<T>& opt )
Chris@16 1193 {
Chris@16 1194 return opt.get() ;
Chris@16 1195 }
Chris@16 1196
Chris@16 1197 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
Chris@16 1198 // No-throw
Chris@16 1199 template<class T>
Chris@16 1200 inline
Chris@16 1201 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
Chris@16 1202 get ( optional<T> const* opt )
Chris@16 1203 {
Chris@16 1204 return opt->get_ptr() ;
Chris@16 1205 }
Chris@16 1206
Chris@16 1207 template<class T>
Chris@16 1208 inline
Chris@16 1209 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
Chris@16 1210 get ( optional<T>* opt )
Chris@16 1211 {
Chris@16 1212 return opt->get_ptr() ;
Chris@16 1213 }
Chris@16 1214
Chris@16 1215 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
Chris@16 1216 // No-throw
Chris@16 1217 template<class T>
Chris@16 1218 inline
Chris@16 1219 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
Chris@16 1220 get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
Chris@16 1221 {
Chris@16 1222 return opt.get_value_or(v) ;
Chris@16 1223 }
Chris@16 1224
Chris@16 1225 template<class T>
Chris@16 1226 inline
Chris@16 1227 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
Chris@16 1228 get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
Chris@16 1229 {
Chris@16 1230 return opt.get_value_or(v) ;
Chris@16 1231 }
Chris@16 1232
Chris@16 1233 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
Chris@16 1234 // No-throw
Chris@16 1235 template<class T>
Chris@16 1236 inline
Chris@16 1237 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
Chris@16 1238 get_pointer ( optional<T> const& opt )
Chris@16 1239 {
Chris@16 1240 return opt.get_ptr() ;
Chris@16 1241 }
Chris@16 1242
Chris@16 1243 template<class T>
Chris@16 1244 inline
Chris@16 1245 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
Chris@16 1246 get_pointer ( optional<T>& opt )
Chris@16 1247 {
Chris@16 1248 return opt.get_ptr() ;
Chris@16 1249 }
Chris@16 1250
Chris@101 1251 // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
Chris@101 1252 template<class CharType, class CharTrait>
Chris@101 1253 std::basic_ostream<CharType, CharTrait>&
Chris@101 1254 operator<<(std::basic_ostream<CharType, CharTrait>& out, optional_detail::optional_tag const& v)
Chris@101 1255 {
Chris@101 1256 BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
Chris@101 1257 }
Chris@101 1258
Chris@16 1259 // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
Chris@16 1260 // WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
Chris@16 1261
Chris@16 1262
Chris@16 1263 //
Chris@16 1264 // optional<T> vs optional<T> cases
Chris@16 1265 //
Chris@16 1266
Chris@16 1267 template<class T>
Chris@16 1268 inline
Chris@16 1269 bool operator == ( optional<T> const& x, optional<T> const& y )
Chris@16 1270 { return equal_pointees(x,y); }
Chris@16 1271
Chris@16 1272 template<class T>
Chris@16 1273 inline
Chris@16 1274 bool operator < ( optional<T> const& x, optional<T> const& y )
Chris@16 1275 { return less_pointees(x,y); }
Chris@16 1276
Chris@16 1277 template<class T>
Chris@16 1278 inline
Chris@16 1279 bool operator != ( optional<T> const& x, optional<T> const& y )
Chris@16 1280 { return !( x == y ) ; }
Chris@16 1281
Chris@16 1282 template<class T>
Chris@16 1283 inline
Chris@16 1284 bool operator > ( optional<T> const& x, optional<T> const& y )
Chris@16 1285 { return y < x ; }
Chris@16 1286
Chris@16 1287 template<class T>
Chris@16 1288 inline
Chris@16 1289 bool operator <= ( optional<T> const& x, optional<T> const& y )
Chris@16 1290 { return !( y < x ) ; }
Chris@16 1291
Chris@16 1292 template<class T>
Chris@16 1293 inline
Chris@16 1294 bool operator >= ( optional<T> const& x, optional<T> const& y )
Chris@16 1295 { return !( x < y ) ; }
Chris@16 1296
Chris@16 1297
Chris@16 1298 //
Chris@16 1299 // optional<T> vs T cases
Chris@16 1300 //
Chris@16 1301 template<class T>
Chris@16 1302 inline
Chris@16 1303 bool operator == ( optional<T> const& x, T const& y )
Chris@16 1304 { return equal_pointees(x, optional<T>(y)); }
Chris@16 1305
Chris@16 1306 template<class T>
Chris@16 1307 inline
Chris@16 1308 bool operator < ( optional<T> const& x, T const& y )
Chris@16 1309 { return less_pointees(x, optional<T>(y)); }
Chris@16 1310
Chris@16 1311 template<class T>
Chris@16 1312 inline
Chris@16 1313 bool operator != ( optional<T> const& x, T const& y )
Chris@16 1314 { return !( x == y ) ; }
Chris@16 1315
Chris@16 1316 template<class T>
Chris@16 1317 inline
Chris@16 1318 bool operator > ( optional<T> const& x, T const& y )
Chris@16 1319 { return y < x ; }
Chris@16 1320
Chris@16 1321 template<class T>
Chris@16 1322 inline
Chris@16 1323 bool operator <= ( optional<T> const& x, T const& y )
Chris@16 1324 { return !( y < x ) ; }
Chris@16 1325
Chris@16 1326 template<class T>
Chris@16 1327 inline
Chris@16 1328 bool operator >= ( optional<T> const& x, T const& y )
Chris@16 1329 { return !( x < y ) ; }
Chris@16 1330
Chris@16 1331 //
Chris@16 1332 // T vs optional<T> cases
Chris@16 1333 //
Chris@16 1334
Chris@16 1335 template<class T>
Chris@16 1336 inline
Chris@16 1337 bool operator == ( T const& x, optional<T> const& y )
Chris@16 1338 { return equal_pointees( optional<T>(x), y ); }
Chris@16 1339
Chris@16 1340 template<class T>
Chris@16 1341 inline
Chris@16 1342 bool operator < ( T const& x, optional<T> const& y )
Chris@16 1343 { return less_pointees( optional<T>(x), y ); }
Chris@16 1344
Chris@16 1345 template<class T>
Chris@16 1346 inline
Chris@16 1347 bool operator != ( T const& x, optional<T> const& y )
Chris@16 1348 { return !( x == y ) ; }
Chris@16 1349
Chris@16 1350 template<class T>
Chris@16 1351 inline
Chris@16 1352 bool operator > ( T const& x, optional<T> const& y )
Chris@16 1353 { return y < x ; }
Chris@16 1354
Chris@16 1355 template<class T>
Chris@16 1356 inline
Chris@16 1357 bool operator <= ( T const& x, optional<T> const& y )
Chris@16 1358 { return !( y < x ) ; }
Chris@16 1359
Chris@16 1360 template<class T>
Chris@16 1361 inline
Chris@16 1362 bool operator >= ( T const& x, optional<T> const& y )
Chris@16 1363 { return !( x < y ) ; }
Chris@16 1364
Chris@16 1365
Chris@16 1366 //
Chris@16 1367 // optional<T> vs none cases
Chris@16 1368 //
Chris@16 1369
Chris@16 1370 template<class T>
Chris@16 1371 inline
Chris@101 1372 bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
Chris@101 1373 { return !x; }
Chris@16 1374
Chris@16 1375 template<class T>
Chris@16 1376 inline
Chris@16 1377 bool operator < ( optional<T> const& x, none_t )
Chris@16 1378 { return less_pointees(x,optional<T>() ); }
Chris@16 1379
Chris@16 1380 template<class T>
Chris@16 1381 inline
Chris@101 1382 bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
Chris@101 1383 { return bool(x); }
Chris@16 1384
Chris@16 1385 template<class T>
Chris@16 1386 inline
Chris@16 1387 bool operator > ( optional<T> const& x, none_t y )
Chris@16 1388 { return y < x ; }
Chris@16 1389
Chris@16 1390 template<class T>
Chris@16 1391 inline
Chris@16 1392 bool operator <= ( optional<T> const& x, none_t y )
Chris@16 1393 { return !( y < x ) ; }
Chris@16 1394
Chris@16 1395 template<class T>
Chris@16 1396 inline
Chris@16 1397 bool operator >= ( optional<T> const& x, none_t y )
Chris@16 1398 { return !( x < y ) ; }
Chris@16 1399
Chris@16 1400 //
Chris@16 1401 // none vs optional<T> cases
Chris@16 1402 //
Chris@16 1403
Chris@16 1404 template<class T>
Chris@16 1405 inline
Chris@101 1406 bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
Chris@101 1407 { return !y; }
Chris@16 1408
Chris@16 1409 template<class T>
Chris@16 1410 inline
Chris@16 1411 bool operator < ( none_t , optional<T> const& y )
Chris@16 1412 { return less_pointees(optional<T>() ,y); }
Chris@16 1413
Chris@16 1414 template<class T>
Chris@16 1415 inline
Chris@101 1416 bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
Chris@101 1417 { return bool(y); }
Chris@16 1418
Chris@16 1419 template<class T>
Chris@16 1420 inline
Chris@16 1421 bool operator > ( none_t x, optional<T> const& y )
Chris@16 1422 { return y < x ; }
Chris@16 1423
Chris@16 1424 template<class T>
Chris@16 1425 inline
Chris@16 1426 bool operator <= ( none_t x, optional<T> const& y )
Chris@16 1427 { return !( y < x ) ; }
Chris@16 1428
Chris@16 1429 template<class T>
Chris@16 1430 inline
Chris@16 1431 bool operator >= ( none_t x, optional<T> const& y )
Chris@16 1432 { return !( x < y ) ; }
Chris@16 1433
Chris@16 1434 namespace optional_detail {
Chris@16 1435
Chris@16 1436 template<bool use_default_constructor> struct swap_selector;
Chris@16 1437
Chris@16 1438 template<>
Chris@16 1439 struct swap_selector<true>
Chris@16 1440 {
Chris@16 1441 template<class T>
Chris@16 1442 static void optional_swap ( optional<T>& x, optional<T>& y )
Chris@16 1443 {
Chris@16 1444 const bool hasX = !!x;
Chris@16 1445 const bool hasY = !!y;
Chris@16 1446
Chris@16 1447 if ( !hasX && !hasY )
Chris@16 1448 return;
Chris@16 1449
Chris@16 1450 if( !hasX )
Chris@16 1451 x = boost::in_place();
Chris@16 1452 else if ( !hasY )
Chris@16 1453 y = boost::in_place();
Chris@16 1454
Chris@16 1455 // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
Chris@16 1456 boost::swap(x.get(),y.get());
Chris@16 1457
Chris@16 1458 if( !hasX )
Chris@16 1459 y = boost::none ;
Chris@16 1460 else if( !hasY )
Chris@16 1461 x = boost::none ;
Chris@16 1462 }
Chris@16 1463 };
Chris@16 1464
Chris@101 1465 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@101 1466 template<>
Chris@101 1467 struct swap_selector<false>
Chris@101 1468 {
Chris@101 1469 template<class T>
Chris@101 1470 static void optional_swap ( optional<T>& x, optional<T>& y )
Chris@101 1471 //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
Chris@101 1472 {
Chris@101 1473 if(x)
Chris@101 1474 {
Chris@101 1475 if (y)
Chris@101 1476 {
Chris@101 1477 boost::swap(*x, *y);
Chris@101 1478 }
Chris@101 1479 else
Chris@101 1480 {
Chris@101 1481 y = boost::move(*x);
Chris@101 1482 x = boost::none;
Chris@101 1483 }
Chris@101 1484 }
Chris@101 1485 else
Chris@101 1486 {
Chris@101 1487 if (y)
Chris@101 1488 {
Chris@101 1489 x = boost::move(*y);
Chris@101 1490 y = boost::none;
Chris@101 1491 }
Chris@101 1492 }
Chris@101 1493 }
Chris@101 1494 };
Chris@101 1495 #else
Chris@16 1496 template<>
Chris@16 1497 struct swap_selector<false>
Chris@16 1498 {
Chris@16 1499 template<class T>
Chris@16 1500 static void optional_swap ( optional<T>& x, optional<T>& y )
Chris@16 1501 {
Chris@16 1502 const bool hasX = !!x;
Chris@16 1503 const bool hasY = !!y;
Chris@16 1504
Chris@16 1505 if ( !hasX && hasY )
Chris@16 1506 {
Chris@16 1507 x = y.get();
Chris@16 1508 y = boost::none ;
Chris@16 1509 }
Chris@16 1510 else if ( hasX && !hasY )
Chris@16 1511 {
Chris@16 1512 y = x.get();
Chris@16 1513 x = boost::none ;
Chris@16 1514 }
Chris@16 1515 else if ( hasX && hasY )
Chris@16 1516 {
Chris@16 1517 // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
Chris@16 1518 boost::swap(x.get(),y.get());
Chris@16 1519 }
Chris@16 1520 }
Chris@16 1521 };
Chris@101 1522 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
Chris@16 1523
Chris@16 1524 } // namespace optional_detail
Chris@16 1525
Chris@16 1526 template<class T>
Chris@16 1527 struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
Chris@16 1528
Chris@16 1529 template<class T> inline void swap ( optional<T>& x, optional<T>& y )
Chris@101 1530 //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
Chris@16 1531 {
Chris@16 1532 optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
Chris@16 1533 }
Chris@16 1534
Chris@16 1535 } // namespace boost
Chris@16 1536
Chris@16 1537 #endif