2018-08-21 16:04:16 +00:00
// Copyright (C) 2015-2018 Andrzej Krzemienski.
2017-03-13 04:29:07 +00:00
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
# ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
# define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
# ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
# include <boost/type_traits/is_integral.hpp>
# include <boost/type_traits/is_const.hpp>
# endif
# if 1
namespace boost {
namespace detail {
# ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
template < class From >
void prevent_binding_rvalue ( )
{
# ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
BOOST_STATIC_ASSERT_MSG ( boost : : is_lvalue_reference < From > : : value ,
" binding rvalue references to optional lvalue references is disallowed " ) ;
# endif
}
template < class T >
BOOST_DEDUCED_TYPENAME boost : : remove_reference < T > : : type & forward_reference ( T & & r )
{
BOOST_STATIC_ASSERT_MSG ( boost : : is_lvalue_reference < T > : : value ,
" binding rvalue references to optional lvalue references is disallowed " ) ;
return boost : : forward < T > ( r ) ;
}
# endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
template < class T >
struct is_const_integral
{
static const bool value = boost : : is_const < T > : : value & & boost : : is_integral < T > : : value ;
} ;
template < class T >
struct is_const_integral_bad_for_conversion
{
# if (!defined BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES) && (defined BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT)
static const bool value = boost : : is_const < T > : : value & & boost : : is_integral < T > : : value ;
# else
static const bool value = false ;
# endif
} ;
template < class From >
void prevent_assignment_from_false_const_integral ( )
{
# ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
# ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
// MSVC compiler without rvalue refernces: we need to disable the asignment from
// const integral lvalue reference, as it may be an invalid temporary
BOOST_STATIC_ASSERT_MSG ( ! is_const_integral < From > : : value ,
" binding const lvalue references to integral types is disabled in this compiler " ) ;
# endif
# endif
}
template < class T >
struct is_optional_
{
static const bool value = false ;
} ;
template < class U >
struct is_optional_ < : : boost : : optional < U > >
{
static const bool value = true ;
} ;
template < class T >
struct is_no_optional
{
static const bool value = ! is_optional_ < BOOST_DEDUCED_TYPENAME boost : : decay < T > : : type > : : value ;
} ;
template < class T , class U >
struct is_same_decayed
{
static const bool value = : : boost : : is_same < T , BOOST_DEDUCED_TYPENAME : : boost : : remove_reference < U > : : type > : : value
| | : : boost : : is_same < T , const BOOST_DEDUCED_TYPENAME : : boost : : remove_reference < U > : : type > : : value ;
} ;
template < class T , class U >
struct no_unboxing_cond
{
static const bool value = is_no_optional < U > : : value & & ! is_same_decayed < T , U > : : value ;
} ;
} // namespace detail
template < class T >
class optional < T & > : public optional_detail : : optional_tag
{
T * ptr_ ;
public :
typedef T & value_type ;
typedef T & reference_type ;
typedef T & reference_const_type ;
typedef T & rval_reference_type ;
typedef T * pointer_type ;
typedef T * pointer_const_type ;
optional ( ) BOOST_NOEXCEPT : ptr_ ( ) { }
optional ( none_t ) BOOST_NOEXCEPT : ptr_ ( ) { }
template < class U >
explicit optional ( const optional < U & > & rhs ) BOOST_NOEXCEPT : ptr_ ( rhs . get_ptr ( ) ) { }
optional ( const optional & rhs ) BOOST_NOEXCEPT : ptr_ ( rhs . get_ptr ( ) ) { }
// the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with srewed conversion construction from const int
template < class U >
2018-08-21 16:04:16 +00:00
explicit optional ( U & rhs , BOOST_DEDUCED_TYPENAME boost : : enable_if_c < detail : : is_same_decayed < T , U > : : value & & detail : : is_const_integral_bad_for_conversion < U > : : value , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
: ptr_ ( boost : : addressof ( rhs ) ) { }
template < class U >
2018-08-21 16:04:16 +00:00
optional ( U & rhs , BOOST_DEDUCED_TYPENAME boost : : enable_if_c < detail : : is_same_decayed < T , U > : : value & & ! detail : : is_const_integral_bad_for_conversion < U > : : value , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
: ptr_ ( boost : : addressof ( rhs ) ) { }
optional & operator = ( const optional & rhs ) BOOST_NOEXCEPT { ptr_ = rhs . get_ptr ( ) ; return * this ; }
template < class U >
optional & operator = ( const optional < U & > & rhs ) BOOST_NOEXCEPT { ptr_ = rhs . get_ptr ( ) ; return * this ; }
optional & operator = ( none_t ) BOOST_NOEXCEPT { ptr_ = 0 ; return * this ; }
void swap ( optional & rhs ) BOOST_NOEXCEPT { std : : swap ( ptr_ , rhs . ptr_ ) ; }
T & get ( ) const { BOOST_ASSERT ( ptr_ ) ; return * ptr_ ; }
T * get_ptr ( ) const BOOST_NOEXCEPT { return ptr_ ; }
T * operator - > ( ) const { BOOST_ASSERT ( ptr_ ) ; return ptr_ ; }
T & operator * ( ) const { BOOST_ASSERT ( ptr_ ) ; return * ptr_ ; }
T & value ( ) const { return ptr_ ? * ptr_ : ( throw_exception ( bad_optional_access ( ) ) , * ptr_ ) ; }
bool operator ! ( ) const BOOST_NOEXCEPT { return ptr_ = = 0 ; }
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT ( )
void reset ( ) BOOST_NOEXCEPT { ptr_ = 0 ; }
bool is_initialized ( ) const BOOST_NOEXCEPT { return ptr_ ! = 0 ; }
2018-08-21 16:04:16 +00:00
bool has_value ( ) const BOOST_NOEXCEPT { return ptr_ ! = 0 ; }
template < typename F >
optional < typename boost : : result_of < F ( T & ) > : : type > map ( F f ) const
{
if ( this - > has_value ( ) )
return f ( this - > get ( ) ) ;
else
return none ;
}
template < typename F >
optional < typename optional_detail : : optional_value_type < typename boost : : result_of < F ( T & ) > : : type > : : type > flat_map ( F f ) const
{
if ( this - > has_value ( ) )
return f ( get ( ) ) ;
else
return none ;
}
2017-03-13 04:29:07 +00:00
# ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
optional ( T & & /* rhs */ ) BOOST_NOEXCEPT { detail : : prevent_binding_rvalue < T & & > ( ) ; }
template < class R >
2018-08-21 16:04:16 +00:00
optional ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : no_unboxing_cond < T , R > , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
: ptr_ ( boost : : addressof ( r ) ) { detail : : prevent_binding_rvalue < R > ( ) ; }
template < class R >
2018-08-21 16:04:16 +00:00
optional ( bool cond , R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
: ptr_ ( cond ? boost : : addressof ( r ) : 0 ) { detail : : prevent_binding_rvalue < R > ( ) ; }
template < class R >
BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > , optional < T & > & > : : type
operator = ( R & & r ) BOOST_NOEXCEPT { detail : : prevent_binding_rvalue < R > ( ) ; ptr_ = boost : : addressof ( r ) ; return * this ; }
template < class R >
2018-08-21 16:04:16 +00:00
void emplace ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ detail : : prevent_binding_rvalue < R > ( ) ; ptr_ = boost : : addressof ( r ) ; }
template < class R >
2018-08-21 16:04:16 +00:00
T & get_value_or ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > , bool > : : type = true ) const BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ detail : : prevent_binding_rvalue < R > ( ) ; return ptr_ ? * ptr_ : r ; }
template < class R >
2018-08-21 16:04:16 +00:00
T & value_or ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > , bool > : : type = true ) const BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ detail : : prevent_binding_rvalue < R > ( ) ; return ptr_ ? * ptr_ : r ; }
template < class R >
2018-08-21 16:04:16 +00:00
void reset ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ detail : : prevent_binding_rvalue < R > ( ) ; ptr_ = boost : : addressof ( r ) ; }
template < class F >
T & value_or_eval ( F f ) const { return ptr_ ? * ptr_ : detail : : forward_reference ( f ( ) ) ; }
# else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
// the following two implement a 'conditionally explicit' constructor
template < class U >
2018-08-21 16:04:16 +00:00
explicit optional ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if_c < detail : : no_unboxing_cond < T , U > : : value & & detail : : is_const_integral_bad_for_conversion < U > : : value , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
: ptr_ ( boost : : addressof ( v ) ) { }
template < class U >
2018-08-21 16:04:16 +00:00
optional ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if_c < detail : : no_unboxing_cond < T , U > : : value & & ! detail : : is_const_integral_bad_for_conversion < U > : : value , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
: ptr_ ( boost : : addressof ( v ) ) { }
template < class U >
2018-08-21 16:04:16 +00:00
optional ( bool cond , U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > , bool > : : type = true ) BOOST_NOEXCEPT : ptr_ ( cond ? boost : : addressof ( v ) : 0 ) { }
2017-03-13 04:29:07 +00:00
template < class U >
BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > , optional < T & > & > : : type
operator = ( U & v ) BOOST_NOEXCEPT
{
detail : : prevent_assignment_from_false_const_integral < U > ( ) ;
ptr_ = boost : : addressof ( v ) ; return * this ;
}
template < class U >
2018-08-21 16:04:16 +00:00
void emplace ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ ptr_ = boost : : addressof ( v ) ; }
template < class U >
2018-08-21 16:04:16 +00:00
T & get_value_or ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > , bool > : : type = true ) const BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ return ptr_ ? * ptr_ : v ; }
template < class U >
2018-08-21 16:04:16 +00:00
T & value_or ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > , bool > : : type = true ) const BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ return ptr_ ? * ptr_ : v ; }
template < class U >
2018-08-21 16:04:16 +00:00
void reset ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > , bool > : : type = true ) BOOST_NOEXCEPT
2017-03-13 04:29:07 +00:00
{ ptr_ = boost : : addressof ( v ) ; }
template < class F >
T & value_or_eval ( F f ) const { return ptr_ ? * ptr_ : f ( ) ; }
# endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
} ;
template < class T >
void swap ( optional < T & > & x , optional < T & > & y ) BOOST_NOEXCEPT
{
x . swap ( y ) ;
}
} // namespace boost
# endif // 1/0
# endif // header guard