DISTRHO Plugin Framework
ScopedPointer.hpp
1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
6  * or without fee is hereby granted, provided that the above copyright notice and this
7  * permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifndef DISTRHO_SCOPED_POINTER_HPP_INCLUDED
18 #define DISTRHO_SCOPED_POINTER_HPP_INCLUDED
19 
20 #include "../DistrhoUtils.hpp"
21 
22 #include <algorithm>
23 
24 START_NAMESPACE_DISTRHO
25 
26 // -----------------------------------------------------------------------
27 // The following code was based from juce-core ScopedPointer class
28 // Copyright (C) 2013 Raw Material Software Ltd.
29 
30 //==============================================================================
31 /**
32  This class holds a pointer which is automatically deleted when this object goes
33  out of scope.
34 
35  Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer
36  gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or
37  as member variables is a good way to use RAII to avoid accidentally leaking dynamically
38  created objects.
39 
40  A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer
41  to an object. If you use the assignment operator to assign a different object to a
42  ScopedPointer, the old one will be automatically deleted.
43 
44  A const ScopedPointer is guaranteed not to lose ownership of its object or change the
45  object to which it points during its lifetime. This means that making a copy of a const
46  ScopedPointer is impossible, as that would involve the new copy taking ownership from the
47  old one.
48 
49  If you need to get a pointer out of a ScopedPointer without it being deleted, you
50  can use the release() method.
51 
52  Something to note is the main difference between this class and the std::auto_ptr class,
53  which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr
54  requires that you always call get() to retrieve the pointer. The advantages of providing
55  the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much
56  exactly the same way as a raw pointer. The disadvantage is that the compiler is free to
57  use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult
58  to return a ScopedPointer as the result of a function. To avoid this causing errors,
59  ScopedPointer contains an overloaded constructor that should cause a syntax error in these
60  circumstances, but it does mean that instead of returning a ScopedPointer from a function,
61  you'd need to return a raw pointer (or use a std::auto_ptr instead).
62 */
63 template<class ObjectType>
65 {
66 public:
67  //==============================================================================
68  /** Creates a ScopedPointer containing a null pointer. */
69  ScopedPointer() noexcept
70  : object(nullptr) {}
71 
72  /** Creates a ScopedPointer that owns the specified object. */
73  ScopedPointer(ObjectType* const objectToTakePossessionOf) noexcept
74  : object(objectToTakePossessionOf) {}
75 
76  /** Creates a ScopedPointer that takes its pointer from another ScopedPointer.
77 
78  Because a pointer can only belong to one ScopedPointer, this transfers
79  the pointer from the other object to this one, and the other object is reset to
80  be a null pointer.
81  */
82  ScopedPointer(ScopedPointer& objectToTransferFrom) noexcept
83  : object(objectToTransferFrom.object)
84  {
85  objectToTransferFrom.object = nullptr;
86  }
87 
88  /** Destructor.
89  This will delete the object that this ScopedPointer currently refers to.
90  */
92  {
93  delete object;
94  }
95 
96  /** Changes this ScopedPointer to point to a new object.
97 
98  Because a pointer can only belong to one ScopedPointer, this transfers
99  the pointer from the other object to this one, and the other object is reset to
100  be a null pointer.
101 
102  If this ScopedPointer already points to an object, that object
103  will first be deleted.
104  */
105  ScopedPointer& operator=(ScopedPointer& objectToTransferFrom)
106  {
107  if (this != objectToTransferFrom.getAddress())
108  {
109  // Two ScopedPointers should never be able to refer to the same object - if
110  // this happens, you must have done something dodgy!
111  DISTRHO_SAFE_ASSERT_RETURN(object == nullptr || object != objectToTransferFrom.object, *this);
112 
113  ObjectType* const oldObject = object;
114  object = objectToTransferFrom.object;
115  objectToTransferFrom.object = nullptr;
116  delete oldObject;
117  }
118 
119  return *this;
120  }
121 
122  /** Changes this ScopedPointer to point to a new object.
123 
124  If this ScopedPointer already points to an object, that object
125  will first be deleted.
126 
127  The pointer that you pass in may be a nullptr.
128  */
129  ScopedPointer& operator=(ObjectType* const newObjectToTakePossessionOf)
130  {
131  if (object != newObjectToTakePossessionOf)
132  {
133  ObjectType* const oldObject = object;
134  object = newObjectToTakePossessionOf;
135  delete oldObject;
136  }
137 
138  return *this;
139  }
140 
141  //==============================================================================
142  /** Returns the object that this ScopedPointer refers to. */
143  operator ObjectType*() const noexcept { return object; }
144 
145  /** Returns the object that this ScopedPointer refers to. */
146  ObjectType* get() const noexcept { return object; }
147 
148  /** Returns the object that this ScopedPointer refers to. */
149  ObjectType& getObject() const noexcept { return *object; }
150 
151  /** Returns the object that this ScopedPointer refers to. */
152  ObjectType& operator*() const noexcept { return *object; }
153 
154  /** Lets you access methods and properties of the object that this ScopedPointer refers to. */
155  ObjectType* operator->() const noexcept { return object; }
156 
157  //==============================================================================
158  /** Removes the current object from this ScopedPointer without deleting it.
159  This will return the current object, and set the ScopedPointer to a null pointer.
160  */
161  ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; }
162 
163  //==============================================================================
164  /** Swaps this object with that of another ScopedPointer.
165  The two objects simply exchange their pointers.
166  */
167  void swapWith(ScopedPointer<ObjectType>& other) noexcept
168  {
169  // Two ScopedPointers should never be able to refer to the same object - if
170  // this happens, you must have done something dodgy!
171  DISTRHO_SAFE_ASSERT_RETURN(object != other.object || this == other.getAddress() || object == nullptr,);
172 
173  std::swap(object, other.object);
174  }
175 
176 private:
177  //==============================================================================
178  ObjectType* object;
179 
180  // (Required as an alternative to the overloaded & operator).
181  const ScopedPointer* getAddress() const noexcept { return this; }
182 
183 #ifndef _MSC_VER // (MSVC can't deal with multiple copy constructors)
184  /* The copy constructors are private to stop people accidentally copying a const ScopedPointer
185  (the compiler would let you do so by implicitly casting the source to its raw object pointer).
186 
187  A side effect of this is that in a compiler that doesn't support C++11, you may hit an
188  error when you write something like this:
189 
190  ScopedPointer<MyClass> m = new MyClass(); // Compile error: copy constructor is private.
191 
192  Even though the compiler would normally ignore the assignment here, it can't do so when the
193  copy constructor is private. It's very easy to fix though - just write it like this:
194 
195  ScopedPointer<MyClass> m (new MyClass()); // Compiles OK
196 
197  It's probably best to use the latter form when writing your object declarations anyway, as
198  this is a better representation of the code that you actually want the compiler to produce.
199  */
200 # ifdef DISTRHO_PROPER_CPP11_SUPPORT
201  ScopedPointer(const ScopedPointer&) = delete;
202  ScopedPointer& operator=(const ScopedPointer&) = delete;
203 # else
206 # endif
207 #endif
208 };
209 
210 //==============================================================================
211 /** Compares a ScopedPointer with another pointer.
212  This can be handy for checking whether this is a null pointer.
213 */
214 template<class ObjectType>
215 bool operator==(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
216 {
217  return static_cast<ObjectType*>(pointer1) == pointer2;
218 }
219 
220 /** Compares a ScopedPointer with another pointer.
221  This can be handy for checking whether this is a null pointer.
222 */
223 template<class ObjectType>
224 bool operator!=(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
225 {
226  return static_cast<ObjectType*>(pointer1) != pointer2;
227 }
228 
229 // -----------------------------------------------------------------------
230 
231 END_NAMESPACE_DISTRHO
232 
233 #endif // DISTRHO_SCOPED_POINTER_HPP_INCLUDED
ScopedPointer::operator=
ScopedPointer & operator=(ObjectType *const newObjectToTakePossessionOf)
Definition: ScopedPointer.hpp:129
ScopedPointer::release
ObjectType * release() noexcept
Definition: ScopedPointer.hpp:161
ScopedPointer::operator->
ObjectType * operator->() const noexcept
Definition: ScopedPointer.hpp:155
ScopedPointer::~ScopedPointer
~ScopedPointer()
Definition: ScopedPointer.hpp:91
ScopedPointer::getObject
ObjectType & getObject() const noexcept
Definition: ScopedPointer.hpp:149
ScopedPointer::operator=
ScopedPointer & operator=(ScopedPointer &objectToTransferFrom)
Definition: ScopedPointer.hpp:105
ScopedPointer
Definition: ScopedPointer.hpp:64
ScopedPointer::ScopedPointer
ScopedPointer(ScopedPointer &objectToTransferFrom) noexcept
Definition: ScopedPointer.hpp:82
ScopedPointer::ScopedPointer
ScopedPointer() noexcept
Definition: ScopedPointer.hpp:69
ScopedPointer::ScopedPointer
ScopedPointer(ObjectType *const objectToTakePossessionOf) noexcept
Definition: ScopedPointer.hpp:73
ScopedPointer::get
ObjectType * get() const noexcept
Definition: ScopedPointer.hpp:146
ScopedPointer::operator*
ObjectType & operator*() const noexcept
Definition: ScopedPointer.hpp:152
ScopedPointer::swapWith
void swapWith(ScopedPointer< ObjectType > &other) noexcept
Definition: ScopedPointer.hpp:167