Skip to content

Instantly share code, notes, and snippets.

@EricWF
Created August 15, 2016 05:18
Show Gist options
  • Select an option

  • Save EricWF/0db4c490d64512ecd42819adf58a9941 to your computer and use it in GitHub Desktop.

Select an option

Save EricWF/0db4c490d64512ecd42819adf58a9941 to your computer and use it in GitHub Desktop.
diff --git a/include/optional b/include/optional
index 3f67363..438fed2 100644
--- a/include/optional
+++ b/include/optional
@@ -184,13 +184,31 @@ struct nullopt_t
/* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
+template <class _Tp, bool = is_trivially_copyable<_Tp>::value>
+struct __optional_value {
+ __optional_value(__optional_value const&) = delete;
+ __optional_value& operator=(__optional_value const&) = delete;
+ template <class ..._Args>
+ constexpr __optional_value(_Args&&... __args) : __value_(_VSTD::forward<_Args>(__args)...) {}
+ _Tp __value_;
+};
+
+template <class _Tp>
+struct __optional_value<_Tp, true> {
+ static_assert(!is_reference<_Tp>::value, "");
+ template <class ..._Args>
+ constexpr __optional_value(_Args&&... __args) : __value_(_VSTD::forward<_Args>(__args)...) {}
+ _Tp __value_;
+};
+
template <class _Tp, bool = is_trivially_destructible_v<_Tp>>
struct __optional_destruct_base;
template <class _Tp>
struct __optional_destruct_base<_Tp, false>
{
- typedef _Tp value_type;
+ static_assert(!is_reference<_Tp>::value, "");
+ using value_type = __optional_value<_Tp>;
union
{
char __null_state_;
@@ -230,7 +248,7 @@ struct __optional_destruct_base<_Tp, false>
template <class _Tp>
struct __optional_destruct_base<_Tp, true>
{
- typedef _Tp value_type;
+ typedef __optional_value<_Tp> value_type;
union
{
char __null_state_;
@@ -263,7 +281,7 @@ template <class _Tp>
struct __optional_storage_base : __optional_destruct_base<_Tp>
{
using __base = __optional_destruct_base<_Tp>;
- using typename __base::value_type;
+ using value_type = _Tp;
using __base::__base;
_LIBCPP_INLINE_VISIBILITY
@@ -275,22 +293,22 @@ struct __optional_storage_base : __optional_destruct_base<_Tp>
_LIBCPP_INLINE_VISIBILITY
constexpr value_type& __get() & noexcept
{
- return this->__val_;
+ return this->__val_.__value_;
}
_LIBCPP_INLINE_VISIBILITY
constexpr const value_type& __get() const& noexcept
{
- return this->__val_;
+ return this->__val_.__value_;
}
_LIBCPP_INLINE_VISIBILITY
constexpr value_type&& __get() && noexcept
{
- return _VSTD::move(this->__val_);
+ return _VSTD::move(this->__val_.__value_);
}
_LIBCPP_INLINE_VISIBILITY
constexpr const value_type&& __get() const&& noexcept
{
- return _VSTD::move(this->__val_);
+ return _VSTD::move(this->__val_.__value_);
}
template <class... _Args>
@@ -298,7 +316,8 @@ struct __optional_storage_base : __optional_destruct_base<_Tp>
void __construct(_Args&&... __args)
{
_LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
- ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
+ ::new(_VSTD::addressof(this->__val_)) __optional_value<_Tp>(
+ _VSTD::forward<_Args>(__args)...);
this->__engaged_ = true;
}
@@ -317,7 +336,7 @@ struct __optional_storage_base : __optional_destruct_base<_Tp>
if (this->__engaged_ == __opt.has_value())
{
if (this->__engaged_)
- this->__val_ = _VSTD::forward<_That>(__opt).__get();
+ this->__val_.__value_ = _VSTD::forward<_That>(__opt).__get();
}
else
{
@@ -405,8 +424,6 @@ public:
using __base = __optional_storage<_Tp>;
using typename __base::value_type;
- static_assert(!is_reference_v<value_type>,
- "Instantiation of optional with a reference type is ill-formed.");
static_assert(!is_same_v<remove_cv_t<value_type>, nullopt_t>,
"Instantiation of optional with a nullopt_t type is ill-formed.");
static_assert(is_reference_v<value_type> || is_object_v<value_type>,
@@ -607,9 +624,11 @@ public:
}
}
+ using __raw_value_type = remove_reference_t<value_type>;
+
_LIBCPP_INLINE_VISIBILITY
constexpr
- value_type const*
+ __raw_value_type const*
operator->() const
{
_LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
@@ -622,7 +641,7 @@ public:
_LIBCPP_INLINE_VISIBILITY
constexpr
- value_type*
+ __raw_value_type*
operator->()
{
_LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
@@ -735,14 +754,14 @@ public:
private:
_LIBCPP_INLINE_VISIBILITY
- _Tp const*
+ __raw_value_type const*
__operator_arrow(true_type) const
{
return _VSTD::addressof(this->__get());
}
_LIBCPP_INLINE_VISIBILITY
- constexpr _Tp const*
+ constexpr __raw_value_type const*
__operator_arrow(false_type) const
{
return &this->__get();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment