35657

Untitled

Sep 16th, 2023
661
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.80 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <stdexcept>
  4. #include <utility>
  5.  
  6. // Исключение этого типа должно генерироватся при обращении к пустому optional
  7. class BadOptionalAccess : public std::exception {
  8. public:
  9.     using exception::exception;
  10.  
  11.     virtual const char* what() const noexcept override {
  12.         return "Bad optional access";
  13.     }
  14. };
  15.  
  16. template <typename T>
  17. class Optional {
  18. public:
  19.     Optional() = default;
  20.  
  21.     Optional(const T& value) {
  22.         ptr_ = new (&data_[0]) T(value);
  23.         is_initialized_ = true;
  24.     }
  25.  
  26.     Optional(T&& value) {
  27.         ptr_ = new (&data_[0]) T(std::move(value));
  28.         is_initialized_ = true;
  29.     }
  30.  
  31.     Optional(const Optional& other) {
  32.         ptr_ = new (&data_[0]) T(*other.ptr_);
  33.         is_initialized_ = true;
  34.     }
  35.  
  36.     Optional(Optional&& other) {
  37.         ptr_ = other.ptr_;
  38.         is_initialized_ = true;
  39.     }
  40.  
  41.     Optional& operator=(const T& value) {
  42.         ptr_ = new (&data_[0]) T(value);
  43.         is_initialized_ = true;
  44.         return *this;
  45.     }
  46.  
  47.     Optional& operator=(T&& value) {
  48.         ptr_ = new (&data_[0]) T(std::move(value));
  49.         is_initialized_ = true;
  50.         return *this;
  51.     }
  52.  
  53.     Optional& operator=(const Optional& rhs) {
  54.         ptr_ = new (&data_[0]) T(*rhs.ptr_);
  55.         is_initialized_ = true;
  56.         return *this;
  57.     }
  58.  
  59.     Optional& operator=(Optional&& rhs) {
  60.         delete[] data_;
  61.         ptr_ = rhs.ptr_;
  62.         is_initialized_ = true;
  63.         return *this;
  64.     }
  65.  
  66.  
  67.     ~Optional() {
  68.         delete[] ptr_;
  69.     }
  70.  
  71.     bool HasValue() const {
  72.         return is_initialized_;
  73.     }
  74.  
  75.     // Операторы * и -> не должны делать никаких проверок на пустоту Optional.
  76.     // Эти проверки остаются на совести программиста
  77.     T& operator*() {
  78.         return *ptr_;
  79.     }
  80.  
  81.     const T& operator*() const {
  82.         return *ptr_;
  83.     }
  84.  
  85.     T* operator->() {
  86.         return ptr_;
  87.     }
  88.  
  89.     const T* operator->() const {
  90.         return ptr_;
  91.     }
  92.  
  93.     // Метод Value() генерирует исключение BadOptionalAccess, если Optional пуст
  94.     T& Value() {
  95.         if (!is_initialized_) {
  96.             throw BadOptionalAccess();
  97.         }
  98.         return *ptr_;
  99.     }
  100.     const T& Value() const {
  101.         if (!is_initialized_) {
  102.             throw BadOptionalAccess();
  103.         }
  104.         return *ptr_;
  105.     }
  106.  
  107.     void Reset() {
  108.         is_initialized_ = false;
  109.         ptr_ = nullptr;
  110.     }
  111.  
  112. private:
  113.     // alignas нужен для правильного выравнивания блока памяти
  114.     alignas(T) char data_[sizeof(T)];
  115.     bool is_initialized_ = false;
  116.     T* ptr_ = nullptr;
  117. };
  118.  
Advertisement
Add Comment
Please, Sign In to add comment