Line data Source code
1 : /* 2 : * Deep_ptr.hpp 3 : * 4 : * A pointer class, that deep copies itself when it is copied. 5 : * Otherwise, adding a unique_ptr member inside a class deletes the 6 : * default copy constructor. 7 : * 8 : * Code is adapted from: https://www.reddit.com/r/cpp_questions/comments/avr9op/specialize_a_copy_constructor_for_unique_ptr/ 9 : * Accessed 2022-11-05 10 : * 11 : * Created on: 05 Nov 2022 12 : * Author(s): Volkan Kumtepeli 13 : */ 14 : 15 : #pragma once 16 : 17 : #include <memory> 18 : 19 : namespace slide { 20 : 21 : template <typename T> 22 : class Deep_ptr 23 : { 24 : std::unique_ptr<T> ptr{}; 25 : 26 : public: 27 : Deep_ptr() = default; //!< Default constructor 28 622 : explicit Deep_ptr(T *p) : ptr(p) {} //!< Constructor taking a raw pointer 29 : 30 : Deep_ptr(std::unique_ptr<T> &&uptr) : ptr(std::move(uptr)) {} // Constructor taking a unique_ptr 31 : 32 : /// Copy constructor 33 1 : Deep_ptr(const Deep_ptr &other) : ptr(other ? other->copy() : nullptr) {} 34 : 35 : // Templated copy constructor for implicit conversion from derived class. 36 : template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>> 37 : Deep_ptr(const Deep_ptr<U> &other) : ptr(other ? other->copy() : nullptr) {} 38 : 39 : // Templated constructor for implicit conversion from derived class for unique_ptr. 40 : template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>> 41 : Deep_ptr(const std::unique_ptr<U> &other) : ptr(other ? other->copy() : nullptr) {} 42 : 43 : /// Move constructor 44 : Deep_ptr(Deep_ptr &&other) noexcept : ptr(std::move(other.ptr)) {} 45 : 46 : // Templated move constructor for implicit conversion 47 : template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>> 48 458 : Deep_ptr(Deep_ptr<U> &&other) noexcept : ptr(std::move(other.ptr)) {} 49 : 50 : // // Templated constructor for implicit conversion from raw pointers 51 : // template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>> 52 : // explicit Deep_ptr(U *raw_ptr) : ptr(raw_ptr) {} 53 : 54 : // Declare the templated Deep_ptr class as a friend 55 : template <typename U> 56 : friend class Deep_ptr; 57 : 58 : /// Copy assignment operator 59 : Deep_ptr &operator=(const Deep_ptr &other) 60 : { 61 : if (this != &other) ptr = other ? other->copy() : nullptr; 62 : 63 : return *this; 64 : } 65 : 66 : /// Move assignment operator 67 132 : Deep_ptr &operator=(Deep_ptr &&other) noexcept 68 : { 69 132 : if (this != &other) ptr = std::move(other.ptr); 70 : 71 132 : return *this; 72 : } 73 : 74 511654351 : T *operator->() const { return ptr.operator->(); } //!< Accessor operator 75 : T &operator*() const { return *ptr; } //!< Dereference operator 76 1410403 : T *get() const { return ptr.get(); } //!< Get the raw pointer 77 : 78 : /// Check if the Deep_ptr is not empty 79 1 : explicit operator bool() const { return static_cast<bool>(ptr); } 80 1 : void reset(T *p = nullptr) { ptr.reset(p); } //!< Reset the Deep_ptr 81 : 82 : // Swap the Deep_ptr with another Deep_ptr 83 : void swap(Deep_ptr &other) { ptr.swap(other.ptr); } 84 : 85 : // Comparison operators 86 : [[nodiscard]] friend bool operator==(const Deep_ptr<T> &lhs, std::nullptr_t) noexcept 87 : { 88 : return lhs.ptr == nullptr; 89 : } 90 : 91 : [[nodiscard]] friend bool operator==(std::nullptr_t, const Deep_ptr<T> &rhs) noexcept 92 : { 93 : return rhs == nullptr; 94 : } 95 : 96 : [[nodiscard]] friend bool operator!=(const Deep_ptr<T> &lhs, std::nullptr_t) noexcept 97 : { 98 : return !(lhs == nullptr); 99 : } 100 : 101 : [[nodiscard]] friend bool operator!=(std::nullptr_t, const Deep_ptr<T> &rhs) noexcept 102 : { 103 : return rhs != nullptr; 104 : } 105 : }; 106 : 107 : // Free functions: 108 : template <typename T, typename... Args> 109 : Deep_ptr<T> make_Deep_ptr(Args &&...args) 110 : { 111 : return Deep_ptr<T>(new T(std::forward<Args>(args)...)); 112 : } 113 : 114 : /// @brief Makes storage units. 115 : /// @tparam T 116 : /// @tparam ...Args 117 : /// @param ...args 118 : /// @return 119 : template <typename T, typename... Args> 120 561 : Deep_ptr<T> make(Args &&...args) { return Deep_ptr<T>(new T(std::forward<Args>(args)...)); } 121 : 122 : } // namespace slide