summaryrefslogtreecommitdiff
path: root/boost/optional/detail/optional_reference_spec.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/optional/detail/optional_reference_spec.hpp')
-rw-r--r--boost/optional/detail/optional_reference_spec.hpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/boost/optional/detail/optional_reference_spec.hpp b/boost/optional/detail/optional_reference_spec.hpp
new file mode 100644
index 0000000000..ba3951af7b
--- /dev/null
+++ b/boost/optional/detail/optional_reference_spec.hpp
@@ -0,0 +1,203 @@
+// 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 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(!(boost::is_const<From>::value && boost::is_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;
+};
+
+} // 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.ptr_) {}
+ optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {}
+
+
+ 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_); }
+ 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
+
+ template <class R>
+ optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<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
+
+ template <class U>
+ optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::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