#pragma once #include "fl/variant.h" namespace fl { // nullopt support for compatibility with std::optional patterns struct nullopt_t {}; constexpr nullopt_t nullopt{}; template class Optional; template using optional = Optional; struct Empty {}; template class Optional { public: Optional() : mValue(Empty()) {} Optional(nullopt_t) : mValue(Empty()) {} Optional(const Optional &other) : mValue(other.mValue) {} Optional(Optional &&other) noexcept : mValue(fl::move(other.mValue)) {} Optional(const T &value) : mValue(value) {} Optional(T &&value) : mValue(fl::move(value)) {} ~Optional() { mValue.reset(); } bool empty() const { return !mValue.template is(); } bool has_value() const { return !empty(); } // std::optional compatibility T *ptr() { return mValue.template ptr(); } const T *ptr() const { return mValue.template ptr(); } void reset() { mValue.reset(); } Optional &operator=(const Optional &other) { if (this != &other) { mValue = other.mValue; } return *this; } Optional &operator=(Optional &&other) noexcept { if (this != &other) { mValue = fl::move(other.mValue); } return *this; } Optional &operator=(nullopt_t) { mValue = Empty(); return *this; } Optional &operator=(const T &value) { mValue = value; return *this; } bool operator()() const { return !empty(); } bool operator!() const { return empty(); } // Explicit conversion to bool for contextual boolean evaluation explicit operator bool() const { return !empty(); } bool operator==(const Optional &other) const { if (empty() && other.empty()) { return true; } if (empty() || other.empty()) { return false; } return *ptr() == *other.ptr(); } bool operator!=(const Optional &other) const { return !(*this == other); } bool operator==(const T &value) const { if (empty()) { return false; } return *ptr() == value; } bool operator==(nullopt_t) const { return empty(); } bool operator!=(nullopt_t) const { return !empty(); } // Dereference operators for compatibility with std::optional T& operator*() { return *ptr(); } const T& operator*() const { return *ptr(); } T* operator->() { return ptr(); } const T* operator->() const { return ptr(); } template bool operator==(const Variant &other) const { if (!other.template holdsTypeOf()) { return false; } if (empty()) { return false; } if (other.empty()) { return false; } return *ptr() == *other.template ptr(); } void swap(Optional &other) { if (this != &other) { mValue.swap(other.mValue); } } private: fl::Variant mValue; }; // Helper function to create optionals template optional make_optional(const T& value) { return optional(value); } template optional make_optional(T&& value) { return optional(fl::move(value)); } } // namespace fl