Bromeon
SmartPtr/OwnershipPolicies.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_OWNERSHIPPOLICIES_HPP
00030 #define THOR_OWNERSHIPPOLICIES_HPP
00031 
00032 #include <Thor/Config.hpp>
00033 
00034 #include THOR_TR1_HEADER(type_traits)
00035 #include <typeinfo>
00036 #include <cassert>
00037 
00038 
00039 namespace thor
00040 {
00041 namespace detail
00042 {
00043 
00044     // Suppresses warnings at some compilers because the variable seems to be unused (although it is needed as typeid operand)
00045     inline void SuppressUnusedWarning(const void*)
00046     {
00047     }
00048     
00049     // Returns true when the dynamic types of *lhs and *rhs are equal
00050     template <typename T>
00051     bool SameDynamicPointerType(const T* lhs, const T* rhs)
00052     {
00053         SuppressUnusedWarning(lhs);
00054         SuppressUnusedWarning(rhs);
00055     
00056         return typeid(*lhs) == typeid(*rhs);
00057     }
00058     
00059     // Returns true when the dynamic types of Lhs and *rhs are equal
00060     template <typename Lhs>
00061     bool SameDynamicPointerType(const Lhs* rhs)
00062     {
00063         SuppressUnusedWarning(rhs);
00064             
00065         return typeid(Lhs) == typeid(*rhs);
00066     }
00067     
00068 } // namespace detail
00069 
00070 // ---------------------------------------------------------------------------------------------------------------------------
00071 
00072 
00075 
00076 
00081 template <typename T>
00082 struct NoCopy
00083 {
00084     static void Destroy(T* pointer)
00085     {
00086         // Check if it's safe to delete pointer and if we don't slice a base object.
00087         // Slicing non-polymorphic classes is still possible since RTTI doesn't work for them.
00088         assert( !pointer || detail::SameDynamicPointerType<T>(pointer) || std::tr1::has_virtual_destructor<T>::value );
00089         
00090         delete pointer;
00091     }
00092 };
00093 
00098 template <typename T>
00099 struct StaticCopy
00100 {
00101     static T* Copy(const T* originPtr)
00102     {
00103         T* copiedPtr = new T(*originPtr);
00104         
00105         // Prevent slicing
00106         assert( detail::SameDynamicPointerType<T>(copiedPtr, originPtr) );
00107         
00108         return copiedPtr;
00109     }
00110     
00111     static void Destroy(T* pointer)
00112     {
00113         // Check if it's safe to delete pointer and if we don't slice a base object
00114         assert( !pointer || detail::SameDynamicPointerType<T>(pointer) );
00115         
00116         delete pointer;
00117     }
00118 };
00119 
00125 template <typename T>
00126 struct DynamicCopy
00127 {
00128     template <class DynamicType> 
00129     static T* Copy(const DynamicType* originPtr)
00130     {
00131         T* copiedPtr = new DynamicType(*originPtr);
00132         
00133         // Make sure we called the actual dynamic type's copy constructor and prevent slicing.
00134         // In case this assertion fails, you didn't pass a pointer to the object's actual type at SmartPtr(U*) or Reset(U*).
00135         // If U is not polymorphic (which is allowed), typeid can't access the dynamic types, therefore it only compares the static
00136         // types, which are of course equal. In this case, the assertion is useless, but not problematic.
00137         // Ignore const-qualification for comparison
00138         assert( detail::SameDynamicPointerType<T>(copiedPtr, originPtr) );
00139         
00140         // Return pointer to deeply copied instance
00141         return copiedPtr;
00142     }
00143     
00144     template <class DynamicType> 
00145     static void Destroy(DynamicType* pointer)
00146     {   
00147         // Check if it's safe to delete pointer and if we don't slice a base object
00148         assert( !pointer || detail::SameDynamicPointerType<DynamicType>(pointer) );
00149         
00150         delete pointer;
00151     }
00152 };
00153 
00157 template <typename T>
00158 struct VirtualClone
00159 {
00160     static T* Copy(const T* originPtr)
00161     {
00162         T* clonedPtr = originPtr->Clone();
00163         
00164         // Make sure the Clone() function is correctly implemented (one can easily forget to override it in a derived class without
00165         // getting any compiler error or warning). The comparison shall not fail because of CV-qualifiers, so cast it.
00166         assert( detail::SameDynamicPointerType<T>(clonedPtr, originPtr) );
00167         
00168         // Return pointer to cloned instance
00169         return clonedPtr;
00170     }
00171     
00172     static void Destroy(T* pointer)
00173     {
00174         delete pointer;
00175     }
00176 };
00177 
00179 
00180 } // namespace thor
00181 
00182 #endif // THOR_OWNERSHIPPOLICIES_HPP