Advertisement
kutuzzzov

Урок 10 variadic templates 3/3

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