Untitled

mail@pastecode.io avatar
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;
};