ClonablePtr.hpp 2.78 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once

#include <memory>
#include <utility>

#include <amdis/common/Utility.hpp>

namespace AMDiS
{
  // A pointer class that deletes only when owning the pointer
  template <class T>
  class ClonablePtr
  {
  private:
    struct alloc_tag {}; ///< hidden helper struct, used by \ref make

  public:
    using Self = ClonablePtr;
    using element_type = T;

    /// Default constructor, creates a non-owned nullptr
    ClonablePtr() = default;

    /// Constructor from pointer. Can only be used via make method,
    /// Transfers ownership.
    ClonablePtr(owner<T>* p, alloc_tag) noexcept
      : p(p)
      , is_owner(true)
    {}

    /// Constructor from reference
    explicit ClonablePtr(T& ref) noexcept
      : p(&ref)
      , is_owner(false)
    {}

    /// Constructor from std::unique_ptr
    explicit ClonablePtr(std::unique_ptr<T>& ptr)
      : p(ptr.release())
      , is_owner(true)
    {}

    explicit ClonablePtr(std::unique_ptr<T>&& ptr)
      : p(ptr.release())
      , is_owner(true)
    {}

    /// Destructor, deletes in case of owner only
    ~ClonablePtr() noexcept
    {
      if (is_owner)
        delete p;
    }

    /// Copy constructor, creates a clone of the pointed to object
    ClonablePtr(Self const& that) noexcept( std::is_nothrow_copy_constructible<T>::value )
      : p(new T(*that.p))
      , is_owner(true)
    {}

    /// Move constructor, copies the pointer only.
    ClonablePtr(Self&& that) noexcept
      : p(that.p)
      , is_owner(that.is_owner)
    {
      that.p = nullptr;
      that.is_owner = false;
    }

    /// Copy and move assignment operator, using the copy-and-swap idiom
    Self& operator=(Self that) noexcept
    {
      swap(that);
      return *this;
    }

    /// Factory method. creates a new Object of type T and stores the pointer.
    template <class... Args>
    static Self make(Args&&... args)
      noexcept( std::is_nothrow_constructible<T, remove_cvref_t<Args>...>::value )
    {
      return {new T(FWD(args)...), Self::alloc_tag()};
    }

    /// Access-method by dereferencing
    T& operator*() const noexcept
    {
      return *p;
    }

    /// Access-method by pointer access
    T* operator->() const noexcept
    {
      return p;
    }

    /// retrieve the underlying pointer
    T* get() const noexcept
    {
      return p;
    }

    /// Test whether pointer is NULL
    operator bool() const noexcept
    {
      return !(p == NULL);
    }

    void swap(Self& that) noexcept
    {
      using std::swap;
      swap(p, that.p);
      swap(is_owner, that.is_owner);
    }

  private:
    T* p = nullptr;		///< managed pointer
    bool is_owner = false;	///< true, if class is owner of pointer, false otherwise
  };

  template <class T>
  void swap(ClonablePtr<T>& a, ClonablePtr<T>& b) noexcept
  {
    a.swap(b);
  }

} // end namespace AMDiS