#pragma once #include #include "gp_config.hpp" #include "gp/exception.hpp" #include "gp/memory.hpp" namespace gp{ struct nullopt_t{}; constexpr nullopt_t nullopt; template::value || std::is_fundamental::value> class optional; template class optional{ bool ready = false; char buffer[sizeof(T)]; public: constexpr optional() : ready{false} {} constexpr optional(nullopt_t) : ready{false} {} constexpr optional(T& value) : ready{true} { new(buffer) T(value); } constexpr optional(T&& value) : ready{true} { new(buffer) T(std::move(value)); } constexpr bool has_value() { return ready; } constexpr T& value() { if constexpr (gp_config::has_exceptions) { if(!ready) { throw bad_optional{}; } } return *reinterpret_cast(buffer); } }; template class optional{ bool ready = false; void* ptr; public: constexpr optional() : ready{false} {} constexpr optional(nullopt_t) : ready{false} {} constexpr optional(T& value) : ready{true} { ptr = (void*)new T(value); } constexpr optional(T&& value) : ready{true} { ptr = (void*)new T(std::move(value)); } constexpr bool has_value() { return ready; } constexpr T& value() { if constexpr (gp_config::has_exceptions) { if(!ready) { throw bad_optional{}; } } return *reinterpret_cast(ptr); } }; }