1 //-----------------------------------------------------------------------------
4 // Category : SDK Core Interfaces
5 // Filename : pluginterfaces/base/smartpointer.h
6 // Created by : Steinberg, 01/2004
7 // Description : Basic Interface
9 //-----------------------------------------------------------------------------
10 // This file is part of a Steinberg SDK. It is subject to the license terms
11 // in the LICENSE file found in the top-level directory of this distribution
12 // and at www.steinberg.net/sdklicenses.
13 // No part of the SDK, including this file, may be copied, modified, propagated,
14 // or distributed except according to the terms contained in the LICENSE file.
15 //-----------------------------------------------------------------------------
19 #include "pluginterfaces/base/fplatform.h"
20 #if SMTG_CPP11_STDLIBSUPPORT
24 //------------------------------------------------------------------------
27 //------------------------------------------------------------------------
29 //------------------------------------------------------------------------
30 /** IPtr - Smart pointer template class.
33 - can be used as an I* pointer
34 - handles refCount of the interface
37 IPtr<IPath> path (sharedPath);
46 //------------------------------------------------------------------------
47 inline IPtr (I
* ptr
, bool addRef
= true);
48 inline IPtr (const IPtr
&);
51 inline IPtr (const IPtr
<T
>& other
) : ptr (other
.get ())
60 inline I
* operator= (I
* ptr
);
62 inline IPtr
& operator= (const IPtr
& other
);
65 inline IPtr
& operator= (const IPtr
<T
>& other
)
67 operator= (other
.get ());
71 inline operator I
* () const { return ptr
; } // act as I*
72 inline I
* operator-> () const { return ptr
; } // act as I*
74 inline I
* get () const { return ptr
; }
76 #if SMTG_CPP11_STDLIBSUPPORT
77 inline IPtr (IPtr
<I
>&& movePtr
) SMTG_NOEXCEPT
: ptr (movePtr
.take ()) { }
80 inline IPtr (IPtr
<T
>&& movePtr
) SMTG_NOEXCEPT
: ptr (movePtr
.take ()) { }
82 inline IPtr
& operator= (IPtr
<I
>&& movePtr
) SMTG_NOEXCEPT
87 ptr
= movePtr
.take ();
92 inline IPtr
& operator= (IPtr
<T
>&& movePtr
)
97 ptr
= movePtr
.take ();
102 inline void reset (I
* obj
= nullptr)
109 I
* take () SMTG_NOEXCEPT
116 template <typename T
>
117 static IPtr
<T
> adopt (T
* obj
) SMTG_NOEXCEPT
{ return IPtr
<T
> (obj
, false); }
119 //------------------------------------------------------------------------
124 //------------------------------------------------------------------------
126 inline IPtr
<I
>::IPtr (I
* _ptr
, bool addRef
) : ptr (_ptr
)
132 //------------------------------------------------------------------------
134 inline IPtr
<I
>::IPtr (const IPtr
<I
>& other
) : ptr (other
.ptr
)
140 //------------------------------------------------------------------------
142 inline IPtr
<I
>::IPtr () : ptr (0)
146 //------------------------------------------------------------------------
148 inline IPtr
<I
>::~IPtr ()
153 ptr
= nullptr; //TODO_CORE: how much does this cost? is this something hiding for us?
157 //------------------------------------------------------------------------
159 inline I
* IPtr
<I
>::operator= (I
* _ptr
)
172 //------------------------------------------------------------------------
174 inline IPtr
<I
>& IPtr
<I
>::operator= (const IPtr
<I
>& _ptr
)
176 operator= (_ptr
.ptr
);
180 //------------------------------------------------------------------------
181 /** OPtr - "owning" smart pointer used for newly created FObjects.
184 FUnknown implementations are supposed to have a refCount of 1 right after creation.
185 So using an IPtr on newly created objects would lead to a leak.
186 Instead the OPtr can be used in this case. \n
189 OPtr<IPath> path = FHostCreate (IPath, hostClasses);
190 // no release is needed...
192 The assignment operator takes ownership of a new object and releases the old.
193 So its safe to write:
195 OPtr<IPath> path = FHostCreate (IPath, hostClasses);
196 path = FHostCreate (IPath, hostClasses);
199 This is the difference to using an IPtr with addRef=false.
202 IPtr<IPath> path (FHostCreate (IPath, hostClasses), false);
203 path = FHostCreate (IPath, hostClasses);
206 This will lead to a leak!
209 class OPtr
: public IPtr
<I
>
212 //------------------------------------------------------------------------
213 inline OPtr (I
* p
) : IPtr
<I
> (p
, false) {}
214 inline OPtr (const IPtr
<I
>& p
) : IPtr
<I
> (p
) {}
215 inline OPtr (const OPtr
<I
>& p
) : IPtr
<I
> (p
) {}
217 inline I
* operator= (I
* _ptr
)
219 if (_ptr
!= this->ptr
)
222 this->ptr
->release ();
229 //------------------------------------------------------------------------
230 /** Assigning newly created object to an IPtr.
233 IPtr<IPath> path = owned (FHostCreate (IPath, hostClasses));
235 which is a slightly shorter form of writing:
237 IPtr<IPath> path = OPtr<IPath> (FHostCreate (IPath, hostClasses));
243 return IPtr
<I
> (p
, false);
246 /** Assigning shared object to an IPtr.
249 IPtr<IPath> path = shared (iface.getXY ());
253 IPtr
<I
> shared (I
* p
)
255 return IPtr
<I
> (p
, true);
258 #if SMTG_CPP11_STDLIBSUPPORT
259 //------------------------------------------------------------------------
260 // Ownership functionality
261 //------------------------------------------------------------------------
267 /** Strong typedef for shared reference counted objects.
268 * Use SKI::adopt to unwrap the provided object.
269 * @tparam T Referenced counted type.
271 template <typename T
>
274 friend struct Detail::Adopt
;
278 /** Strong typedef for transferring the ownership of reference counted objects.
279 * Use SKI::adopt to unwrap the provided object.
280 * After calling adopt the reference in this object is null.
281 * @tparam T Referenced counted type.
283 template <typename T
>
286 friend struct Detail::Adopt
;
290 /** Strong typedef for using reference counted objects.
291 * Use SKI::adopt to unwrap the provided object.
292 * After calling adopt the reference in this object is null.
293 * @tparam T Referenced counted type.
295 template <typename T
>
298 friend struct Detail::Adopt
;
306 template <typename T
>
307 static IPtr
<T
> adopt (Shared
<T
>& ref
)
309 using Steinberg::shared
;
310 return shared (ref
.obj
);
313 template <typename T
>
314 static IPtr
<T
> adopt (Owned
<T
>& ref
)
316 using Steinberg::owned
;
317 IPtr
<T
> out
= owned (ref
.obj
);
322 template <typename T
>
323 static T
* adopt (Used
<T
>& ref
)
328 template <template <typename
> class OwnerType
, typename T
>
329 static OwnerType
<T
> toOwnerType (T
* obj
)
339 /** Common function to adopt referenced counted object.
340 * @tparam T Referenced counted type.
341 * @param ref The reference to be adopted in a smart pointer.
343 template <typename T
>
344 IPtr
<T
> adopt (Shared
<T
>& ref
) { return Detail::Adopt::adopt (ref
); }
346 template <typename T
>
347 IPtr
<T
> adopt (Shared
<T
>&& ref
) { return Detail::Adopt::adopt (ref
); }
349 /** Common function to adopt referenced counted object.
350 * @tparam T Referenced counted type.
351 * @param ref The reference to be adopted in a smart pointer.
353 template <typename T
>
354 IPtr
<T
> adopt (Owned
<T
>& ref
) { return Detail::Adopt::adopt (ref
); }
356 template <typename T
>
357 IPtr
<T
> adopt (Owned
<T
>&& ref
) { return Detail::Adopt::adopt (ref
); }
359 /** Common function to adopt referenced counted object.
360 * @tparam T Referenced counted type.
361 * @param ref The reference to be adopted in a smart pointer.
363 template <typename T
>
364 T
* adopt (Used
<T
>& ref
) { return Detail::Adopt::adopt (ref
); }
366 template <typename T
>
367 T
* adopt (Used
<T
>&& ref
) { return Detail::Adopt::adopt (ref
); }
369 /** Common function to wrap owned instances. */
370 template <typename T
>
371 Owned
<T
> toOwned (T
* obj
) { return Detail::Adopt::toOwnerType
<Owned
> (obj
); }
373 /** Common function to wrap shared instances. */
374 template <typename T
>
375 Shared
<T
> toShared (T
* obj
) { return Detail::Adopt::toOwnerType
<Shared
> (obj
); }
377 /** Common function to wrap used instances. */
378 template <typename T
>
379 Used
<T
> toUsed (T
* obj
) { return Detail::Adopt::toOwnerType
<Used
> (obj
); }
381 //------------------------------------------------------------------------