Advertisement
kutuzzzov

Урок 13 перегрузка по рвалуе

Jul 20th, 2023
1,062
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.20 KB | None | 0 0
  1. /* Разместите здесь код класса Optional */
  2. #include <stdexcept>
  3. #include <utility>
  4.  
  5. // Исключение этого типа должно генерироватся при обращении к пустому optional
  6. class BadOptionalAccess : public std::exception {
  7. public:
  8.     using exception::exception;
  9.  
  10.     virtual const char* what() const noexcept override {
  11.         return "Bad optional access";
  12.     }
  13. };
  14.  
  15. template <typename T>
  16. class Optional {
  17. public:
  18.     Optional() = default;
  19.     Optional(const T& value);
  20.     Optional(T&& value);
  21.     Optional(const Optional& other);
  22.     Optional(Optional&& other);
  23.  
  24.     Optional& operator=(const T& value);
  25.     Optional& operator=(T&& rhs);
  26.     Optional& operator=(const Optional& rhs);
  27.     Optional& operator=(Optional&& rhs);
  28.  
  29.     ~Optional();
  30.  
  31.     bool HasValue() const;
  32.  
  33.     // Операторы * и -> не должны делать никаких проверок на пустоту Optional.
  34.     // Эти проверки остаются на совести программиста
  35.     T& operator*()& ;
  36.     const T& operator*() const&;
  37.     T* operator->();
  38.     const T* operator->() const;
  39.     T&& operator*()&&;
  40.  
  41.     // Метод Value() генерирует исключение BadOptionalAccess, если Optional пуст
  42.     T& Value()&;
  43.     const T& Value() const&;
  44.     T&& Value()&&;
  45.  
  46.     void Reset();
  47.  
  48.     template <typename... Vs>
  49.     void Emplace(Vs&&... vs);
  50.  
  51. private:
  52.     // alignas нужен для правильного выравнивания блока памяти
  53.     alignas(T) char data_[sizeof(T)];
  54.     T* ptr_ = nullptr;
  55.     bool is_initialized_ = false;
  56. };
  57.  
  58. template <typename T>
  59. Optional<T>::Optional(const T& value)
  60.     : is_initialized_(true) {
  61.     ptr_ = new(&data_[0]) T(value);
  62. }
  63.  
  64. template <typename T>
  65. Optional<T>::Optional(T&& value)
  66.     : is_initialized_(true) {
  67.     ptr_ = new(&data_[0]) T(std::move(value));
  68. }
  69.  
  70. template <typename T>
  71. Optional<T>::Optional(const Optional& other)
  72.     : is_initialized_(other.is_initialized_) {
  73.     if (is_initialized_) {
  74.         ptr_ = new(&data_[0]) T(other.Value());
  75.     }
  76. }
  77.  
  78. template <typename T>
  79. Optional<T>::Optional(Optional&& other)
  80.     : is_initialized_(std::move(other.is_initialized_)) {
  81.     if (is_initialized_) {
  82.         ptr_ = new(&data_[0]) T(std::move(other.Value()));
  83.     }
  84. }
  85.  
  86. template <typename T>
  87. Optional<T>::~Optional() {
  88.     Reset();
  89. }
  90.  
  91. template <typename T>
  92. Optional<T>& Optional<T>::operator=(const T& value) {
  93.     if (!is_initialized_) {
  94.         ptr_ = new(&data_[0]) T(value);
  95.         is_initialized_ = true;
  96.     }
  97.     else {
  98.         *ptr_ = value;
  99.     }
  100.     return *this;
  101. }
  102.  
  103. template <typename T>
  104. Optional<T>& Optional<T>::operator=(T&& rhs) {
  105.     if (!is_initialized_) {
  106.         ptr_ = new(&data_[0]) T(std::move(rhs));
  107.         is_initialized_ = true;
  108.     }
  109.     else {
  110.         *ptr_ = std::move(rhs);
  111.     }
  112.     return *this;
  113. }
  114.  
  115. template <typename T>
  116. Optional<T>& Optional<T>::operator=(const Optional& rhs) {
  117.     if (!is_initialized_) {
  118.         if (rhs.is_initialized_) {
  119.             ptr_ = new(&data_[0]) T(rhs.Value());
  120.             is_initialized_ = rhs.is_initialized_;
  121.         }
  122.     }
  123.     else {
  124.         if (rhs.is_initialized_) {
  125.             *ptr_ = rhs.Value();
  126.         }
  127.         else {
  128.             Reset();
  129.         }
  130.     }
  131.     return *this;
  132. }
  133.  
  134. template <typename T>
  135. Optional<T>& Optional<T>::operator=(Optional&& rhs) {
  136.     if (!is_initialized_) {
  137.         if (rhs.is_initialized_) {
  138.             ptr_ = new(&data_[0]) T(std::move(rhs.Value()));
  139.             is_initialized_ = std::move(rhs.is_initialized_);
  140.         }
  141.     }
  142.     else {
  143.         if (rhs.is_initialized_) {
  144.             *ptr_ = std::move(rhs.Value());
  145.         }
  146.         else {
  147.             Reset();
  148.         }
  149.     }
  150.     return *this;
  151. }
  152.  
  153. template <typename T>
  154. bool Optional<T>::HasValue() const {
  155.     return is_initialized_;
  156. }
  157.  
  158. template <typename T>
  159. T& Optional<T>::operator*()& {
  160.     return *ptr_;
  161. }
  162.  
  163. template <typename T>
  164. const T& Optional<T>::operator*() const& {
  165.     return *ptr_;
  166. }
  167.  
  168. template <typename T>
  169. T&& Optional<T>::operator*()&& {
  170.     return std::move(*ptr_);
  171. }
  172.  
  173. template <typename T>
  174. T* Optional<T>::operator->() {
  175.     return ptr_;
  176. }
  177.  
  178. template <typename T>
  179. const T* Optional<T>::operator->() const {
  180.     return ptr_;
  181. }
  182.  
  183. template <typename T>
  184. T& Optional<T>::Value()& {
  185.     if (!is_initialized_) {
  186.         throw BadOptionalAccess();
  187.     }
  188.     return *ptr_;
  189. }
  190.  
  191. template <typename T>
  192. const T& Optional<T>::Value() const& {
  193.     if (!is_initialized_) {
  194.         throw BadOptionalAccess();
  195.     }
  196.     return *ptr_;
  197. }
  198.  
  199. template <typename T>
  200. T&& Optional<T>::Value()&& {
  201.     if (!is_initialized_) {
  202.         throw BadOptionalAccess();
  203.     }
  204.     return std::move(*ptr_);
  205. }
  206.  
  207. template <typename T>
  208. void Optional<T>::Reset() {
  209.     if (is_initialized_) {
  210.         ptr_->~T();
  211.         ptr_ = nullptr;
  212.     }
  213.     is_initialized_ = false;
  214. }
  215.  
  216. template <typename T> template <typename... Vs>
  217. void Optional<T>::Emplace(Vs&&...vs) {
  218.     if (HasValue()) {
  219.         Reset();
  220.     }
  221.     ptr_ = new(&data_[0]) T(std::forward<Vs>(vs)...);
  222.     is_initialized_ = true;
  223. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement