summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2014-10-19 20:22:58 (GMT)
committerTobias Markmann <tm@ayena.de>2014-10-20 13:49:33 (GMT)
commit6b22dfcf59474dd016a0355a3102a1dd3692d92c (patch)
tree2b1fd33be433a91e81fee84fdc2bf1b52575d934 /3rdParty/Boost/src/boost/optional/optional.hpp
parent38b0cb785fea8eae5e48fae56440695fdfd10ee1 (diff)
downloadswift-6b22dfcf59474dd016a0355a3102a1dd3692d92c.zip
swift-6b22dfcf59474dd016a0355a3102a1dd3692d92c.tar.bz2
Update Boost in 3rdParty to version 1.56.0.
This updates Boost in our 3rdParty directory to version 1.56.0. Updated our update.sh script to stop on error. Changed error reporting in SwiftTools/CrashReporter.cpp to SWIFT_LOG due to missing include of <iostream> with newer Boost. Change-Id: I4b35c77de951333979a524097f35f5f83d325edc
Diffstat (limited to '3rdParty/Boost/src/boost/optional/optional.hpp')
-rw-r--r--3rdParty/Boost/src/boost/optional/optional.hpp679
1 files changed, 600 insertions, 79 deletions
diff --git a/3rdParty/Boost/src/boost/optional/optional.hpp b/3rdParty/Boost/src/boost/optional/optional.hpp
index 0d6dba4..07c4bd3 100644
--- a/3rdParty/Boost/src/boost/optional/optional.hpp
+++ b/3rdParty/Boost/src/boost/optional/optional.hpp
@@ -1,4 +1,5 @@
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2014 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
@@ -11,58 +12,55 @@
//
// Revisions:
// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
+// 05 May 2014 (Added move semantics) Andrzej Krzemienski
//
#ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
#include <new>
#include <algorithm>
+#include <iosfwd>
#include <boost/config.hpp>
#include <boost/assert.hpp>
+#include <boost/core/explicit_operator_bool.hpp>
+#include <boost/optional/bad_optional_access.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/type.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/has_nothrow_constructor.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/detail/reference_content.hpp>
+#include <boost/move/utility.hpp>
#include <boost/none.hpp>
-#include <boost/utility/swap.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/utility/compare_pointees.hpp>
+#include <boost/utility/enable_if.hpp>
#include <boost/utility/in_place_factory.hpp>
+#include <boost/utility/swap.hpp>
-#include <boost/optional/optional_fwd.hpp>
-#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
-// VC6.0 has the following bug:
-// When a templated assignment operator exist, an implicit conversion
-// constructing an optional<T> is used when assigment of the form:
-// optional<T> opt ; opt = T(...);
-// is compiled.
-// However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
-// Therefore, for VC6.0 templated assignment is disabled.
-//
-#define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
-#endif
-#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
-// VC7.0 has the following bug:
-// When both a non-template and a template copy-ctor exist
-// and the templated version is made 'explicit', the explicit is also
-// given to the non-templated version, making the class non-implicitely-copyable.
-//
-#define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
-#endif
+#include <boost/optional/optional_fwd.hpp>
-#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
-// AFAICT only VC7.1 correctly resolves the overload set
+#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,
-// so for the other VC versions, in-place factory support
+// so for the other icc versions, in-place factory support
// is disabled
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#endif
@@ -83,8 +81,7 @@
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
#endif
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
- && !defined(__INTEL_COMPILER)
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
// regard to violation of the strict aliasing rules. The optional< T > storage type is marked
// with this attribute in order to let the compiler know that it will alias objects of type T
@@ -115,7 +112,6 @@ class typed_in_place_factory_base ;
template<class T> void swap ( optional<T>& x, optional<T>& y );
namespace optional_detail {
-
// This local class is used instead of that in "aligned_storage.hpp"
// because I've found the 'official' class to ICE BCB5.5
// when some types are used with optional<>
@@ -127,7 +123,7 @@ class aligned_storage
union
// This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
- __attribute__((may_alias))
+ __attribute__((__may_alias__))
#endif
dummy_u
{
@@ -152,22 +148,49 @@ struct types_when_isnt_ref
{
typedef T const& reference_const_type ;
typedef T & reference_type ;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef T && rval_reference_type ;
+ typedef T && reference_type_of_temporary_wrapper;
+#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+ // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
+ // causes warnings about returning references to a temporary.
+ static T&& move(T&& r) { return r; }
+#else
+ static rval_reference_type move(reference_type r) { return boost::move(r); }
+#endif
+#endif
typedef T const* pointer_const_type ;
typedef T * pointer_type ;
typedef T const& argument_type ;
} ;
+
template<class T>
struct types_when_is_ref
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
- typedef raw_type& reference_const_type ;
- typedef raw_type& reference_type ;
- typedef raw_type* pointer_const_type ;
- typedef raw_type* pointer_type ;
- typedef raw_type& argument_type ;
+ typedef raw_type& reference_const_type ;
+ typedef raw_type& reference_type ;
+#ifndef BOOST_NO_CXX11_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; }
+#endif
+ typedef raw_type* pointer_const_type ;
+ typedef raw_type* pointer_type ;
+ typedef raw_type& argument_type ;
} ;
+template <class To, class From>
+void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
+{
+#ifndef BOOST_OPTIONAL_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");
+#endif
+}
+
struct optional_tag {} ;
template<class T>
@@ -201,10 +224,12 @@ class optional_base : public optional_tag
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
protected:
- typedef bool (this_type::*unspecified_bool_type)() const;
-
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
+ 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
typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
@@ -230,6 +255,17 @@ class optional_base : public optional_tag
construct(val);
}
+#ifndef BOOST_NO_CXX11_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 )
+ :
+ m_initialized(false)
+ {
+ construct( boost::move(val) );
+ }
+#endif
+
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
// Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val )
@@ -250,7 +286,29 @@ class optional_base : public optional_tag
construct(rhs.get_impl());
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Creates a deep move of another optional<T>
+ // Can throw if T::T(T&&) does
+ optional_base ( optional_base&& rhs )
+ :
+ m_initialized(false)
+ {
+ if ( rhs.is_initialized() )
+ construct( boost::move(rhs.get_impl()) );
+ }
+#endif
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template<class Expr, class PtrExpr>
+ explicit optional_base ( Expr&& expr, PtrExpr const* tag )
+ :
+ m_initialized(false)
+ {
+ construct(boost::forward<Expr>(expr),tag);
+ }
+#else
// This is used for both converting and in-place constructions.
// Derived classes use the 'tag' to select the appropriate
// implementation (the correct 'construct()' overload)
@@ -262,6 +320,7 @@ class optional_base : public optional_tag
construct(expr,tag);
}
+#endif
// No-throw (assuming T::~T() doesn't)
@@ -282,6 +341,24 @@ class optional_base : public optional_tag
construct(rhs.get_impl());
}
}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Assigns from another optional<T> (deep-moves the rhs value)
+ void assign ( optional_base&& rhs )
+ {
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(boost::move(rhs.get_impl()));
+ }
+ }
+#endif
// Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
template<class U>
@@ -300,6 +377,26 @@ class optional_base : public optional_tag
}
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
+ template<class U>
+ void assign ( optional<U>&& rhs )
+ {
+ typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(static_cast<ref_type>(rhs.get()));
+ }
+ }
+#endif
+
// Assigns from a T (deep-copies the rhs value)
void assign ( argument_type val )
{
@@ -307,28 +404,50 @@ class optional_base : public optional_tag
assign_value(val, is_reference_predicate() );
else construct(val);
}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ void assign ( rval_reference_type val )
+ {
+ if (is_initialized())
+ assign_value( boost::move(val), is_reference_predicate() );
+ else construct( boost::move(val) );
+ }
+#endif
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
- void assign ( none_t ) { destroy(); }
+ void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template<class Expr, class ExprPtr>
+ void assign_expr ( Expr&& expr, ExprPtr const* tag )
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
+ else construct(boost::forward<Expr>(expr),tag);
+ }
+#else
template<class Expr>
void assign_expr ( Expr const& expr, Expr const* tag )
- {
- if (is_initialized())
- assign_expr_to_initialized(expr,tag);
- else construct(expr,tag);
- }
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(expr,tag);
+ else construct(expr,tag);
+ }
+#endif
+
#endif
public :
- // Destroys the current value, if any, leaving this UNINITIALIZED
+ // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
- void reset() { destroy(); }
+ void reset() BOOST_NOEXCEPT { destroy(); }
- // Replaces the current value -if any- with 'val'
+ // **DEPPRECATED** Replaces the current value -if any- with 'val'
void reset ( argument_type val ) { assign(val); }
// Returns a pointer to the value if this is initialized, otherwise,
@@ -343,11 +462,92 @@ class optional_base : public optional_tag
void construct ( argument_type val )
{
- new (m_storage.address()) internal_type(val) ;
+ ::new (m_storage.address()) internal_type(val) ;
+ m_initialized = true ;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ void construct ( rval_reference_type val )
+ {
+ ::new (m_storage.address()) internal_type( types::move(val) ) ;
+ m_initialized = true ;
+ }
+#endif
+
+
+#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // Constructs in-place
+ // upon exception *this is always uninitialized
+ template<class... Args>
+ void emplace_assign ( Args&&... args )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
+ m_initialized = true ;
+ }
+#elif (!defined BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template<class Arg>
+ void emplace_assign ( Arg&& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
+ m_initialized = true ;
+ }
+#else
+ template<class Arg>
+ void emplace_assign ( const Arg& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( arg );
+ m_initialized = true ;
+ }
+
+ template<class Arg>
+ void emplace_assign ( Arg& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( arg );
m_initialized = true ;
}
+#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Constructs in-place using the given factory
+ template<class Expr>
+ void construct ( Expr&& factory, in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ boost_optional_detail::construct<value_type>(factory, m_storage.address());
+ m_initialized = true ;
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void construct ( Expr&& factory, typed_in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ factory.apply(m_storage.address()) ;
+ m_initialized = true ;
+ }
+
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+#else
// Constructs in-place using the given factory
template<class Expr>
void construct ( Expr const& factory, in_place_factory_base const* )
@@ -382,7 +582,31 @@ class optional_base : public optional_tag
}
#endif
- // Constructs using any expression implicitely convertible to the single argument
+#endif
+
+#ifndef BOOST_NO_CXX11_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
+ // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
+ template<class Expr>
+ void construct ( Expr&& expr, void const* )
+ {
+ new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
+ m_initialized = true ;
+ }
+
+ // Assigns using a form any expression implicitly convertible to the single argument
+ // of a T's assignment operator.
+ // Converting assignments of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& expr, void const* )
+ {
+ assign_value(boost::forward<Expr>(expr), is_reference_predicate());
+ }
+#else
+ // 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
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
@@ -393,7 +617,7 @@ class optional_base : public optional_tag
m_initialized = true ;
}
- // Assigns using a form any expression implicitely convertible to the single argument
+ // Assigns using a form any expression implicitly convertible to the single argument
// of a T's assignment operator.
// Converting assignments of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
@@ -403,6 +627,8 @@ class optional_base : public optional_tag
assign_value(expr, is_reference_predicate());
}
+#endif
+
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
// BCB5.64 (and probably lower versions) workaround.
// The in-place factories are supported by means of catch-all constructors
@@ -416,6 +642,20 @@ 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
+ // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
+ template<class Expr>
+ void construct ( Expr&& expr, optional_tag const* )
+ {
+ if ( expr.is_initialized() )
+ {
+ // An exception can be thrown here.
+ // It it happens, THIS will be left uninitialized.
+ new (m_storage.address()) internal_type(types::move(expr.get())) ;
+ m_initialized = true ;
+ }
+ }
+#else
// Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
template<class Expr>
void construct ( Expr const& expr, optional_tag const* )
@@ -429,9 +669,14 @@ class optional_base : public optional_tag
}
}
#endif
+#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
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
+ 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
void destroy()
{
@@ -439,8 +684,6 @@ class optional_base : public optional_tag
destroy_impl(is_reference_predicate()) ;
}
- unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
-
reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
@@ -476,7 +719,7 @@ class optional_base : public optional_tag
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
#else
- void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; }
+ void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
#endif
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
@@ -500,8 +743,6 @@ class optional : public optional_detail::optional_base<T>
{
typedef optional_detail::optional_base<T> base ;
- typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
-
public :
typedef optional<T> this_type ;
@@ -509,27 +750,37 @@ 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
+ 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
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
// Creates an optional<T> uninitialized.
// No-throw
- optional() : base() {}
+ optional() BOOST_NOEXCEPT : base() {}
// Creates an optional<T> uninitialized.
// No-throw
- optional( none_t none_ ) : base(none_) {}
+ optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
+#ifndef BOOST_NO_CXX11_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) )
+ {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
+#endif
+
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}
-#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
// NOTE: MSVC needs templated versions first
// Creates a deep copy of another convertible optional<U>
@@ -543,43 +794,94 @@ class optional : public optional_detail::optional_base<T>
if ( rhs.is_initialized() )
this->construct(rhs.get());
}
+
+#ifndef BOOST_NO_CXX11_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
+ template<class U>
+ explicit optional ( optional<U> && rhs )
+ :
+ base()
+ {
+ if ( rhs.is_initialized() )
+ this->construct( boost::move(rhs.get()) );
+ }
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Creates an optional<T> with an expression which can be either
// (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
// (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
- // (c) Any expression implicitely convertible to the single type
+ // (c) Any expression implicitly convertible to the single type
// of a one-argument T's constructor.
// (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
// even though explicit overloads are present for these.
// Depending on the above some T ctor is called.
- // Can throw is the resolved T ctor throws.
+ // Can throw if the resolved T ctor throws.
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+
+ template<class Expr>
+ explicit optional ( Expr&& expr,
+ BOOST_DEDUCED_TYPENAME boost::disable_if_c<
+ (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
+ boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value >::type* = 0
+ )
+ : base(boost::forward<Expr>(expr),boost::addressof(expr))
+ {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
+
+#else
template<class Expr>
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
-#endif
+#endif // !defined BOOST_NO_CXX11_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
+ // Creates a deep move of another optional<T>
+ // Can throw if T::T(T&&) does
+ optional ( optional && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
+ : base( boost::move(rhs) )
+ {}
+
+#endif
// No-throw (assuming T::~T() doesn't)
~optional() {}
#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
+
+ template<class Expr>
+ BOOST_DEDUCED_TYPENAME boost::disable_if_c<
+ boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
+ boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
+ optional&
+ >::type
+ operator= ( Expr&& expr )
+ {
+ optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
+ this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
+ return *this ;
+ }
+
+#else
template<class Expr>
optional& operator= ( Expr const& expr )
{
this->assign_expr(expr,boost::addressof(expr));
return *this ;
}
-#endif
-
+#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
-#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
- // Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
+ // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
// Requires a valid conversion from U to T.
// Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
template<class U>
@@ -588,6 +890,17 @@ class optional : public optional_detail::optional_base<T>
this->assign(rhs);
return *this ;
}
+
+#ifndef BOOST_NO_CXX11_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
+ template<class U>
+ optional& operator= ( optional<U> && rhs )
+ {
+ this->assign(boost::move(rhs));
+ return *this ;
+ }
#endif
// Assigns from another optional<T> (deep-copies the rhs value)
@@ -599,6 +912,16 @@ class optional : public optional_detail::optional_base<T>
return *this ;
}
+#ifndef BOOST_NO_CXX11_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)
+ {
+ this->assign( static_cast<base &&>(rhs) ) ;
+ return *this ;
+ }
+#endif
+
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
optional& operator= ( argument_type val )
@@ -607,20 +930,58 @@ class optional : public optional_detail::optional_base<T>
return *this ;
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ optional& operator= ( rval_reference_type val )
+ {
+ optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
+ this->assign( boost::move(val) ) ;
+ return *this ;
+ }
+#endif
+
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
- optional& operator= ( none_t none_ )
+ optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
{
this->assign( none_ ) ;
return *this ;
}
+
+#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // Constructs in-place
+ // upon exception *this is always uninitialized
+ template<class... Args>
+ void emplace ( Args&&... args )
+ {
+ this->emplace_assign( boost::forward<Args>(args)... );
+ }
+#elif (!defined BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template<class Arg>
+ void emplace ( Arg&& arg )
+ {
+ this->emplace_assign( boost::forward<Arg>(arg) );
+ }
+#else
+ template<class Arg>
+ void emplace ( const Arg& arg )
+ {
+ this->emplace_assign( arg );
+ }
+
+ template<class Arg>
+ void emplace ( Arg& arg )
+ {
+ this->emplace_assign( arg );
+ }
+#endif
void swap( optional & arg )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
{
// allow for Koenig lookup
- using boost::swap;
- swap(*this, arg);
+ boost::swap(*this, arg);
}
@@ -643,17 +1004,139 @@ 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
+ 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()) ; }
+#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
+ reference_const_type value() const&
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type value() &
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type_of_temporary_wrapper value() &&
+ {
+ if (this->is_initialized())
+ return boost::move(this->get()) ;
+ else
+ throw_exception(bad_optional_access());
+ }
- // implicit conversion to "bool"
- // No-throw
- operator unspecified_bool_type() const { return this->safe_bool() ; }
+#else
+ reference_const_type value() const
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type value()
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+#endif
- // This is provided for those compilers which don't like the conversion to bool
- // on some contexts.
- bool operator!() const { return !this->is_initialized() ; }
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+ template <class U>
+ value_type value_or ( U&& v ) const&
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return boost::forward<U>(v);
+ }
+
+ template <class U>
+ value_type value_or ( U&& v ) &&
+ {
+ if (this->is_initialized())
+ return boost::move(get());
+ else
+ return boost::forward<U>(v);
+ }
+#elif !defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class U>
+ value_type value_or ( U&& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return boost::forward<U>(v);
+ }
+#else
+ template <class U>
+ value_type value_or ( U const& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return v;
+ }
+#endif
+
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+ template <typename F>
+ value_type value_or_eval ( F f ) const&
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return f();
+ }
+
+ template <typename F>
+ value_type value_or_eval ( F f ) &&
+ {
+ if (this->is_initialized())
+ return boost::move(get());
+ else
+ return f();
+ }
+#else
+ template <typename F>
+ value_type value_or_eval ( F f ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return f();
+ }
+#endif
+
+ bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+} ;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template<class T>
+class optional<T&&>
+{
+ BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
} ;
+#endif
// Returns optional<T>(v)
template<class T>
@@ -743,6 +1226,11 @@ 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>
+std::basic_ostream<CharType, CharTrait>&
+operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v);
+
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
@@ -856,8 +1344,8 @@ bool operator >= ( T const& x, optional<T> const& y )
template<class T>
inline
-bool operator == ( optional<T> const& x, none_t )
-{ return equal_pointees(x, optional<T>() ); }
+bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
+{ return !x; }
template<class T>
inline
@@ -866,8 +1354,8 @@ bool operator < ( optional<T> const& x, none_t )
template<class T>
inline
-bool operator != ( optional<T> const& x, none_t y )
-{ return !( x == y ) ; }
+bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
+{ return bool(x); }
template<class T>
inline
@@ -890,8 +1378,8 @@ bool operator >= ( optional<T> const& x, none_t y )
template<class T>
inline
-bool operator == ( none_t , optional<T> const& y )
-{ return equal_pointees(optional<T>() ,y); }
+bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
+{ return !y; }
template<class T>
inline
@@ -900,8 +1388,8 @@ bool operator < ( none_t , optional<T> const& y )
template<class T>
inline
-bool operator != ( none_t x, optional<T> const& y )
-{ return !( x == y ) ; }
+bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
+{ return bool(y); }
template<class T>
inline
@@ -949,6 +1437,37 @@ struct swap_selector<true>
}
};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template<>
+struct swap_selector<false>
+{
+ template<class T>
+ static void optional_swap ( optional<T>& x, optional<T>& y )
+ //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
+ {
+ if(x)
+ {
+ if (y)
+ {
+ boost::swap(*x, *y);
+ }
+ else
+ {
+ y = boost::move(*x);
+ x = boost::none;
+ }
+ }
+ else
+ {
+ if (y)
+ {
+ x = boost::move(*y);
+ y = boost::none;
+ }
+ }
+ }
+};
+#else
template<>
struct swap_selector<false>
{
@@ -975,6 +1494,7 @@ struct swap_selector<false>
}
}
};
+#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
} // namespace optional_detail
@@ -982,6 +1502,7 @@ template<class T>
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
template<class T> inline void swap ( optional<T>& x, optional<T>& y )
+ //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
{
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
}