Bromeon
SmartPtr/CopiedPtrPolicies.hpp
Go to the documentation of this file.
00001 
00002 //
00003 // Thor C++ Library
00004 // Copyright (c) 2011 Jan Haller
00005 // 
00006 // This software is provided 'as-is', without any express or implied
00007 // warranty. In no event will the authors be held liable for any damages
00008 // arising from the use of this software.
00009 // 
00010 // Permission is granted to anyone to use this software for any purpose,
00011 // including commercial applications, and to alter it and redistribute it
00012 // freely, subject to the following restrictions:
00013 // 
00014 // 1. The origin of this software must not be misrepresented; you must not
00015 //    claim that you wrote the original software. If you use this software
00016 //    in a product, an acknowledgment in the product documentation would be
00017 //    appreciated but is not required.
00018 // 
00019 // 2. Altered source versions must be plainly marked as such, and must not be
00020 //    misrepresented as being the original software.
00021 // 
00022 // 3. This notice may not be removed or altered from any source distribution.
00023 //
00025 
00028 
00029 #ifndef THOR_COPIEDPTRPOLICIES_HPP
00030 #define THOR_COPIEDPTRPOLICIES_HPP
00031 
00032 #include <typeinfo>
00033 #include <cassert>
00034 
00035 
00036 namespace thor
00037 {
00038 namespace detail
00039 {
00040 
00041     // Suppresses warnings at some compilers because the variable seems to be unused (although it is needed as typeid operand)
00042     inline void SuppressUnusedWarning(const void*)
00043     {
00044     }
00045     
00046     // Returns true when the dynamic types of *lhs and *rhs are equal
00047     template <typename T>
00048     bool SameDynamicPointerType(const T* lhs, const T* rhs)
00049     {
00050         SuppressUnusedWarning(lhs);
00051         SuppressUnusedWarning(rhs);
00052     
00053         return typeid(*lhs) == typeid(*rhs);
00054     }
00055     
00056     // Returns true when the dynamic types of Lhs and *rhs are equal
00057     template <typename Lhs>
00058     bool SameDynamicPointerType(const Lhs* rhs)
00059     {
00060         SuppressUnusedWarning(rhs);
00061             
00062         return typeid(Lhs) == typeid(*rhs);
00063     }
00064     
00065 } // namespace detail
00066 
00067 // ---------------------------------------------------------------------------------------------------------------------------
00068 
00069 
00072 
00077 template <typename T>
00078 struct StaticCopy
00079 {
00080     static T* Copy(const T* originPtr)
00081     {
00082         T* copiedPtr = new T(*originPtr);
00083         
00084         // Prevent slicing
00085         assert( detail::SameDynamicPointerType<T>(copiedPtr, originPtr) );
00086         
00087         return copiedPtr;
00088     }
00089     
00090     static void Destroy(T* pointer)
00091     {
00092         // Check if it's safe to delete pointer and if we don't slice a base object
00093         assert( !pointer || detail::SameDynamicPointerType<T>(pointer) );
00094         
00095         delete pointer;
00096     }
00097 };
00098 
00104 template <typename T>
00105 struct DynamicCopy
00106 {
00107     template <class DynamicType> 
00108     static T* Copy(const DynamicType* originPtr)
00109     {
00110         T* copiedPtr = new DynamicType(*originPtr);
00111         
00112         // Make sure we called the actual dynamic type's copy constructor and prevent slicing.
00113         // In case this assertion fails, you didn't pass a pointer to the object's actual type at SmartPtr(U*) or Reset(U*).
00114         // If U is not polymorphic (which is allowed), typeid can't access the dynamic types, therefore it only compares the static
00115         // types, which are of course equal. In this case, the assertion is useless, but not problematic.
00116         // Ignore const-qualification for comparison
00117         assert( detail::SameDynamicPointerType<T>(copiedPtr, originPtr) );
00118         
00119         // Return pointer to deeply copied instance
00120         return copiedPtr;
00121     }
00122     
00123     template <class DynamicType> 
00124     static void Destroy(DynamicType* pointer)
00125     {   
00126         // Check if it's safe to delete pointer and if we don't slice a base object
00127         assert( !pointer || detail::SameDynamicPointerType<DynamicType>(pointer) );
00128         
00129         delete pointer;
00130     }
00131 };
00132 
00136 template <typename T>
00137 struct VirtualClone
00138 {
00139     static T* Copy(const T* originPtr)
00140     {
00141         T* clonedPtr = originPtr->Clone();
00142         
00143         // Make sure the Clone() function is correctly implemented (one can easily forget to override it in a derived class without
00144         // getting any compiler error or warning). The comparison shall not fail because of CV-qualifiers, so cast it.
00145         assert( detail::SameDynamicPointerType<T>(clonedPtr, originPtr) );
00146         
00147         // Return pointer to cloned instance
00148         return clonedPtr;
00149     }
00150     
00151     static void Destroy(T* pointer)
00152     {
00153         delete pointer;
00154     }
00155 };
00156 
00158 
00159 } // namespace thor
00160 
00161 #endif // THOR_COPIEDPTRPOLICIES_HPP