2016-02-13 00:46:41 +01:00
// Copyright (C) 2015-2016 Andrzej Krzemienski.
2015-10-05 16:54:05 +02: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
2016-02-18 23:18:01 +01:00
# 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
2015-10-05 16:54:05 +02:00
# if 1
namespace boost {
namespace detail {
2015-10-06 09:17:14 +02:00
# ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
2015-10-05 16:54:05 +02:00
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 >
2015-10-05 23:50:11 +02:00
BOOST_DEDUCED_TYPENAME boost : : remove_reference < T > : : type & forward_reference ( T & & r )
2015-10-05 16:54:05 +02:00
{
BOOST_STATIC_ASSERT_MSG ( boost : : is_lvalue_reference < T > : : value ,
" binding rvalue references to optional lvalue references is disallowed " ) ;
return boost : : forward < T > ( r ) ;
}
2015-10-06 09:17:14 +02:00
# endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
2016-09-02 01:41:31 +02:00
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
} ;
2016-02-18 23:18:01 +01:00
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
2016-09-02 01:41:31 +02:00
BOOST_STATIC_ASSERT_MSG ( ! is_const_interal < From > : : value ,
2016-02-18 23:18:01 +01:00
" binding const lvalue references to integral types is disabled in this compiler " ) ;
# endif
# endif
}
2016-09-02 01:41:31 +02:00
2015-10-05 23:50:11 +02:00
template < class T >
2015-10-05 16:54:05 +02:00
struct is_optional_
{
static const bool value = false ;
} ;
2015-10-05 23:50:11 +02:00
template < class U >
struct is_optional_ < : : boost : : optional < U > >
2015-10-05 16:54:05 +02:00
{
static const bool value = true ;
} ;
2015-10-05 23:50:11 +02:00
template < class T >
2015-10-05 16:54:05 +02:00
struct is_no_optional
{
2015-10-05 23:50:11 +02:00
static const bool value = ! is_optional_ < BOOST_DEDUCED_TYPENAME boost : : decay < T > : : type > : : value ;
2015-10-05 16:54:05 +02:00
} ;
2016-09-02 01:41:31 +02:00
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 ;
} ;
2015-10-05 16:54:05 +02:00
} // 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 ;
2016-03-06 19:08:25 +01:00
typedef T & rval_reference_type ;
2015-10-05 16:54:05 +02:00
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 . ptr_ ) { }
optional ( const optional & rhs ) BOOST_NOEXCEPT : ptr_ ( rhs . ptr_ ) { }
2016-09-02 01:41:31 +02:00
// 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 >
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 > : : type * = 0 ) BOOST_NOEXCEPT
: ptr_ ( boost : : addressof ( rhs ) ) { }
template < class U >
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 > : : type * = 0 ) BOOST_NOEXCEPT
: ptr_ ( boost : : addressof ( rhs ) ) { }
2015-10-05 16:54:05 +02:00
optional & operator = ( const optional & rhs ) BOOST_NOEXCEPT { ptr_ = rhs . ptr_ ; return * this ; }
template < class U >
optional & operator = ( const optional < U & > & rhs ) BOOST_NOEXCEPT { ptr_ = rhs . ptr_ ; return * this ; }
optional & operator = ( none_t ) BOOST_NOEXCEPT { ptr_ = 0 ; return * this ; }
void swap ( optional & rhs ) BOOST_NOEXCEPT { std : : swap ( ptr_ , rhs . ptr_ ) ; }
2015-10-06 00:33:14 +02:00
T & get ( ) const { BOOST_ASSERT ( ptr_ ) ; return * ptr_ ; }
2015-10-05 16:54:05 +02:00
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 ; }
# ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
2016-05-31 01:00:20 +02:00
optional ( T & & /* rhs */ ) BOOST_NOEXCEPT { detail : : prevent_binding_rvalue < T & & > ( ) ; }
2016-05-17 00:54:09 +02:00
2015-10-05 16:54:05 +02:00
template < class R >
2016-09-02 01:41:31 +02:00
optional ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : no_unboxing_cond < T , R > > : : type * = 0 ) BOOST_NOEXCEPT
2015-10-05 16:54:05 +02:00
: ptr_ ( boost : : addressof ( r ) ) { detail : : prevent_binding_rvalue < R > ( ) ; }
template < class R >
optional ( bool cond , R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > > : : type * = 0 ) BOOST_NOEXCEPT
: 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 >
void emplace ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > > : : type * = 0 ) BOOST_NOEXCEPT
{ detail : : prevent_binding_rvalue < R > ( ) ; ptr_ = boost : : addressof ( r ) ; }
template < class R >
T & get_value_or ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > > : : type * = 0 ) const BOOST_NOEXCEPT
{ detail : : prevent_binding_rvalue < R > ( ) ; return ptr_ ? * ptr_ : r ; }
template < class R >
T & value_or ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > > : : type * = 0 ) const BOOST_NOEXCEPT
{ detail : : prevent_binding_rvalue < R > ( ) ; return ptr_ ? * ptr_ : r ; }
template < class R >
void reset ( R & & r , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < R > > : : type * = 0 ) BOOST_NOEXCEPT
{ detail : : prevent_binding_rvalue < R > ( ) ; ptr_ = boost : : addressof ( r ) ; }
2015-10-06 12:39:02 +02:00
template < class F >
T & value_or_eval ( F f ) const { return ptr_ ? * ptr_ : detail : : forward_reference ( f ( ) ) ; }
2015-10-05 16:54:05 +02:00
# else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
2016-09-02 01:41:31 +02:00
// the following two implement a 'conditionally explicit' constructor
template < class U >
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 > : : type * = 0 ) BOOST_NOEXCEPT
: ptr_ ( boost : : addressof ( v ) ) { }
2015-10-05 16:54:05 +02:00
template < class U >
2016-09-02 01:41:31 +02: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 > : : type * = 0 ) BOOST_NOEXCEPT
: ptr_ ( boost : : addressof ( v ) ) { }
2015-10-05 16:54:05 +02:00
template < class U >
2016-09-02 01:41:31 +02:00
optional ( bool cond , U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > > : : type * = 0 ) BOOST_NOEXCEPT : ptr_ ( cond ? boost : : addressof ( v ) : 0 ) { }
2016-02-18 23:18:01 +01:00
2015-10-05 16:54:05 +02:00
template < class U >
2016-09-02 01:41:31 +02:00
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 ;
}
2016-02-18 23:18:01 +01:00
2015-10-05 16:54:05 +02:00
template < class U >
2015-10-06 00:33:14 +02:00
void emplace ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > > : : type * = 0 ) BOOST_NOEXCEPT
{ ptr_ = boost : : addressof ( v ) ; }
2015-10-05 16:54:05 +02:00
template < class U >
2015-10-06 00:33:14 +02:00
T & get_value_or ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > > : : type * = 0 ) const BOOST_NOEXCEPT
{ return ptr_ ? * ptr_ : v ; }
2015-10-05 16:54:05 +02:00
template < class U >
2015-10-06 00:33:14 +02:00
T & value_or ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > > : : type * = 0 ) const BOOST_NOEXCEPT
{ return ptr_ ? * ptr_ : v ; }
2015-10-05 16:54:05 +02:00
template < class U >
2015-10-06 00:33:14 +02:00
void reset ( U & v , BOOST_DEDUCED_TYPENAME boost : : enable_if < detail : : is_no_optional < U > > : : type * = 0 ) BOOST_NOEXCEPT
{ ptr_ = boost : : addressof ( v ) ; }
2015-10-05 16:54:05 +02:00
2015-10-06 12:39:02 +02:00
template < class F >
T & value_or_eval ( F f ) const { return ptr_ ? * ptr_ : f ( ) ; }
2015-10-05 16:54:05 +02:00
# endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
} ;
2016-02-13 15:33:07 +01:00
template < class T >
void swap ( optional < T & > & x , optional < T & > & y ) BOOST_NOEXCEPT
{
x . swap ( y ) ;
}
2015-10-05 16:54:05 +02:00
} // namespace boost
2016-02-13 00:46:41 +01:00
# endif // 1/0
2015-10-05 16:54:05 +02:00
# endif // header guard