summaryrefslogtreecommitdiff
path: root/boost/optional/optional.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/optional/optional.hpp')
-rw-r--r--boost/optional/optional.hpp137
1 files changed, 121 insertions, 16 deletions
diff --git a/boost/optional/optional.hpp b/boost/optional/optional.hpp
index a465b9ed66..c0f10e1daa 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 - 2016 Andrzej Krzemienski.
+// Copyright (C) 2014 - 2017 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
@@ -20,6 +20,10 @@
#include <new>
#include <iosfwd>
+#ifdef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
+# include <type_traits>
+#endif
+
#include <boost/assert.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/enable_if.hpp>
@@ -37,12 +41,15 @@
#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_const.hpp>
#include <boost/type_traits/is_constructible.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_rvalue_reference.hpp>
#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/is_scalar.hpp>
#include <boost/move/utility.hpp>
#include <boost/none.hpp>
#include <boost/utility/compare_pointees.hpp>
@@ -67,7 +74,7 @@ struct in_place_init_t
};
const in_place_init_t in_place_init ((in_place_init_t::init_tag()));
-// a tag for conditional in-place initialization of contained value
+// a tag for conditional in-place initialization of contained value
struct in_place_init_if_t
{
struct init_tag{};
@@ -152,6 +159,18 @@ class optional_base : public optional_tag
construct(val);
}
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates an optional<T> initialized with 'move(val)' IFF cond is true, otherwise creates an uninitialzed optional<T>.
+ // Can throw if T::T(T &&) does
+ optional_base ( bool cond, rval_reference_type val )
+ :
+ m_initialized(false)
+ {
+ if ( cond )
+ construct(boost::move(val));
+ }
+#endif
+
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional_base ( optional_base const& rhs )
@@ -166,6 +185,7 @@ class optional_base : public optional_tag
// Creates a deep move of another optional<T>
// Can throw if T::T(T&&) does
optional_base ( optional_base&& rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
:
m_initialized(false)
{
@@ -198,6 +218,20 @@ class optional_base : public optional_tag
#endif
+ optional_base& operator= ( optional_base const& rhs )
+ {
+ this->assign(rhs);
+ return *this;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ optional_base& operator= ( optional_base && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
+ {
+ this->assign(static_cast<optional_base&&>(rhs));
+ return *this;
+ }
+#endif
// No-throw (assuming T::~T() doesn't)
~optional_base() { destroy() ; }
@@ -723,6 +757,10 @@ class optional_base : public optional_tag
storage_type m_storage ;
} ;
+
+
+#include <boost/optional/detail/optional_trivially_copyable_base.hpp>
+
// definition of metafunciton is_optional_val_init_candidate
template <typename U>
struct is_optional_related
@@ -764,13 +802,34 @@ struct is_optional_val_init_candidate
: boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value
, boost::true_type, boost::false_type>::type
{};
-
+
} // namespace optional_detail
+namespace optional_config {
+
+template <typename T>
+struct optional_uses_direct_storage_for
+ : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
+ , boost::true_type, boost::false_type>::type
+{};
+
+} // namespace optional_config
+
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC
+# define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::optional_uses_direct_storage_for<T>::value, \
+ optional_detail::tc_optional_base<T>, \
+ optional_detail::optional_base<T> \
+ >::type
+#else
+# define BOOST_OPTIONAL_BASE_TYPE(T) optional_detail::optional_base<T>
+#endif
+
template<class T>
-class optional : public optional_detail::optional_base<T>
+class optional
+ : public BOOST_OPTIONAL_BASE_TYPE(T)
{
- typedef optional_detail::optional_base<T> base ;
+ typedef typename BOOST_OPTIONAL_BASE_TYPE(T) base ;
public :
@@ -810,6 +869,13 @@ class optional : public optional_detail::optional_base<T>
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ /// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
+ // Can throw if T::T(T &&) does
+ optional ( bool cond, rval_reference_type val ) : base( cond, boost::forward<T>(val) )
+ {}
+#endif
+
// NOTE: MSVC needs templated versions first
// Creates a deep copy of another convertible optional<U>
@@ -823,7 +889,7 @@ class optional : public optional_detail::optional_base<T>
)
:
base()
- {
+ {
if ( rhs.is_initialized() )
this->construct(rhs.get());
}
@@ -874,15 +940,24 @@ class optional : public optional_detail::optional_base<T>
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
+#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
+ optional ( optional const& ) = default;
+#else
optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
+#endif
#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 )
- BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
- : base( boost::move(rhs) )
- {}
+ // Creates a deep move of another optional<T>
+ // Can throw if T::T(T&&) does
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
+ optional ( optional && rhs ) = default;
+#else
+ optional ( optional && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
+ : base( boost::move(rhs) )
+ {}
+#endif
#endif
@@ -891,7 +966,7 @@ class optional : public optional_detail::optional_base<T>
~optional() {}
#endif
-
+
#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
@@ -940,21 +1015,30 @@ class optional : public optional_detail::optional_base<T>
// Assigns from another optional<T> (deep-copies the rhs value)
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
+#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
+ optional& operator= ( optional const& rhs ) = default;
+#else
optional& operator= ( optional const& rhs )
{
this->assign( static_cast<base const&>(rhs) ) ;
return *this ;
}
+#endif
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
// Assigns from another optional<T> (deep-moves the rhs value)
+#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
+ optional& operator= ( optional && ) = default;
+#else
optional& operator= ( optional && rhs )
- BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
+ 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
+#endif
+
+#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
@@ -1093,7 +1177,7 @@ class optional : public optional_detail::optional_base<T>
#endif
void swap( optional & arg )
- BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
{
// allow for Koenig lookup
boost::swap(*this, arg);
@@ -1276,6 +1360,25 @@ class optional<T&&>
namespace boost {
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+template<class T>
+inline
+optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( T && v )
+{
+ return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(boost::forward<T>(v));
+}
+
+// Returns optional<T>(cond,v)
+template<class T>
+inline
+optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( bool cond, T && v )
+{
+ return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(cond,boost::forward<T>(v));
+}
+
+#else
+
// Returns optional<T>(v)
template<class T>
inline
@@ -1292,6 +1395,8 @@ optional<T> make_optional ( bool cond, T const& v )
return optional<T>(cond,v);
}
+#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>