Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <utility>
- // Исключение этого типа должно генерироваться при обращении к "пустому" Optional в функции Value
- struct BadOptionalAccess
- {
- };
- template <typename T>
- class Optional
- {
- private:
- // alignas нужен для правильного выравнивания блока памяти
- alignas(T) unsigned char data[sizeof(T)];
- bool defined = false;
- public:
- Optional() = default;
- Optional(const T &elem)
- {
- new (data) T(elem);
- defined = true;
- };
- Optional(T &&elem)
- {
- new (data) T(std::move(elem));
- defined = true;
- };
- Optional(const Optional &other)
- {
- if (HasValue())
- {
- *reinterpret_cast<T *>(data) = *reinterpret_cast<const T *>(other.data);
- }
- else
- {
- new (data) T(*reinterpret_cast<const T *>(other.data));
- }
- this->defined = other.defined;
- };
- Optional(Optional &&other)
- {
- this->defined = other.defined;
- new (data) T(std::move(*reinterpret_cast<T *>(other.data)));
- };
- Optional &operator=(const T &elem)
- {
- if (HasValue())
- {
- *reinterpret_cast<T *>(data) = elem;
- }
- else
- {
- new (data) T(elem);
- }
- defined = true;
- return *this;
- };
- Optional &operator=(T &&elem)
- {
- if (HasValue())
- {
- *reinterpret_cast<T *>(data) = std::move(elem);
- }
- else
- {
- new (data) T(std::move(elem));
- }
- defined = true;
- return *this;
- };
- Optional &operator=(const Optional &other)
- {
- if (HasValue())
- {
- *reinterpret_cast<T *>(data) = *reinterpret_cast<const T *>(other.data);
- }
- else
- {
- new (data) T(*reinterpret_cast<const T *>(other.data));
- }
- this->defined = other.defined;
- return *this;
- };
- Optional &operator=(Optional &&other)
- {
- if (HasValue())
- {
- *reinterpret_cast<T *>(data) = std::move(*reinterpret_cast<const T *>(other.data));
- }
- else
- {
- new (data) T(std::move(*reinterpret_cast<T *>(other.data)));
- }
- this->defined = other.defined;
- return *this;
- };
- bool HasValue() const
- {
- return this->defined;
- };
- // Эти операторы не должны делать никаких проверок на пустоту.
- // Проверки остаются на совести программиста.
- T &operator*()
- {
- return *reinterpret_cast<T *>(data);
- };
- const T &operator*() const
- {
- return *reinterpret_cast<const T *>(data);
- };
- T *operator->()
- {
- return reinterpret_cast<T *>(data);
- };
- const T *operator->() const
- {
- return reinterpret_cast<const T *>(data);
- };
- // Генерирует исключение BadOptionalAccess, если объекта нет
- T &Value()
- {
- if (!HasValue())
- {
- throw BadOptionalAccess{};
- }
- return *reinterpret_cast<T*>(data);
- };
- const T &Value() const
- {
- if (!HasValue())
- {
- throw BadOptionalAccess{};
- }
- return *reinterpret_cast<const T*>(data);
- };
- void Reset()
- {
- if (HasValue())
- {
- reinterpret_cast<T *>(data)->~T();
- }
- defined = false;
- };
- ~Optional()
- {
- if (HasValue())
- {
- reinterpret_cast<T *>(data)->~T();
- }
- };
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement