LCOV - code coverage report
Current view: top level - src/types - Deep_ptr.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 11 11 100.0 %
Date: 2023-04-08 04:19:02 Functions: 57 59 96.6 %

          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

Generated by: LCOV version 1.14