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