diff --git a/libc/src/__support/CPP/optional.h b/libc/src/__support/CPP/optional.h --- a/libc/src/__support/CPP/optional.h +++ b/libc/src/__support/CPP/optional.h @@ -36,85 +36,93 @@ // several assumptions that the underlying type is trivially constructable, // copyable, or movable. template class optional { - template class OptionalStorage { + template ::value> + struct OptionalStorage { union { char empty; U stored_value; }; - bool in_use; - public: - LIBC_INLINE ~OptionalStorage() { reset(); } - - LIBC_INLINE constexpr OptionalStorage() : empty(), in_use(false) {} + LIBC_INLINE ~OptionalStorage() { stored_value.~U(); } + LIBC_INLINE constexpr OptionalStorage() : empty() {} template LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args) - : stored_value(forward(args)...), in_use(true) {} + : stored_value(forward(args)...) {} + }; - LIBC_INLINE void reset() { - if (in_use) - stored_value.~U(); - in_use = false; - } + template struct OptionalStorage { + union { + char empty; + U stored_value; + }; - LIBC_INLINE constexpr bool has_value() const { return in_use; } + // The only difference is that this class doesn't have a destructor. + LIBC_INLINE constexpr OptionalStorage() : empty() {} - LIBC_INLINE U &value() & { return stored_value; } - LIBC_INLINE constexpr U const &value() const & { return stored_value; } - LIBC_INLINE U &&value() && { return move(stored_value); } + template + LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args) + : stored_value(forward(args)...) {} }; OptionalStorage storage; + bool in_use = false; public: LIBC_INLINE constexpr optional() = default; LIBC_INLINE constexpr optional(nullopt_t) {} - LIBC_INLINE constexpr optional(const T &t) : storage(in_place, t) {} + LIBC_INLINE constexpr optional(const T &t) + : storage(in_place, t), in_use(true) {} LIBC_INLINE constexpr optional(const optional &) = default; - LIBC_INLINE constexpr optional(T &&t) : storage(in_place, move(t)) {} + LIBC_INLINE constexpr optional(T &&t) + : storage(in_place, move(t)), in_use(true) {} LIBC_INLINE constexpr optional(optional &&O) = default; template LIBC_INLINE constexpr optional(in_place_t, ArgTypes &&...Args) - : storage(in_place, forward(Args)...) {} + : storage(in_place, forward(Args)...), in_use(true) {} - LIBC_INLINE optional &operator=(T &&t) { + LIBC_INLINE constexpr optional &operator=(T &&t) { storage = move(t); return *this; } - LIBC_INLINE optional &operator=(optional &&) = default; - - LIBC_INLINE static constexpr optional create(const T *t) { - return t ? optional(*t) : optional(); - } + LIBC_INLINE constexpr optional &operator=(optional &&) = default; - LIBC_INLINE optional &operator=(const T &t) { + LIBC_INLINE constexpr optional &operator=(const T &t) { storage = t; return *this; } - LIBC_INLINE optional &operator=(const optional &) = default; + LIBC_INLINE constexpr optional &operator=(const optional &) = default; - LIBC_INLINE void reset() { storage.reset(); } + LIBC_INLINE constexpr void reset() { + if (in_use) + storage.~OptionalStorage(); + in_use = false; + } - LIBC_INLINE constexpr const T &value() const & { return storage.value(); } - LIBC_INLINE T &value() & { return storage.value(); } + LIBC_INLINE constexpr const T &value() const & { + return storage.stored_value; + } - LIBC_INLINE constexpr explicit operator bool() const { return has_value(); } - LIBC_INLINE constexpr bool has_value() const { return storage.has_value(); } - LIBC_INLINE constexpr const T *operator->() const { return &storage.value(); } - LIBC_INLINE T *operator->() { return &storage.value(); } - LIBC_INLINE constexpr const T &operator*() const & { return value(); } - LIBC_INLINE T &operator*() & { return value(); } + LIBC_INLINE constexpr T &value() & { return storage.stored_value; } - template LIBC_INLINE constexpr T value_or(U &&value) const & { - return has_value() ? value() : forward(value); + LIBC_INLINE constexpr explicit operator bool() const { return in_use; } + LIBC_INLINE constexpr bool has_value() const { return in_use; } + LIBC_INLINE constexpr const T *operator->() const { + return &storage.stored_value; + } + LIBC_INLINE constexpr T *operator->() { return &storage.stored_value; } + LIBC_INLINE constexpr const T &operator*() const & { + return storage.stored_value; } + LIBC_INLINE constexpr T &operator*() & { return storage.stored_value; } - LIBC_INLINE T &&value() && { return move(storage.value()); } - LIBC_INLINE T &&operator*() && { return move(storage.value()); } + LIBC_INLINE constexpr T &&value() && { return move(storage.stored_value); } + LIBC_INLINE constexpr T &&operator*() && { + return move(storage.stored_value); + } }; } // namespace cpp