Untitled
unknown
plain_text
4 years ago
2.7 kB
10
Indexable
#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;
};Editor is loading...