4 #include <initializer_list>
12 #define REQUIRES(...) bool rt_=true, typename std::enable_if<rt_ && (__VA_ARGS__),bool>::type = true
15 struct in_place_t
{ };
17 constexpr nullopt_t nullopt
{};
18 constexpr in_place_t in_place
{};
22 bool mHasValue
{false};
24 char mDummy
[sizeof(T
)]{};
28 template<typename
... Args
>
29 void DoConstruct(Args
&& ...args
)
31 ::new (std::addressof(mValue
)) T
{std::forward
<Args
>(args
)...};
38 optional() noexcept
= default;
39 optional(nullopt_t
) noexcept
{ }
40 template<REQUIRES(std::is_copy_constructible
<T
>::value
)>
41 optional(const optional
&rhs
) { if(rhs
) DoConstruct(*rhs
); }
42 template<REQUIRES(std::is_move_constructible
<T
>::value
)>
43 optional(optional
&& rhs
) { if(rhs
) DoConstruct(std::move(*rhs
)); }
44 template<typename
... Args
, REQUIRES(std::is_constructible
<T
, Args
...>::value
)>
45 explicit optional(in_place_t
, Args
&& ...args
) : mHasValue
{true}
46 , mValue
{std::forward
<Args
>(args
)...}
48 template<typename U
, typename
... Args
, REQUIRES(std::is_constructible
<T
, std::initializer_list
<U
>&, Args
...>::value
)>
49 explicit optional(in_place_t
, std::initializer_list
<U
> il
, Args
&& ...args
)
50 : mHasValue
{true}, mValue
{il
, std::forward
<Args
>(args
)...}
52 template<typename U
=value_type
, REQUIRES(std::is_constructible
<T
, U
&&>::value
&&
53 !std::is_same
<typename
std::decay
<U
>::type
, in_place_t
>::value
&&
54 !std::is_same
<typename
std::decay
<U
>::type
, optional
<T
>>::value
&&
55 std::is_constructible
<U
&&, T
>::value
)>
56 constexpr explicit optional(U
&& value
) : mHasValue
{true}, mValue
{std::forward
<U
>(value
)}
58 template<typename U
=value_type
, REQUIRES(std::is_constructible
<T
, U
&&>::value
&&
59 !std::is_same
<typename
std::decay
<U
>::type
, in_place_t
>::value
&&
60 !std::is_same
<typename
std::decay
<U
>::type
, optional
<T
>>::value
&&
61 !std::is_constructible
<U
&&, T
>::value
)>
62 constexpr optional(U
&& value
) : mHasValue
{true}, mValue
{std::forward
<U
>(value
)}
64 ~optional() { if(mHasValue
) al::destroy_at(std::addressof(mValue
)); }
66 optional
& operator=(nullopt_t
) noexcept
{ reset(); return *this; }
67 template<REQUIRES(std::is_copy_constructible
<T
>::value
&& std::is_copy_assignable
<T
>::value
)>
68 optional
& operator=(const optional
&rhs
)
78 template<REQUIRES(std::is_move_constructible
<T
>::value
&& std::is_move_assignable
<T
>::value
)>
79 optional
& operator=(optional
&& rhs
)
84 mValue
= std::move(*rhs
);
86 DoConstruct(std::move(*rhs
));
89 template<typename U
=T
, REQUIRES(std::is_constructible
<T
, U
>::value
&&
90 std::is_assignable
<T
&, U
>::value
&&
91 !std::is_same
<typename
std::decay
<U
>::type
, optional
<T
>>::value
&&
92 (!std::is_same
<typename
std::decay
<U
>::type
, T
>::value
||
93 !std::is_scalar
<U
>::value
))>
94 optional
& operator=(U
&& rhs
)
97 mValue
= std::forward
<U
>(rhs
);
99 DoConstruct(std::forward
<U
>(rhs
));
103 const T
* operator->() const { return std::addressof(mValue
); }
104 T
* operator->() { return std::addressof(mValue
); }
105 const T
& operator*() const& { return mValue
; }
106 T
& operator*() & { return mValue
; }
107 const T
&& operator*() const&& { return std::move(mValue
); }
108 T
&& operator*() && { return std::move(mValue
); }
110 operator bool() const noexcept
{ return mHasValue
; }
111 bool has_value() const noexcept
{ return mHasValue
; }
113 T
& value() & { return mValue
; }
114 const T
& value() const& { return mValue
; }
115 T
&& value() && { return std::move(mValue
); }
116 const T
&& value() const&& { return std::move(mValue
); }
119 T
value_or(U
&& defval
) const&
120 { return bool{*this} ? **this : static_cast<T
>(std::forward
<U
>(defval
)); }
122 T
value_or(U
&& defval
) &&
123 { return bool{*this} ? std::move(**this) : static_cast<T
>(std::forward
<U
>(defval
)); }
125 void reset() noexcept
128 al::destroy_at(std::addressof(mValue
));
134 inline optional
<typename
std::decay
<T
>::type
> make_optional(T
&& arg
)
135 { return optional
<typename
std::decay
<T
>::type
>{in_place
, std::forward
<T
>(arg
)}; }
137 template<typename T
, typename
... Args
>
138 inline optional
<T
> make_optional(Args
&& ...args
)
139 { return optional
<T
>{in_place
, std::forward
<Args
>(args
)...}; }
141 template<typename T
, typename U
, typename
... Args
>
142 inline optional
<T
> make_optional(std::initializer_list
<U
> il
, Args
&& ...args
)
143 { return optional
<T
>{in_place
, il
, std::forward
<Args
>(args
)...}; }
149 #endif /* AL_SPAN_H */