254 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			254 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // Copyright (C) 2015-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 | ||
|  | // 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> | ||
|  |       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)) {} | ||
|  | 
 | ||
|  |     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; } | ||
|  |      | ||
|  | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES    | ||
|  |   | ||
|  |     optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<T&&>(); } | ||
|  |      | ||
|  |     template <class R> | ||
|  |         optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::no_unboxing_cond<T, R> >::type* = 0) BOOST_NOEXCEPT | ||
|  |         : 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); } | ||
|  |        | ||
|  |     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> | ||
|  |       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)) { } | ||
|  |        | ||
|  |     template <class U> | ||
|  |       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)) { } | ||
|  |          | ||
|  |     template <class U> | ||
|  |       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) {} | ||
|  | 
 | ||
|  |     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> | ||
|  |         void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) BOOST_NOEXCEPT | ||
|  |         { ptr_ = boost::addressof(v); } | ||
|  |          | ||
|  |     template <class U> | ||
|  |       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; } | ||
|  |        | ||
|  |     template <class U> | ||
|  |         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; } | ||
|  |          | ||
|  |     template <class U> | ||
|  |       void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) BOOST_NOEXCEPT | ||
|  |       { 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 |