diff options
Diffstat (limited to 'boost/optional/optional.hpp')
-rw-r--r-- | boost/optional/optional.hpp | 117 |
1 files changed, 71 insertions, 46 deletions
diff --git a/boost/optional/optional.hpp b/boost/optional/optional.hpp index 07c4bd39ab..afcb8079e2 100644 --- a/boost/optional/optional.hpp +++ b/boost/optional/optional.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. -// Copyright (C) 2014 Andrzej Krzemienski. +// Copyright (C) 2014, 2015 Andrzej Krzemienski. // // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -57,6 +57,10 @@ #include <boost/optional/optional_fwd.hpp> +#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES) +#define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif + #if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700) // AFAICT only Intel 7 correctly resolves the overload set // that includes the in-place factory taking functions, @@ -148,7 +152,7 @@ struct types_when_isnt_ref { typedef T const& reference_const_type ; typedef T & reference_type ; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES typedef T && rval_reference_type ; typedef T && reference_type_of_temporary_wrapper; #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES @@ -171,7 +175,7 @@ struct types_when_is_ref typedef raw_type& reference_const_type ; typedef raw_type& reference_type ; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ; typedef raw_type& reference_type_of_temporary_wrapper; static reference_type move(reference_type r) { return r; } @@ -184,7 +188,7 @@ struct types_when_is_ref template <class To, class From> void prevent_binding_rvalue_ref_to_optional_lvalue_ref() { -#ifndef BOOST_OPTIONAL_ALLOW_BINDING_TO_RVALUES +#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES BOOST_STATIC_ASSERT_MSG( !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value, "binding rvalue references to optional lvalue references is disallowed"); @@ -226,7 +230,7 @@ class optional_base : public optional_tag protected: typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ; typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ; typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; #endif @@ -255,7 +259,7 @@ class optional_base : public optional_tag construct(val); } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // move-construct an optional<T> initialized from an rvalue-ref to 'val'. // Can throw if T::T(T&&) does optional_base ( rval_reference_type val ) @@ -286,7 +290,7 @@ class optional_base : public optional_tag construct(rhs.get_impl()); } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Creates a deep move of another optional<T> // Can throw if T::T(T&&) does optional_base ( optional_base&& rhs ) @@ -298,7 +302,7 @@ class optional_base : public optional_tag } #endif -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template<class Expr, class PtrExpr> explicit optional_base ( Expr&& expr, PtrExpr const* tag ) @@ -342,7 +346,7 @@ class optional_base : public optional_tag } } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Assigns from another optional<T> (deep-moves the rhs value) void assign ( optional_base&& rhs ) { @@ -367,17 +371,26 @@ class optional_base : public optional_tag if (is_initialized()) { if ( rhs.is_initialized() ) - assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() ); +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + assign_value(rhs.get(), is_reference_predicate() ); +#else + assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() ); +#endif + else destroy(); } else { if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + construct(rhs.get()); +#else construct(static_cast<value_type>(rhs.get())); +#endif } } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value) template<class U> void assign ( optional<U>&& rhs ) @@ -405,7 +418,7 @@ class optional_base : public optional_tag else construct(val); } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Assigns from a T (deep-moves the rhs value) void assign ( rval_reference_type val ) { @@ -421,7 +434,7 @@ class optional_base : public optional_tag #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template<class Expr, class ExprPtr> void assign_expr ( Expr&& expr, ExprPtr const* tag ) { @@ -466,7 +479,7 @@ class optional_base : public optional_tag m_initialized = true ; } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES void construct ( rval_reference_type val ) { ::new (m_storage.address()) internal_type( types::move(val) ) ; @@ -475,7 +488,7 @@ class optional_base : public optional_tag #endif -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) // Constructs in-place // upon exception *this is always uninitialized template<class... Args> @@ -485,7 +498,7 @@ class optional_base : public optional_tag ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... ); m_initialized = true ; } -#elif (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template<class Arg> void emplace_assign ( Arg&& arg ) { @@ -513,7 +526,7 @@ class optional_base : public optional_tag #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Constructs in-place using the given factory template<class Expr> void construct ( Expr&& factory, in_place_factory_base const* ) @@ -584,7 +597,7 @@ class optional_base : public optional_tag #endif -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Constructs using any expression implicitly convertible to the single argument // of a one-argument T constructor. // Converting constructions of optional<T> from optional<U> uses this function with @@ -642,7 +655,7 @@ class optional_base : public optional_tag // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error // instead of choosing the wrong overload // -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>) template<class Expr> void construct ( Expr&& expr, optional_tag const* ) @@ -673,7 +686,7 @@ class optional_base : public optional_tag void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; } void assign_value ( argument_type val, is_reference_tag ) { construct(val); } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); } void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); } #endif @@ -750,7 +763,7 @@ class optional : public optional_detail::optional_base<T> typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ; typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; #endif @@ -770,7 +783,7 @@ class optional : public optional_detail::optional_base<T> // Can throw if T::T(T const&) does optional ( argument_type val ) : base(val) {} -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Creates an optional<T> initialized with 'move(val)'. // Can throw if T::T(T &&) does optional ( rval_reference_type val ) : base( boost::forward<T>(val) ) @@ -795,7 +808,7 @@ class optional : public optional_detail::optional_base<T> this->construct(rhs.get()); } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Creates a deep move of another convertible optional<U> // Requires a valid conversion from U to T. // Can throw if T::T(U&&) does @@ -819,7 +832,7 @@ class optional : public optional_detail::optional_base<T> // even though explicit overloads are present for these. // Depending on the above some T ctor is called. // Can throw if the resolved T ctor throws. -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template<class Expr> @@ -834,14 +847,14 @@ class optional : public optional_detail::optional_base<T> #else template<class Expr> explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {} -#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT // Creates a deep copy of another optional<T> // Can throw if T::T(T const&) does optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {} -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Creates a deep move of another optional<T> // Can throw if T::T(T&&) does optional ( optional && rhs ) @@ -856,7 +869,7 @@ class optional : public optional_detail::optional_base<T> #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) // Assigns from an expression. See corresponding constructor. // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template<class Expr> BOOST_DEDUCED_TYPENAME boost::disable_if_c< @@ -878,7 +891,7 @@ class optional : public optional_detail::optional_base<T> this->assign_expr(expr,boost::addressof(expr)); return *this ; } -#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value) @@ -891,7 +904,7 @@ class optional : public optional_detail::optional_base<T> return *this ; } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value) // Requires a valid conversion from U to T. // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED @@ -912,7 +925,7 @@ class optional : public optional_detail::optional_base<T> return *this ; } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Assigns from another optional<T> (deep-moves the rhs value) optional& operator= ( optional && rhs ) BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value) @@ -930,7 +943,7 @@ class optional : public optional_detail::optional_base<T> return *this ; } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Assigns from a T (deep-moves the rhs value) optional& operator= ( rval_reference_type val ) { @@ -949,7 +962,7 @@ class optional : public optional_detail::optional_base<T> return *this ; } -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) // Constructs in-place // upon exception *this is always uninitialized template<class... Args> @@ -957,7 +970,7 @@ class optional : public optional_detail::optional_base<T> { this->emplace_assign( boost::forward<Args>(args)... ); } -#elif (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template<class Arg> void emplace ( Arg&& arg ) { @@ -1004,16 +1017,16 @@ class optional : public optional_detail::optional_base<T> // Returns a reference to the value if this is initialized, otherwise, // the behaviour is UNDEFINED // No-throw -#ifndef BOOST_NO_CXX11_REF_QUALIFIERS +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) reference_const_type operator *() const& { return this->get() ; } reference_type operator *() & { return this->get() ; } - reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; } + reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; } #else reference_const_type operator *() const { return this->get() ; } reference_type operator *() { return this->get() ; } #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS -#ifndef BOOST_NO_CXX11_REF_QUALIFIERS +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) reference_const_type value() const& { if (this->is_initialized()) @@ -1033,7 +1046,7 @@ class optional : public optional_detail::optional_base<T> reference_type_of_temporary_wrapper value() && { if (this->is_initialized()) - return boost::move(this->get()) ; + return base::types::move(this->get()) ; else throw_exception(bad_optional_access()); } @@ -1071,11 +1084,11 @@ class optional : public optional_detail::optional_base<T> value_type value_or ( U&& v ) && { if (this->is_initialized()) - return boost::move(get()); + return base::types::move(get()); else return boost::forward<U>(v); } -#elif !defined BOOST_NO_CXX11_RVALUE_REFERENCES +#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template <class U> value_type value_or ( U&& v ) const { @@ -1093,6 +1106,15 @@ class optional : public optional_detail::optional_base<T> else return v; } + + template <class U> + value_type value_or ( U& v ) const + { + if (this->is_initialized()) + return get(); + else + return v; + } #endif @@ -1110,7 +1132,7 @@ class optional : public optional_detail::optional_base<T> value_type value_or_eval ( F f ) && { if (this->is_initialized()) - return boost::move(get()); + return base::types::move(get()); else return f(); } @@ -1130,7 +1152,7 @@ class optional : public optional_detail::optional_base<T> BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() } ; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template<class T> class optional<T&&> { @@ -1226,10 +1248,13 @@ get_pointer ( optional<T>& opt ) return opt.get_ptr() ; } -// Forward declaration to prevent operator safe-bool from being used. -template<class CharType, class CharTrait, class T> +// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header. +template<class CharType, class CharTrait> std::basic_ostream<CharType, CharTrait>& -operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v); +operator<<(std::basic_ostream<CharType, CharTrait>& out, optional_detail::optional_tag const& v) +{ + BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>"); +} // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). // WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead. @@ -1437,7 +1462,7 @@ struct swap_selector<true> } }; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template<> struct swap_selector<false> { @@ -1494,7 +1519,7 @@ struct swap_selector<false> } } }; -#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES } // namespace optional_detail |