in_chainz

Untitled

Mar 20th, 2019
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.61 KB | None | 0 0
  1. #include <iostream>
  2. #include <memory>
  3. #include <cstddef>
  4.  
  5.  
  6. struct BadOptionalAccess {
  7. };
  8.  
  9. template <typename T>
  10. class Optional {
  11. private:
  12.     // alignas нужен для правильного выравнивания блока памяти
  13.     alignas(T) unsigned char data[sizeof(T)];
  14.     bool defined = false;
  15.  
  16. public:
  17.     Optional() = default;
  18.     Optional(const T& elem) {
  19.         new (data) T(elem);
  20.         defined = true;
  21.     }
  22.     Optional(T&& elem) {
  23.         new (data) T(std::move(elem));
  24.         defined = true;
  25.     }
  26.     Optional(const Optional& other) {
  27.         if (other.defined)
  28.             new (data) T(*reinterpret_cast<T*>(other.data));
  29.  
  30.         defined = other.defined;
  31.     }
  32.  
  33.     Optional& operator=(const Optional& other) {
  34.         if (other.defined) {
  35.             if (defined)
  36.                 *reinterpret_cast<T *>(data) = *reinterpret_cast<const T *>(other.data);
  37.             else
  38.                 new(data) T(*reinterpret_cast<const T *>(other.data));
  39.             defined = other.defined;
  40.         }
  41.         else {
  42.             reinterpret_cast<T *>(data)->~T();
  43.             defined = false;
  44.         }
  45.         return *this;
  46.     }
  47.  
  48.     Optional& operator=(const T& elem) {
  49.         if (defined) {
  50.             *reinterpret_cast<T*>(data) = elem;
  51.             return *this;
  52.         }
  53.  
  54.         new (data) T(elem);
  55.         defined = true;
  56.         return *this;
  57.     }
  58.  
  59.     Optional& operator=(T&& elem) {
  60.         if (defined) {
  61.             *reinterpret_cast<T*>(data) = std::move(elem);
  62.             return *this;
  63.         }
  64.  
  65.         new (data) T(std::move(elem));
  66.         defined = true;
  67.         return *this;
  68.     }
  69.  
  70.     bool has_value() const {
  71.         return defined;
  72.     }
  73.  
  74.     T& operator*() {
  75.         return *reinterpret_cast<T*>(data);
  76.     }
  77.     const T& operator*() const {
  78.         return *reinterpret_cast<const T*>(data);
  79.     }
  80.  
  81.     T* operator->() {
  82.         return reinterpret_cast<T*>(data);
  83.     }
  84.     const T* operator->() const {
  85.         return reinterpret_cast<const T*>(data);
  86.     }
  87.  
  88.     T& value() {
  89.         if (!defined) {
  90.             throw BadOptionalAccess();
  91.         }
  92.         return *reinterpret_cast<T*>(data);
  93.     }
  94.     const T& value() const {
  95.         if (!defined) {
  96.             throw BadOptionalAccess();
  97.         }
  98.         return *reinterpret_cast<const T*>(data);
  99.  
  100.     }
  101.  
  102.     void reset() {
  103.         if (defined) {
  104.             reinterpret_cast<T *>(data)->~T();
  105.             defined = false;
  106.         }
  107.     }
  108.  
  109.     ~Optional() {
  110.         if (defined) {
  111.             reinterpret_cast<T*>(data)->~T();
  112.         }
  113.     }
  114. };
Add Comment
Please, Sign In to add comment