28template <
typename E =
void>
31 const char*
what() const noexcept
override {
32 return "bad expected access";
39 constexpr explicit Unexpected(
const E& error) : error_(error) {}
40 constexpr explicit Unexpected(E&& error) : error_(std::move(error)) {}
42 [[nodiscard]]
constexpr E&
error() &
noexcept {
46 [[nodiscard]]
constexpr const E&
error() const& noexcept {
50 [[nodiscard]]
constexpr E&&
error() &&
noexcept {
51 return std::move(error_);
54 [[nodiscard]]
constexpr const E&&
error() const&& noexcept {
55 return std::move(error_);
63template <
typename T,
typename E>
71 requires std::is_default_constructible_v<T>
78 ConstructValue(value);
82 ConstructValue(std::move(value));
86 ConstructError(error.
error());
90 ConstructError(std::move(error).error());
96 ConstructValue(other.ValueRef());
98 ConstructError(other.ErrorRef());
103 std::is_nothrow_move_constructible_v<E>)
105 if (other.has_value()) {
106 ConstructValue(std::move(other.ValueRef()));
108 ConstructError(std::move(other.ErrorRef()));
114 if (
this == &other) {
118 ValueRef() = other.ValueRef();
121 if (!has_value() && !other.
has_value()) {
122 ErrorRef() = other.ErrorRef();
126 T tmp(other.ValueRef());
128 ConstructValue(std::move(tmp));
131 E tmp(other.ErrorRef());
133 ConstructError(std::move(tmp));
138 std::is_nothrow_move_assignable_v<E> &&
139 std::is_nothrow_move_constructible_v<T> &&
140 std::is_nothrow_move_constructible_v<E>)
142 if (
this == &other) {
145 if (has_value() && other.has_value()) {
146 ValueRef() = std::move(other.ValueRef());
149 if (!has_value() && !other.has_value()) {
150 ErrorRef() = std::move(other.ErrorRef());
153 if (other.has_value()) {
154 T tmp(std::move(other.ValueRef()));
156 ConstructValue(std::move(tmp));
159 E tmp(std::move(other.ErrorRef()));
161 ConstructError(std::move(tmp));
174 [[nodiscard]]
explicit operator bool() const noexcept {
187 return std::move(value());
191 return std::move(value());
195 return std::addressof(value());
199 return std::addressof(value());
209 [[nodiscard]]
const T&
value() const& {
220 return std::move(ValueRef());
223 [[nodiscard]]
const T&&
value() const&& {
227 return std::move(ValueRef());
237 [[nodiscard]]
const E&
error() const& {
248 return std::move(ErrorRef());
251 [[nodiscard]]
const E&&
error() const&& {
255 return std::move(ErrorRef());
264 Storage() noexcept : empty() {}
268 template <
typename... Args>
269 void ConstructValue(Args&&... args)
271 std::construct_at(std::addressof(storage_.value), std::forward<Args>(args)...);
275 template <
typename... Args>
276 void ConstructError(Args&&... args)
278 std::construct_at(std::addressof(storage_.error), std::forward<Args>(args)...);
282 void Destroy() noexcept
285 std::destroy_at(std::addressof(storage_.value));
288 std::destroy_at(std::addressof(storage_.error));
291 T& ValueRef() &
noexcept
293 return storage_.value;
296 const T& ValueRef() const& noexcept
298 return storage_.value;
301 E& ErrorRef() &
noexcept
303 return storage_.error;
306 const E& ErrorRef() const& noexcept
308 return storage_.error;
313 bool m_has_value{
false};
334 [[nodiscard]] constexpr
bool has_value() const noexcept {
338 [[nodiscard]]
constexpr explicit operator bool() const noexcept {
348 [[nodiscard]]
constexpr E&
error() & {
355 [[nodiscard]]
constexpr const E&
error() const& {
362 [[nodiscard]]
constexpr E&&
error() && {
366 return std::move(error_);
369 [[nodiscard]]
constexpr const E&&
error() const&& {
373 return std::move(error_);
377 bool has_value_ =
true;
constexpr E && error() &&
constexpr const E && error() const &&
constexpr Expected(Expected &&) noexcept=default
constexpr Expected(Unexpected< E > &&error)
constexpr Expected() noexcept=default
constexpr const E & error() const &
constexpr Expected(const Expected &)=default
constexpr void value() const
Purify result carrier that either holds a value or an error.
Expected(const Expected &other)
Expected(Unexpected< E > &&error)
Expected(const Unexpected< E > &error)
const T & operator*() const &
const T && operator*() const &&
const E && error() const &&
const T && value() const &&
Expected & operator=(const Expected &other)
const E & error() const &
Expected & operator=(Expected &&other) noexcept(std::is_nothrow_move_assignable_v< T > &&std::is_nothrow_move_assignable_v< E > &&std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_move_constructible_v< E >)
bool has_value() const noexcept
Expected(Expected &&other) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_move_constructible_v< E >)
const T * operator->() const
const T & value() const &
constexpr const E & error() const &noexcept
constexpr E & error() &noexcept
constexpr Unexpected(const E &error)
constexpr E && error() &&noexcept
constexpr const E && error() const &&noexcept
constexpr Unexpected(E &&error)
const char * what() const noexcept override
constexpr unexpect_t unexpect
constexpr unexpect_t() noexcept=default