Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.77 KB | None | 0 0
  1. #include <utility>
  2. // Исключение этого типа должно генерироваться при обращении к "пустому" Optional в функции Value
  3. struct BadOptionalAccess
  4. {
  5. };
  6.  
  7. template <typename T>
  8. class Optional
  9. {
  10. private:
  11.     // alignas нужен для правильного выравнивания блока памяти
  12.     alignas(T) unsigned char data[sizeof(T)];
  13.     bool defined = false;
  14.  
  15. public:
  16.     Optional() = default;
  17.     Optional(const T &elem)
  18.     {
  19.         new (data) T(elem);
  20.         defined = true;
  21.     };
  22.     Optional(T &&elem)
  23.     {
  24.         new (data) T(std::move(elem));
  25.         defined = true;
  26.     };
  27.     Optional(const Optional &other)
  28.     {
  29.         if (HasValue())
  30.         {
  31.             *reinterpret_cast<T *>(data) = *reinterpret_cast<const T *>(other.data);
  32.         }
  33.         else
  34.         {
  35.             new (data) T(*reinterpret_cast<const T *>(other.data));
  36.         }
  37.  
  38.         this->defined = other.defined;
  39.     };
  40.     Optional(Optional &&other)
  41.     {
  42.         this->defined = other.defined;
  43.         new (data) T(std::move(*reinterpret_cast<T *>(other.data)));
  44.     };
  45.  
  46.     Optional &operator=(const T &elem)
  47.     {
  48.         if (HasValue())
  49.         {
  50.             *reinterpret_cast<T *>(data) = elem;
  51.         }
  52.         else
  53.         {
  54.             new (data) T(elem);
  55.         }
  56.         defined = true;
  57.         return *this;
  58.     };
  59.     Optional &operator=(T &&elem)
  60.     {
  61.         if (HasValue())
  62.         {
  63.             *reinterpret_cast<T *>(data) = std::move(elem);
  64.         }
  65.         else
  66.         {
  67.             new (data) T(std::move(elem));
  68.         }
  69.  
  70.         defined = true;
  71.         return *this;
  72.     };
  73.     Optional &operator=(const Optional &other)
  74.     {
  75.         if (HasValue())
  76.         {
  77.             *reinterpret_cast<T *>(data) = *reinterpret_cast<const T *>(other.data);
  78.         }
  79.         else
  80.         {
  81.             new (data) T(*reinterpret_cast<const T *>(other.data));
  82.         }
  83.         this->defined = other.defined;
  84.         return *this;
  85.     };
  86.     Optional &operator=(Optional &&other)
  87.     {
  88.         if (HasValue())
  89.         {
  90.             *reinterpret_cast<T *>(data) = std::move(*reinterpret_cast<const T *>(other.data));
  91.         }
  92.         else
  93.         {
  94.             new (data) T(std::move(*reinterpret_cast<T *>(other.data)));
  95.         }
  96.         this->defined = other.defined;
  97.         return *this;
  98.     };
  99.  
  100.     bool HasValue() const
  101.     {
  102.         return this->defined;
  103.     };
  104.  
  105.     // Эти операторы не должны делать никаких проверок на пустоту.
  106.     // Проверки остаются на совести программиста.
  107.     T &operator*()
  108.     {
  109.         return *reinterpret_cast<T *>(data);
  110.     };
  111.     const T &operator*() const
  112.     {
  113.         return *reinterpret_cast<const T *>(data);
  114.     };
  115.     T *operator->()
  116.     {
  117.         return reinterpret_cast<T *>(data);
  118.     };
  119.     const T *operator->() const
  120.     {
  121.         return reinterpret_cast<const T *>(data);
  122.     };
  123.  
  124.     // Генерирует исключение BadOptionalAccess, если объекта нет
  125.     T &Value()
  126.     {
  127.         if (!HasValue())
  128.         {
  129.             throw BadOptionalAccess{};
  130.         }
  131.         return *reinterpret_cast<T*>(data);
  132.     };
  133.     const T &Value() const
  134.     {
  135.         if (!HasValue())
  136.         {
  137.             throw BadOptionalAccess{};
  138.         }
  139.         return *reinterpret_cast<const T*>(data);
  140.     };
  141.  
  142.     void Reset()
  143.     {
  144.         if (HasValue())
  145.         {
  146.             reinterpret_cast<T *>(data)->~T();
  147.         }
  148.         defined = false;
  149.     };
  150.  
  151.     ~Optional()
  152.     {
  153.         if (HasValue())
  154.         {
  155.             reinterpret_cast<T *>(data)->~T();
  156.         }
  157.     };
  158. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement