MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
countedptr.h
Go to the documentation of this file.
1 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _countedptr_h
41 #define _countedptr_h
42 
43 #include "datatypes.h"
44 
45 /// @file
46 /// @brief This file describes and implements a reference counted pointer that is NOT threadsafe
47 namespace Mezzanine
48 {
49  /// @brief CountedPointer casting implementation states.
50  /// @details
51  /// The CountedPtrCast uses some template metaprogramming to include the correct cast at compile time
52  /// in the CountedPtr. In some situations it is difficult to cast from one kind of pointer to another
53  /// even when it is conceptually sound to do so. For example, when virtual inheritance is used
54  /// downcasting can be difficult even when a pointer was just returned from one member of an object
55  /// into another member of that object but from a member function whose interface specified a more
56  /// base return type. While possible to work around this normally, imagine the same situation if
57  /// some of the types involved were templates.
59  {
60  CastNoneError = -2, ///< No Casting, any cast attempt results in a compilation Error.
61  CastNoneReturnZero = -1, ///< No Casting, 0 is returned. Useful when types are unknown and dynamic casts are already used and checked.
62  CastImplicit = 1, ///< Does no casting, but keeps types distinct. This should allow implicit casts to more base types, and disallow casts to derived types.
63  CastStatic = 2, ///< A static cast from the pointer as provided with no attempt to calls functions on the pointer target, this is default for externally reference counted pointers.
64  CastDynamic = 3 ///< A dynamic cast from the pointer as provided with no attempt to calls functions on the pointer target, this is default for externally reference counted pointers.
65  };
66 
67  #ifndef SWIG
68  // Forward Declares Just about everything in this file
69  // The Pointer itself
70  template <typename TypePointedTo> class CountedPtr;
71 
72  // Externally callable casts
73  template <typename ReturnType, typename OtherPointerTargetType> CountedPtr<ReturnType> CountedPtrCast(CountedPtr<OtherPointerTargetType>& Original);
74  template <typename ReturnType, typename OtherPointerTargetType> CountedPtr<ReturnType> CountedPtrStaticCast(CountedPtr<OtherPointerTargetType>& Original);
75  template <typename ReturnType, typename OtherPointerTargetType> CountedPtr<ReturnType> CountedPtrDynamicCast(CountedPtr<OtherPointerTargetType>& Original);
76 
77  // Casts the pointer uses internally for consistency.
78  template <typename ReturnPointer, typename OriginalPointer, CountedPointerCastingState> class CountedPtrCastImpl;
79  template <typename OriginalPointer> class CountedPtrCastImpl <OriginalPointer, OriginalPointer, CastNoneError>;
80  template <typename ReturnPointer, typename OriginalPointer> class CountedPtrCastImpl <ReturnPointer, OriginalPointer, CastNoneReturnZero>;
81  template <typename ReturnPointer, typename OriginalPointer> class CountedPtrCastImpl <ReturnPointer, OriginalPointer, CastStatic>;
82  template <typename ReturnPointer, typename OriginalPointer> class CountedPtrCastImpl <ReturnPointer, OriginalPointer, CastDynamic>;
83 
84  template <typename Pointer> Pointer* CountedPtrInternalCast(Pointer* Original);
85  template <typename ReturnPointer, typename OriginalPointer> ReturnPointer* CountedPtrInternalCast(const OriginalPointer* Original);
86 
87  template <typename T> class ReferenceCountTraits;
88 
89  ///////////////////////////////////////////////////////////////////////////////
90  /// @brief This exists once per object managed by a group of shared pointer to track items in memory.
91  /// @details This exists to track the pointer to the managed object, and stores the single
92  /// counter of existing references. Only one of these should be created for each group of
93  /// pointers managing the same object.
94  /// @note It should be extremely rare to need to create one of these outside of pointer implemenation.
95  ///////////////////////////////////////////////////////////////////////////////
96  template <typename TypePointedTo> class ReferenceCount
97  {
98  private:
99  /// @brief The Pointer that is the crux of this class, At this smart pointer's core there must be a raw pointer.
100  TypePointedTo* Target;
101 
102  /// @brief This is the Counter that stores how many references exist
103  Whole RefCount;
104 
105  public:
106  /// @brief Constructor
107  /// @param InitialPointer A pointer to the type of this template. This defaults to 0 if not provided
108  /// @param InitialCount The number of references to default to this defaults to 1 if not provided.
109  ReferenceCount(TypePointedTo* InitialPointer = 0, unsigned InitialCount = 0)
110  : Target(InitialPointer), RefCount(InitialCount)
111  {}
112 
113  /// @brief Destructor, cleans up the object when the last reference deletes this
114  virtual ~ReferenceCount()
115  { delete Target; }
116 
117  /// @brief Increase the reference count by one and return the updated count.
118  /// @return The updated count;
120  { return ++RefCount; }
121 
122  /// @brief Decrease the reference count by one and return the updated count.
123  /// @return The updated count;
125  { return --RefCount; }
126 
127  /// @brief Gets the actual pointer to the target.
128  /// @return A Pointer of the targeted type to the object being managed.
130  { return Target; }
131 
132  /// @brief Get the current amount of references.
133  /// @return A Whole with the current reference count
135  { return RefCount; }
136 
137  /// @brief Get a pointer to the Target as a The most derived type in of this object*
138  /// @return A pointer, for use with CountedPtrCast
139  virtual TypePointedTo* GetMostDerived()
140  { return Target; }
141  };
142 
143  /// @brief A sample class that implements a minimal intrusive reference counting scheme.
144  /// @details It might work to inherit from this, however on some platforms multiple inheritance
145  /// comes with the exact same cost intrusive pointers are designed to avoid. This should be used
146  /// as an example of how to implement a reference counted object.
148  {
149  private:
150  /// @brief This is the Counter that stores how many references exist
151  Whole RefCount;
152 
153  public:
154  /// @brief Constructor for instatiating the Reference Count
155  IntrusiveRefCount(): RefCount(0)
156  {}
157 
158  /// @brief Increase the reference count by one and return the updated count.
159  /// @return The updated count;
161  { return ++RefCount; }
162 
163  /// @brief Decrease the reference count by one and return the updated count.
164  /// @return The updated count;
166  { return --RefCount; }
167 
168  /// @brief Gets the actual pointer to the target.
169  /// @return A Pointer of the targeted type to the object being managed.
171  { return this; }
172 
173  /// @brief Get the current amount of references.
174  /// @return A Whole with the current reference count
176  { return RefCount; }
177 
178  /// @brief Get a pointer to the most Derived type of this class
179  /// @return A pointer of the most derived pointing to this.
181  { return this; }
182 
183  /// @brief Virtual Deconstructor to prevent issues with deletion with incomplete type information
184  virtual ~IntrusiveRefCount() {}
185  };
186 
187  ///////////////////////////////////////////////////////////////////////////////
188  /// @brief This is used to deduce at compile if a specific class has built-in reference counting or needs an external reference count.
189  /// @details Every class that does not implement its own reference count gets this default one.
190  /// The Default reference count is not thread-safe, and requires that every dereferencing
191  /// of the smart pointer has the cost of a double dereference. The double dereference is caused because
192  /// the reference counter has to store a native pointer to the managed object. In benchmarks
193  /// included with the Unit tests this seems to increase dereference time by about double.
194  /// @n @n
195  /// Any class that provides TypePointedTo* GetReferenceCountTargetAsPointer(), Whole GetReferenceCount(),
196  /// Whole IncrementReferenceCount(), Whole DecrementReferenceCount()
197  /// and something* GetMostDerived() (which need to be virtual if inheritance is used to be useful) can be used as a reference
198  /// counter. If it provides these then a specialization of ReferenceCountTraits should be implemented for a given class
199  /// and CountedPtr will use the type defined by ReferenceCountTraits<T>::RefCountType as the counter. @n @n
200  /// The Mezzanine provides a Reference count class that can be used with any type at the cost of
201  /// extra dereferences. Some types (Scripts) have their own internal reference count that when used
202  /// will increase the locality (since the reference count is part of the managed object) and reduce
203  /// dereferences to exactly one. Since the CountedPtr is the size of a native pointer if it is used
204  /// with an internal reference count, the only signifigant overhead should be the counting itself.
205  template <typename T>
206  class ReferenceCountTraits
207  {
208  public:
209  /// @brief This is type of the ReferenceCounter, The type of the class if reference counting is instrusive.
211 
212  /// @brief This will somehow return a pointer to the reference count
213  /// @param Target A pointer the freshly created object.
214  /// @return This will return a pointer to a valid reference counter.
215  /// @note The default implemetation call new with a matching delete in CounterPtr::~CountedPtr . If no allocations are required this may simply return the passed parameter.
217  { return new RefCountType(Target); }
218 
219  /// @brief Used to determine if the data a CountedPtr is managing can be cast
220  /// @details This uses the @ref CountedPointerCastingState to enter a value the Template MetaProgramming Machinery will understand.
221  enum { IsCastable = CastStatic };
222  };
223 
224  /// @brief An Example ReferenceCountTraits implmentation.
225  /// @details Anything with an internal Reference should implement a specialization of this template
226  /// that defines PtrType to be a pointer to the structure with the reference count interface in
227  /// to the items defined in the main ReferenceCountTraits documentation.
228  template <>
230  {
231  public:
232  /// @brief The sample internal reference count needs to indicate that the managed type is the same as the ReferenceCountType, because it will have a counter.
234 
235  /// @brief Because The reference count is allocated when the caller created the target this does not need to allocate a Reference count separetaly.
236  /// @param The create object to manage.
237  /// @return This is expected to return a valid reference count, since the reference count is in the target, this returns whatever was passed in,
239  { return Target; }
240 
241  /// @brief What kind of casting should be done when the target must be down(or side) cast.
242  enum { IsCastable = CastStatic};
243  };
244 
245  /// @internal
246  /// @brief This exists to conceal internal type detection mechanisms making internal and external reference couting different.
247  namespace
248  {
249  /// @brief This handles the case of needing to adjust the reference count of covariant pointers all covariant pointer must use internal reference counts
250  template <typename CurrentReferenceCountType, typename OtherReferenceCountType>
251  class ReferenceCountAdjuster
252  {
253  public:
254  /// @brief Gain a copy of the reference counter with appropriate type data.
255  /// @param UpdateCounter A reference to a pointer that the CounterPtr wants to point at the correct reference count
256  /// @param OtherCounter A reference to a pointer that is pointing to the refence counter we want to acquire
257  static void Acquire(CurrentReferenceCountType* & UpdateCounter, OtherReferenceCountType* & OtherCounter)
258  { UpdateCounter = CountedPtrInternalCast<CurrentReferenceCountType>(OtherCounter->GetMostDerived()); }
259  };
260 
261  /// @brief The logic is much simpler when covariant types are not involved, this will acwuire a reference counter
262  /// @details Incidentally this should work for internal reference counts that are of identical type and all external reference counts.
263  template <typename InternalReferenceCount>
264  class ReferenceCountAdjuster<InternalReferenceCount,InternalReferenceCount>
265  {
266  public:
267  /// @brief Gain a copy of the reference counter which already has appropriate type data.
268  /// @param UpdateCounter A reference to a pointer that the CounterPtr wants to point at the correct reference count.
269  /// @param OtherCounter A reference to a pointer that is pointing to the refence counter we want to acquire.
270  static void Acquire(InternalReferenceCount* & UpdateCounter, InternalReferenceCount* & OtherCounter)
271  { UpdateCounter = OtherCounter; }
272  };
273  }
274  #endif // \SWIG
275 
276  ///////////////////////////////////////////////////////////////////////////////
277  /// @brief A simple reference counting pointer.
278  /// @details This is a pointer that automatically deallocates the object it manages when
279  /// all CountedPtr intances managing it are destroyed or fall out of scope. This is a
280  /// simpler version of std::shared_ptr.
281  /// @warning This is not thread safe by default.
282  /// @warning If you intead to have covariant pointers (Multiple pointers to the same item but with different type date, like more base or more derived pointers) all classes pointed to must have virtual deconstructors
283  /// @note The basis of this class originated externally, please see the counted pointer
284  /// from http://ootips.org/yonat/4dev/smart-pointers.html which came with written permission
285  /// for use stated as "Feel free to use my own smart pointers in your code" on that page.
286  ///////////////////////////////////////////////////////////////////////////////
287  template <typename TypePointedTo>
288  class CountedPtr
289  {
290  public:
291  /// @brief The non pointer version of PtrType
293 
294  /// @brief This makes referencing the type of the pointer object easier for external classes.
295  typedef TypePointedTo element_type;
296 
297  /// @brief declare all pointers as friends so they can reference eachother _ReferenceCounter.
298  template <typename OtherPointer> friend class CountedPtr;
299 
300  /// @brief Static casting can access internals also
301  template <typename ReturnType, typename OtherPointerTargetType> friend CountedPtr<ReturnType> CountedPtrStaticCast(CountedPtr<OtherPointerTargetType>& Original);
302  protected:
303  /// @brief This is the only data on this class, a pointer to the counter and the managed object.
305 
306  /// @brief Have this pointer point at the same thing another pointer points to,
307  /// @param CounterToAcquire The ReferenceCounter that this pointer will use.
308  /// @warning This does not Release the previous Reference counter. This means it is possible leak memory if a ReferenceCounter is acquired that differs from the previous one without plans to manage the original.
309  /// @throw Nothing This member function does not throw exceptions, unless debug logging is enabled, then it can throw any exception the logger can throw.
310  template <typename AnyReferenceCountType>
311  void Acquire(AnyReferenceCountType* CounterToAcquire) throw()
312  {
313  ReferenceCountAdjuster<RefCountType, AnyReferenceCountType>::Acquire(_ReferenceCounter, CounterToAcquire);
314  if (_ReferenceCounter)
316  }
317 
318  /// @brief This decrements the reference count and deletes the managed items if there are no remaining references.
319  void Release() throw()
320  {
321  if (_ReferenceCounter)
322  {
324  {
325  delete _ReferenceCounter; // deleting a ReferenceCount should clean up the target object in its destructor, if we are deleting something intrusively reference counted this does
326  _ReferenceCounter = 0;
327  }
328  }
329  }
330 
331  /// @brief If required create a reference counter and point this at the passed pointer.
332  /// @param PointerTarget the Pointer to take ownership of.
333  void FirstAcquire(TypePointedTo* PointerTarget)
335 
336  public:
337  /// @brief Initializing Constructor
338  /// @details This should only be used for initial creation of a shared pointer group. This will allocate the raw
339  /// pointer and the ReferenceCounter that will be used to track the pointer passed. This will only be explicitly
340  /// called to prevent accidental premature deletion of the item managed.
341  /// @n @n It is quite easy to accidentally
342  /// make a secondary group of counted pointers if not using the new statement inline with this constructor, and it is
343  /// not recomended to use this in any other way. Here is an example of the recommended way to use new inline with this:
344  /// "Mezzanine::CountedPtr<Mezzanine::Vector3> VecPtr (new Mezzanine::Vector3);"
345  /// @param PointerTarget The item that will be deleted once all the pointer of this group disappear.
346  explicit CountedPtr(TypePointedTo* PointerTarget = 0) throw()
347  {
348  if(PointerTarget)
349  { FirstAcquire(PointerTarget); }
350  else
351  { _ReferenceCounter = NULL; }
352  }
353 
354  /// @brief Deconstructor, Just calls Release().
355  ~CountedPtr() throw()
356  { Release(); }
357 
358  /// @brief Copy constructor
359  /// @param Original The pointer being copied. This fresh pointer will use the same ReferenceCounter as the original.
360  /// @throw Nothing This member function does throws exceptions.
361  CountedPtr(const CountedPtr& Original) throw()
362  { Acquire( Original._ReferenceCounter ); }
363 
364  /// @brief Casting copy constructor
365  /// @param Original The CountedPtr being copied. This fresh pointer will use the same ReferenceCounter as the original.
366  /// @throw Nothing This member function does throws exceptions, unless the casting mechanism throws, which it shouldn't.
367  template <typename OtherPointer>
368  CountedPtr(const CountedPtr<OtherPointer>& Original) throw() : _ReferenceCounter(NULL)
369  {
370  //Acquire( CountedPtr<TypePointedTo>(Original)._ReferenceCounter );
371  Acquire( Original._ReferenceCounter );
372  }
373 
374  /// @brief Reset this to point at nothing.
375  void Reset()
376  {
377  Release();
378  _ReferenceCounter = NULL;
379  }
380 
381  /// @copydoc Reset()
382  /// @note Provided to match method names on standard smart pointers
383  void reset()
384  { Reset(); }
385 
386  /// @brief Reset this to point at the same as another CountedPtr of the same type.
387  /// @param Other Another CountedPtr which will share ownership of the target.
388  void Reset(const CountedPtr<TypePointedTo>& Other)
389  {
390  if (this != &Other) {
391  Release();
392  Acquire(Other._ReferenceCounter);
393  }
394  }
395 
396  /// @copydoc Reset(const CountedPtr<TypePointedTo>&)
397  /// @note Provided to match method names on standard smart pointers
398  void reset(const CountedPtr<TypePointedTo>& Other)
399  { Reset(Other); }
400 
401  /// @brief Take ownership of the passed pointer.
402  /// @param PointerTarget The pointer to assume ownership of.
403  void Reset(TypePointedTo* PointerTarget)
404  {
405  if(PointerTarget)
406  { FirstAcquire(PointerTarget); }
407  else
408  { _ReferenceCounter = NULL; }
409  }
410 
411  /// @copydoc Reset(TypePointedTo*)
412  /// @note Provided to match method names on standard smart pointers
413  void reset(TypePointedTo* PointerTarget)
414  { Reset (PointerTarget); }
415 
416  /// @brief Get the current count of references.
417  /// @note This name was chosen to match standard compliant names, and should be usable in templates that require this function.
418  /// @return The amount of references which still exist, or 0 if the reference counter is somehow invalid.
419  /// @throw Nothing This member function does not throws exceptions.
420  Whole UseCount() const throw()
422 
423  /// @copydoc UseCount
424  /// @note Provided to match method names on standard smart pointers
425  Whole use_count() const throw()
426  { return UseCount(); }
427 
428  /// @brief Assignement operator
429  /// @details This safely handles the semantics or release the previously assigned object and acquiring the new
430  /// managed object. This performs basic checks as expected.
431  /// @param Other The Item on the right hand side of the '=', which this class instance will copy.
432  /// @return A reference to this.
433  CountedPtr& operator=(const CountedPtr& Other) throw()
434  {
435  if (this != &Other) {
436  Release();
437  Acquire(Other._ReferenceCounter);
438  }
439  return *this;
440  }
441 
442  /// @brief Dereference operator.
443  /// @return The managed object is returned by reference.
444  /// @throw Nothing This member function does not throw exceptions.
445  TypePointedTo& operator*() const throw()
447 
448  /// @brief The Structure dereference operator.
449  /// @return Makes it appear, syntactically, as though you are dereferencing the raw pointer.
450  /// @throw Nothing This member function does not throw exceptions.
451  TypePointedTo* operator->() const throw()
452  { return CountedPtrInternalCast<TypePointedTo>(_ReferenceCounter->GetMostDerived()); }
453 
454  /// @brief Get the raw pointer to the managed object.
455  /// @return The raw pointer to the managed object or 0 if this pointer is invalid.
456  /// @throw Nothing This member function does not throw exceptions.
457  /// @note This name was chosen to match standard compliant names, and should be usable in templates that require this function.
458  TypePointedTo* Get() const throw()
459  { return CountedPtrInternalCast<TypePointedTo>(_ReferenceCounter->GetMostDerived()); }
460 
461  /// @copydoc Get
462  /// @note Provided to match method names on standard smart pointers
463  TypePointedTo* get() const throw()
464  { return Get(); }
465 
466  /// @brief Is this the only pointer to the managed object
467  /// @return True if use_count() == 1 or if the pointer is invalid
468  /// @throw Nothing This member function does not throw exceptions.
469  /// @note This name was chosen to match standard compliant names, and should be usable in templates that require this function.
470  bool Unique() const throw()
471  { return _ReferenceCounter ? _ReferenceCounter->GetReferenceCount()==1 : true; }
472 
473  /// @copydoc Unique
474  /// @note Provided to match method names on standard smart pointers
475  bool unique() const throw()
476  { return Unique(); }
477 
478  /// @brief A comparision of two CountedPtr instances
479  /// @details This is used to see if this and another CountedPtr are managing the same
480  /// object and are part of the same group of CountedPtr managing that object.
481  /// @param Other The CountedPtr on the right hand side of the ==
482  /// @return This returns true if this and Other use the same reference count and pointer.
483  bool operator==(const CountedPtr& Other) const throw()
484  { return Other._ReferenceCounter == _ReferenceCounter; }
485 
486  /// @brief Returns true if this pointer points to something.
487  /// @warning Without C++11 this can be accidentally easily be cast to a bool and can do sill things.
488  operator bool() const throw()
489  { return 0 != _ReferenceCounter; }
490 
491  /// @internal
492  /// @brief Get the internal Reference count
493  /// @return A pointer to internal reference count of this pointer.
495  { return _ReferenceCounter; }
496  };
497 
498  #ifndef SWIG
499  /// @internal
500  /// @brief This is used as to determine how a CountedPtr performs castin between pointer types internally.
501  /// @details The default implementation for internal casting in the CountedPtr Simply throws an exception.
502  /// @n @n
503  /// This Should never actually get called. Though it is the default template instance
504  /// the default ReferenceCountTraits uses the CastNoneError specialization of this template.
505  /// @n @n
506  /// The ReferenceCountTraits for the CountedPtr<Type> should declare what kind castint should be used by
507  /// declaring an enumeration called 'IsCastable' and assigning the desired casting type.
508  /// @code
509  /// enum { IsCastable = CastStaticVirtual };
510  /// @endcode
511  /// @param ReturnPointer The type of pointer that the functions on the CountedPtr must return
512  /// @param OriginalPointer The actual type the CountedPtr is maintaining as a target.
513  /// @param CountedPointerCastingState Any value in the @ref CountedPointerCastingState to indicate kind of casting.
514  /// @details For any case that uses CastNoneError including the default.
515  template <typename ReturnPointer, typename OriginalPointer, CountedPointerCastingState>
516  class CountedPtrCastImpl
517  {
518  public:
519  /// @internal
520  /// @brief Do not cast, rather fail.
521  /// @return Always fails by throwing
522  /// @throw Always throws a 0
523  static ReturnPointer Cast(OriginalPointer)
524  {
525  // #error Invalid Casting value for CountedPtr cast
526  throw(0); /// @todo make this conditionally fail to compile.
527  return ReturnPointer(0);
528  }
529  };
530 
531  /// @internal
532  /// @brief An implementation of the CountedPtrCast that always return the pointer passed reached via CastNoneError in the ReferenceCountTraits of the target class.
533  /// @param OriginalPointer The type of the original pointer and return value must match exactly
534  /// @note Since this requires both matching pointer types and CastNoneError to be present in the ReferenceCountTraits This should produce a compilation error when somethign is set wrong.
535  template <typename OriginalPointer>
536  class CountedPtrCastImpl <OriginalPointer, OriginalPointer, CastNoneError>
537  {
538  public:
539  /// @internal
540  /// @brief This literally does nothing and returns the value passed, so simple all but the dumbest compilers will optimize it away at compile time.
541  /// @return Whatever was passed.
542  static OriginalPointer Cast(OriginalPointer Original)
543  { return Original; }
544  };
545 
546  /// @internal
547  /// @brief An implementation of the CountedPtrCast that always returns 0 cast to the original pointer type. Reached by putting CastNoneReturnZero in the ReferenceCountTraits of the target class.
548  /// @param ReturnPointer The type of the NULL pointer to create.
549  /// @param OriginalPointer The type of the pointer prior to casting.
550  template <typename ReturnPointer, typename OriginalPointer>
551  class CountedPtrCastImpl <ReturnPointer, OriginalPointer, CastNoneReturnZero>
552  {
553  public:
554  /// @internal
555  /// @brief This accepts a parameter solely for compatibility with other templates and always returns 0.
556  /// @return Always 0
557  static ReturnPointer Cast(OriginalPointer)
558  { return ReturnPointer(0); }
559  };
560 
561  /// @internal
562  /// @brief An implementation of the CountedPtrCast that casts the passed pointer. Reached by putting CastStatic in the ReferenceCountTraits of the target class.
563  /// @param ReturnPointer The type of the pointer to target with the static cast
564  /// @param OriginalPointer The type of the pointer prior to casting.
565  template <typename ReturnPointer, typename OriginalPointer>
566  class CountedPtrCastImpl <ReturnPointer, OriginalPointer, CastImplicit>
567  {
568  public:
569  /// @internal
570  /// @brief Simply static cast the passed pointer.
571  /// @param Original the passed pointer.
572  /// @return The pointer after the cast.
573  /// @note This will almost certainly never actually exists as a function, in even basic testing the compiles completely optimizes this out during compilation.
574  static ReturnPointer Cast(OriginalPointer Original)
575  { return static_cast<ReturnPointer>(Original); }
576  };
577 
578  /// @internal
579  /// @brief An implementation of the CountedPtrCast that naively static casts the passed pointer. Reached by putting CastStatic in the ReferenceCountTraits of the target class.
580  /// @param ReturnPointer The type of the pointer to target with the static cast
581  /// @param OriginalPointer The type of the pointer prior to casting.
582  template <typename ReturnPointer, typename OriginalPointer>
583  class CountedPtrCastImpl <ReturnPointer, OriginalPointer, CastStatic>
584  {
585  public:
586  /// @internal
587  /// @brief Simply static cast the passed pointer.
588  /// @param Original the passed pointer.
589  /// @return The pointer after the cast.
590  /// @note This will almost certainly never actually exists as a function, in even basic testing the compiles completely optimizes this out during compilation.
591  static ReturnPointer Cast(OriginalPointer Original)
592  { return dynamic_cast<ReturnPointer>(Original); }
593  };
594 
595  /// @internal
596  /// @brief An implementation of the CountedPtrCast that naively dynamic casts the passed pointer. Reached by putting CastDynamic in the ReferenceCountTraits of the target class.
597  /// @param ReturnPointer The type of the pointer to target with the dynamic cast.
598  /// @param OriginalPointer The type of the pointer prior to casting.
599  template <typename ReturnPointer, typename OriginalPointer>
600  class CountedPtrCastImpl <ReturnPointer, OriginalPointer, CastDynamic>
601  {
602  public:
603  /// @internal
604  /// @brief Simply dynamic cast the passed pointer.
605  /// @param Original the passed pointer.
606  /// @return The pointer after the cast.
607  /// @note This will almost certainly never actually exists as a function, tests show this as performant as a normal call to dynamic_cast.
608  static ReturnPointer Cast(OriginalPointer Original)
609  { return dynamic_cast<ReturnPointer>(Original); }
610  };
611 
612  /// @internal
613  /// @brief Used internally by CounterPtr to abstract away casts in the case where the return type would *NOT* match the input type.
614  /// @param ReturnPointer The type of the pointer to target after using the Casting Strategy described in the classes ReferenceCountTraits.
615  /// @param OriginalPointer The type of the pointer prior to casting.
616  /// @note The function argument Original is of type const OriginalPointer. When search for possible matching functions an template a compiler prioritizes functions that are off by just a CV qualifier ahead of those that it would need to implicitly cast to call. So if the to pointer types match exactly this will not be called.
617  /// @param Original The Pointer to cast which must be exactly of the type OriginalPointer(Which might be inferable).
618  /// @return A pointer of the type ReturnPointer after the desired casting strategy has been used.
619  template <typename ReturnPointer, typename OriginalPointer>
620  ReturnPointer* CountedPtrInternalCast(const OriginalPointer* Original)
621  {
622  return CountedPtrCastImpl
623  <
624  ReturnPointer*,
625  OriginalPointer*,
627  (
629  )
630  >::Cast(
631  const_cast<OriginalPointer*>(Original) // cast away the constness we just added
632  );
633  }
634 
635  /// @internal
636  /// @brief Used internally by CounterPtr to abstract away casts in the case where the return type would match the input type.
637  /// @details This enforces the logic that cast should only be performed inside the CountedPtr when a cast is required. This
638  /// also has the advantage of not performing meaningless extra casts if a runtime cast is used, so it coudl enhance performance.
639  /// @param Pointer The only type of pointers involved.
640  /// @param Original The pointer that needs to be checked to see if it should be cast and this compilation case does not require it.
641  /// @return The value passed in Original.
642  template <typename Pointer>
643  Pointer* CountedPtrInternalCast(Pointer* Original)
644  { return Original; }
645 
646  /// @brief A compile time cast that uses only the implicit conversion of the underlying raw pointers
647  /// @param ReturnType The type to be returned, must be specified
648  /// @param OtherPointerTargetType The type of the provided pointer, this can be infered and should not be provided.
649  /// @param Original The pointer to convert.
650  /// @return Either a pointer of the desired or a compilation error
651  template <typename ReturnType, typename OtherPointerTargetType>
653  { return CountedPtr<ReturnType>(Original); }
654 
655  /// @brief A compile time cast that uses static casting conversion of the underlying raw pointers but only works on internally reference count types
656  /// @param ReturnType The type to be returned, must be specified
657  /// @param OtherPointerTargetType The type of the provided pointer, this can be infered and should not be provided.
658  /// @param Original The pointer to convert.
659  /// @return Either a pointer of the desired or a compilation error
660  template <typename ReturnType, typename OtherPointerTargetType>
662  { return CountedPtr<ReturnType>(static_cast<ReturnType*>(Original.GetReferenceCount())); }
663 
664  /// @brief A Runtime cast that uses dynamic casting conversion of the underlying raw pointers but only works on internally reference count types
665  /// @param ReturnType The type to be returned, must be specified
666  /// @param OtherPointerTargetType The type of the provided pointer, this can be infered and should not be provided.
667  /// @param Original The pointer to convert.
668  /// @return Either a pointer of the desired or a 0 if casting is not possible.
669  template <typename ReturnType, typename OtherPointerTargetType>
671  { return CountedPtr<ReturnType>(dynamic_cast<ReturnType*>(Original.GetReferenceCount())); }
672  #endif // \SWIG
673 
674 } // \Mezzanine
675 
676 #endif // _smartptr_h