2018-06-23 18:27:14 +02:00
// Copyright (C) 2015-2018 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
2022-11-01 21:46:35 -04:00
// MSVC compiler without rvalue references: we need to disable the assignment from
2016-02-18 23:18:01 +01:00
// const integral lvalue reference, as it may be an invalid temporary
2016-09-06 21:59:54 +02:00
BOOST_STATIC_ASSERT_MSG ( ! is_const_integral < 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 >
2016-09-27 09:51:09 +03:00
explicit optional ( const optional < U &>& rhs ) BOOST_NOEXCEPT : ptr_ ( rhs . get_ptr ()) {}
optional ( const optional & rhs ) BOOST_NOEXCEPT : ptr_ ( rhs . get_ptr ()) {}
2015-10-05 16:54:05 +02:00
2022-11-01 21:46:37 -04:00
// the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with screwed conversion construction from const int
2016-09-02 01:41:31 +02:00
template < class U >
2018-02-15 22:51:08 +01: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
2016-09-02 01:41:31 +02:00
: ptr_ ( boost :: addressof ( rhs )) {}
template < class U >
2018-02-15 22:51:08 +01: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
2016-09-02 01:41:31 +02:00
: ptr_ ( boost :: addressof ( rhs )) {}
2015-10-05 16:54:05 +02:00
2016-09-27 09:51:09 +03:00
optional & operator = ( const optional & rhs ) BOOST_NOEXCEPT { ptr_ = rhs . get_ptr (); return * this ; }
2015-10-05 16:54:05 +02:00
template < class U >
2016-09-27 09:51:09 +03:00
optional & operator = ( const optional < U &>& rhs ) BOOST_NOEXCEPT { ptr_ = rhs . get_ptr (); return * this ; }
2015-10-05 16:54:05 +02:00
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_ ; }
2020-12-18 11:13:47 -06:00
T & value () const
{
if ( this -> is_initialized ())
return this -> get ();
else
throw_exception ( bad_optional_access ());
}
2015-10-05 16:54:05 +02:00
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-03-24 00:04:15 +01:00
bool has_value () const BOOST_NOEXCEPT { return ptr_ != 0 ; }
2015-10-05 16:54:05 +02:00
2018-06-23 18:27:14 +02:00
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 ;
}
2018-06-28 23:27:42 +02:00
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 ;
}
2015-10-05 16:54:05 +02:00
#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 >
2018-02-15 22:51:08 +01:00
optional ( R && r , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: no_unboxing_cond < T , R > , bool >:: type = true ) BOOST_NOEXCEPT
2015-10-05 16:54:05 +02:00
: ptr_ ( boost :: addressof ( r )) { detail :: prevent_binding_rvalue < R > (); }
template < class R >
2018-02-15 22:51:08 +01:00
optional ( bool cond , R && r , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < R > , bool >:: type = true ) BOOST_NOEXCEPT
2015-10-05 16:54:05 +02: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-02-15 22:51:08 +01:00
void emplace ( R && r , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < R > , bool >:: type = true ) BOOST_NOEXCEPT
2015-10-05 16:54:05 +02:00
{ detail :: prevent_binding_rvalue < R > (); ptr_ = boost :: addressof ( r ); }
template < class R >
2018-02-15 22:51:08 +01:00
T & get_value_or ( R && r , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < R > , bool >:: type = true ) const BOOST_NOEXCEPT
2015-10-05 16:54:05 +02:00
{ detail :: prevent_binding_rvalue < R > (); return ptr_ ? * ptr_ : r ; }
template < class R >
2018-02-15 22:51:08 +01:00
T & value_or ( R && r , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < R > , bool >:: type = true ) const BOOST_NOEXCEPT
2015-10-05 16:54:05 +02:00
{ detail :: prevent_binding_rvalue < R > (); return ptr_ ? * ptr_ : r ; }
template < class R >
2018-02-15 22:51:08 +01:00
void reset ( R && r , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < R > , bool >:: type = true ) BOOST_NOEXCEPT
2015-10-05 16:54:05 +02:00
{ 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
2015-10-05 16:54:05 +02:00
template < class U >
2018-02-15 22:51:08 +01: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
2016-09-02 01:41:31 +02:00
: ptr_ ( boost :: addressof ( v )) { }
template < class U >
2018-02-15 22:51:08 +01: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
2016-09-02 01:41:31 +02:00
: ptr_ ( boost :: addressof ( v )) { }
2015-10-05 16:54:05 +02:00
template < class U >
2018-02-15 22:51:08 +01: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 ) {}
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 >
2018-02-15 22:51:08 +01:00
void emplace ( U & v , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < U > , bool >:: type = true ) BOOST_NOEXCEPT
2015-10-06 00:33:14 +02:00
{ ptr_ = boost :: addressof ( v ); }
2015-10-05 16:54:05 +02:00
template < class U >
2018-02-15 22:51:08 +01:00
T & get_value_or ( U & v , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < U > , bool >:: type = true ) const BOOST_NOEXCEPT
2015-10-06 00:33:14 +02:00
{ return ptr_ ? * ptr_ : v ; }
2015-10-05 16:54:05 +02:00
template < class U >
2018-02-15 22:51:08 +01:00
T & value_or ( U & v , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < U > , bool >:: type = true ) const BOOST_NOEXCEPT
2015-10-06 00:33:14 +02:00
{ return ptr_ ? * ptr_ : v ; }
2015-10-05 16:54:05 +02:00
template < class U >
2018-02-15 22:51:08 +01:00
void reset ( U & v , BOOST_DEDUCED_TYPENAME boost :: enable_if < detail :: is_no_optional < U > , bool >:: type = true ) BOOST_NOEXCEPT
2015-10-06 00:33:14 +02:00
{ 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