Untitled
unknown
plain_text
2 years ago
2.7 kB
1
Indexable
Never
#include <stdexcept> #include <utility> // Исключение этого типа должно генерироватся при обращении к пустому optional class BadOptionalAccess : public std::exception { public: using exception::exception; virtual const char* what() const noexcept override { return "Bad optional access"; } }; template <typename T> class Optional { public: Optional() = default; Optional(const T& value) { t = new(&data_[0]) T(value); is_initialized_ = true; } Optional(T&& value) { t = new(&data_[0]) T(std::move(value)); is_initialized_ = true; } Optional(const Optional& other) : t(new(&data_[0]) T(*other.t)) { is_initialized_ = true; } Optional(Optional&& other) : t(new(&other.data_[0]) T(std::move(*other.t))) { is_initialized_ = true; } Optional& operator=(const T& value) { is_initialized_ = true; t = new(&data_[0]) T(value); return *this; } Optional& operator=(T&& rhs) { is_initialized_ = true; t = new(&data_[0]) T(std::move(rhs)); return *this; } Optional& operator=(const Optional& other) { is_initialized_ = true; t = new(&data_[0]) T(*other.t); return *this; } Optional& operator=(Optional&& other) { is_initialized_ = true; t = new(&other.data_[0]) T(std::move(*other.t)); return *this; } ~Optional() { } bool HasValue() const { return is_initialized_; } // Операторы * и -> не должны делать никаких проверок на пустоту Optional. // Эти проверки остаются на совести программиста T& operator*() { return t; } const T& operator*() const { return t; } T* operator->() { return &t; } const T* operator->() const { return &t; } // Метод Value() генерирует исключение BadOptionalAccess, если Optional пуст T& Value() { if (not is_initialized_) { BadOptionalAccess{}; } return t; } const T& Value() const { if (not is_initialized_) { BadOptionalAccess{}; } return t; } void Reset() { } private: // alignas нужен для правильного выравнивания блока памяти alignas(T) char data_[sizeof(T)]; T t; bool is_initialized_ = false; };