#pragma once #include #include // Like std::optional, but the stored data is responsible for containing the empty // state. T should define a function `bool T::Valid()`. template class Maybe { T storage; public: constexpr Maybe() = default; Maybe(const Maybe&) = default; Maybe(std::nullopt_t) {} Maybe(const T& x) : storage(x) {} Maybe(T&& x) : storage(std::forward(x)) {} Maybe& operator=(const Maybe&) = default; Maybe& operator=(const T& x) { storage = x; return *this; } const T* operator->() const { return &storage; } T* operator->() { return &storage; } const T& operator*() const { return storage; } T& operator*() { return storage; } bool Valid() const { return storage.Valid(); } explicit operator bool() const { return Valid(); } operator std::optional() const { if (Valid()) return storage; return std::nullopt; } void operator=(std::optional&& o) { storage = o ? *o : T(); } // Does not test if has_value() bool operator==(const Maybe& o) const { return storage == o.storage; } bool operator!=(const Maybe& o) const { return !(*this == o); } };