diff options
Diffstat (limited to 'boost/optional/optional.hpp')
-rw-r--r-- | boost/optional/optional.hpp | 295 |
1 files changed, 267 insertions, 28 deletions
diff --git a/boost/optional/optional.hpp b/boost/optional/optional.hpp index ff1a16ca48..a465b9ed66 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, 2015 Andrzej Krzemienski. +// Copyright (C) 2014 - 2016 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 @@ -56,6 +56,31 @@ #include <boost/optional/detail/old_optional_implementation.hpp> #else namespace boost { + +namespace optional_ns { + +// a tag for in-place initialization of contained value +struct in_place_init_t +{ + struct init_tag{}; + explicit in_place_init_t(init_tag){} +}; +const in_place_init_t in_place_init ((in_place_init_t::init_tag())); + +// a tag for conditional in-place initialization of contained value +struct in_place_init_if_t +{ + struct init_tag{}; + explicit in_place_init_if_t(init_tag){} +}; +const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag())); + +} // namespace optional_ns + +using optional_ns::in_place_init_t; +using optional_ns::in_place_init; +using optional_ns::in_place_init_if_t; +using optional_ns::in_place_init_if; namespace optional_detail { @@ -339,50 +364,178 @@ class optional_base : public optional_tag // Constructs in-place // upon exception *this is always uninitialized template<class... Args> + void construct ( in_place_init_t, Args&&... args ) + { + ::new (m_storage.address()) value_type( boost::forward<Args>(args)... ) ; + m_initialized = true ; + } + + template<class... Args> void emplace_assign ( Args&&... args ) + { + destroy(); + construct(in_place_init, boost::forward<Args>(args)...); + } + + template<class... Args> + explicit optional_base ( in_place_init_t, Args&&... args ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward<Args>(args)...); + } + + template<class... Args> + explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward<Args>(args)...); + } +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template<class Arg> + void construct ( in_place_init_t, Arg&& arg ) { - destroy(); - ::new (m_storage.address()) value_type( boost::forward<Args>(args)... ); + ::new (m_storage.address()) value_type( boost::forward<Arg>(arg) ); m_initialized = true ; } -#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + + void construct ( in_place_init_t ) + { + ::new (m_storage.address()) value_type(); + m_initialized = true ; + } + template<class Arg> void emplace_assign ( Arg&& arg ) { destroy(); - ::new (m_storage.address()) value_type( boost::forward<Arg>(arg) ); - m_initialized = true ; + construct(in_place_init, boost::forward<Arg>(arg)) ; } void emplace_assign () { destroy(); - ::new (m_storage.address()) value_type(); - m_initialized = true ; + construct(in_place_init) ; } + + template<class Arg> + explicit optional_base ( in_place_init_t, Arg&& arg ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward<Arg>(arg)); + } + + explicit optional_base ( in_place_init_t ) + : + m_initialized(false) + { + construct(in_place_init); + } + + template<class Arg> + explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward<Arg>(arg)); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } + #else + template<class Arg> - void emplace_assign ( const Arg& arg ) + void construct ( in_place_init_t, const Arg& arg ) { - destroy(); ::new (m_storage.address()) value_type( arg ); m_initialized = true ; } template<class Arg> - void emplace_assign ( Arg& arg ) + void construct ( in_place_init_t, Arg& arg ) { - destroy(); ::new (m_storage.address()) value_type( arg ); m_initialized = true ; } - void emplace_assign () + void construct ( in_place_init_t ) { - destroy(); ::new (m_storage.address()) value_type(); m_initialized = true ; } + + template<class Arg> + void emplace_assign ( const Arg& arg ) + { + destroy(); + construct(in_place_init, arg); + } + + template<class Arg> + void emplace_assign ( Arg& arg ) + { + destroy(); + construct(in_place_init, arg); + } + + void emplace_assign () + { + destroy(); + construct(in_place_init); + } + + template<class Arg> + explicit optional_base ( in_place_init_t, const Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + template<class Arg> + explicit optional_base ( in_place_init_t, Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_t ) + : m_initialized(false) + { + construct(in_place_init); + } + + template<class Arg> + explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + template<class Arg> + explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } #endif #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT @@ -574,30 +727,36 @@ class optional_base : public optional_tag template <typename U> struct is_optional_related : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value - || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value, + || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value + || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_t>::value + || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_if_t>::value, boost::true_type, boost::false_type>::type {}; -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC) - // this condition is a copy paste from is_constructible.hpp - // I also disable SUNPRO, as it seems not to support type_traits correctly +#if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT) template <typename T, typename U> struct is_convertible_to_T_or_factory : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value || boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value - || boost::is_constructible<T, U&&>::value + || (boost::is_constructible<T, U&&>::value && !boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value) , boost::true_type, boost::false_type>::type {}; -#else +template <typename T, typename U> +struct is_optional_constructible : boost::is_constructible<T, U> +{}; -#define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT +#else template <typename, typename> struct is_convertible_to_T_or_factory : boost::true_type {}; +template <typename T, typename U> +struct is_optional_constructible : boost::true_type +{}; + #endif // is_convertible condition template <typename T, typename U> @@ -657,7 +816,11 @@ class optional : public optional_detail::optional_base<T> // Requires a valid conversion from U to T. // Can throw if T::T(U const&) does template<class U> - explicit optional ( optional<U> const& rhs ) + explicit optional ( optional<U> const& rhs +#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS + ,typename boost::enable_if< optional_detail::is_optional_constructible<T, U const&> >::type* = 0 +#endif + ) : base() { @@ -670,7 +833,11 @@ class optional : public optional_detail::optional_base<T> // Requires a valid conversion from U to T. // Can throw if T::T(U&&) does template<class U> - explicit optional ( optional<U> && rhs ) + explicit optional ( optional<U> && rhs +#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS + ,typename boost::enable_if< optional_detail::is_optional_constructible<T, U> >::type* = 0 +#endif + ) : base() { @@ -789,6 +956,19 @@ class optional : public optional_detail::optional_base<T> } #endif +#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX + + // Assigns from a T (deep-moves/copies the rhs value) + template <typename T_> + BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type + operator= ( T_&& val ) + { + this->assign( boost::forward<T_>(val) ) ; + return *this ; + } + +#else + // 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 ) @@ -796,7 +976,7 @@ class optional : public optional_detail::optional_base<T> this->assign( val ) ; return *this ; } - + #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES // Assigns from a T (deep-moves the rhs value) optional& operator= ( rval_reference_type val ) @@ -805,7 +985,9 @@ class optional : public optional_detail::optional_base<T> return *this ; } #endif - + +#endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX + // Assigns from a "none" // Which destroys the current value, if any, leaving this UNINITIALIZED // No-throw (assuming T::~T() doesn't) @@ -820,9 +1002,20 @@ class optional : public optional_detail::optional_base<T> // upon exception *this is always uninitialized template<class... Args> void emplace ( Args&&... args ) - { - this->emplace_assign( boost::forward<Args>(args)... ); - } + { + this->emplace_assign( boost::forward<Args>(args)... ); + } + + template<class... Args> + explicit optional ( in_place_init_t, Args&&... args ) + : base( in_place_init, boost::forward<Args>(args)... ) + {} + + template<class... Args> + explicit optional ( in_place_init_if_t, bool cond, Args&&... args ) + : base( in_place_init_if, cond, boost::forward<Args>(args)... ) + {} + #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template<class Arg> void emplace ( Arg&& arg ) @@ -834,6 +1027,24 @@ class optional : public optional_detail::optional_base<T> { this->emplace_assign(); } + + template<class Args> + explicit optional ( in_place_init_t, Args&& args ) + : base( in_place_init, boost::forward<Args>(args) ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template<class Args> + explicit optional ( in_place_init_if_t, bool cond, Args&& args ) + : base( in_place_init_if, cond, boost::forward<Args>(args) ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} #else template<class Arg> void emplace ( const Arg& arg ) @@ -851,6 +1062,34 @@ class optional : public optional_detail::optional_base<T> { this->emplace_assign(); } + + template<class Arg> + explicit optional ( in_place_init_t, const Arg& arg ) + : base( in_place_init, arg ) + {} + + template<class Arg> + explicit optional ( in_place_init_t, Arg& arg ) + : base( in_place_init, arg ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template<class Arg> + explicit optional ( in_place_init_if_t, bool cond, const Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + template<class Arg> + explicit optional ( in_place_init_if_t, bool cond, Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} #endif void swap( optional & arg ) |