#pragma once #include namespace vcpkg { struct NullOpt { explicit constexpr NullOpt(int) {} }; const static constexpr NullOpt nullopt{0}; namespace details { template struct OptionalStorage { constexpr OptionalStorage() noexcept : m_is_present(false), m_t() {} constexpr OptionalStorage(const T& t) : m_is_present(true), m_t(t) {} constexpr OptionalStorage(T&& t) : m_is_present(true), m_t(std::move(t)) {} constexpr bool has_value() const { return m_is_present; } const T& value() const { return this->m_t; } T& value() { return this->m_t; } private: bool m_is_present; T m_t; }; template struct OptionalStorage { constexpr OptionalStorage() noexcept : m_t(nullptr) {} constexpr OptionalStorage(T& t) : m_t(&t) {} constexpr bool has_value() const { return m_t != nullptr; } T& value() const { return *this->m_t; } private: T* m_t; }; } template struct Optional { constexpr Optional() noexcept {} // Constructors are intentionally implicit constexpr Optional(NullOpt) {} template Optional(U&& t) : m_base(std::forward(t)) { } T&& value_or_exit(const LineInfo& line_info) && { this->exit_if_null(line_info); return std::move(this->m_base.value()); } T& value_or_exit(const LineInfo& line_info) & { this->exit_if_null(line_info); return this->m_base.value(); } const T& value_or_exit(const LineInfo& line_info) const& { this->exit_if_null(line_info); return this->m_base.value(); } constexpr explicit operator bool() const { return this->m_base.has_value(); } constexpr bool has_value() const { return this->m_base.has_value(); } template T value_or(U&& default_value) const& { return this->m_base.has_value() ? this->m_base.value() : static_cast(std::forward(default_value)); } template T value_or(U&& default_value) && { return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast(std::forward(default_value)); } typename std::add_pointer::type get() const { return this->m_base.has_value() ? &this->m_base.value() : nullptr; } typename std::add_pointer::type get() { return this->m_base.has_value() ? &this->m_base.value() : nullptr; } private: void exit_if_null(const LineInfo& line_info) const { Checks::check_exit(line_info, this->m_base.has_value(), "Value was null"); } details::OptionalStorage m_base; }; template Optional> make_optional(U&& u) { return Optional>(std::forward(u)); } template bool operator==(const Optional& o, const T& t) { if (auto p = o.get()) return *p == t; return false; } template bool operator==(const T& t, const Optional& o) { if (auto p = o.get()) return t == *p; return false; } template bool operator!=(const Optional& o, const T& t) { if (auto p = o.get()) return *p != t; return true; } template bool operator!=(const T& t, const Optional& o) { if (auto p = o.get()) return t != *p; return true; } }