implement HiddenPtr smart pointer type; use it for Steps. This avoids having

to write a whole copy constructor for a class just to hide a couple types from
the header.
This commit is contained in:
Glenn Maynard
2005-07-03 03:05:54 +00:00
parent b0935c1111
commit f2a418d79d
4 changed files with 102 additions and 2 deletions
+2
View File
@@ -9,6 +9,8 @@
#include "RageUtil.h"
#include "RageLog.h"
#include "RageUtil_AutoPtr.h"
REGISTER_CLASS_TRAITS( NoteData, new NoteData(*pCopy) )
NoteData::NoteData()
{
+97
View File
@@ -96,6 +96,103 @@ inline void swap( AutoPtrCopyOnWrite<T> &a, AutoPtrCopyOnWrite<T> &b )
a.Swap(b);
}
/*
* This smart pointer template is used to safely hide implementations from
* headers, to reduce dependencies. This is the same as declaring a pointer
* to a class, and allocating/deallocating it in the implementation: only
* the implementation needs to include that class. This makes copying
* and deletion automatic, so you don't need to include a copy ctor or
* remember to delete it.
*
* There's one subtlety: in order to copy or delete an object, we need its
* definition. This is intended to avoid pulling in the definition. So,
* we use a traits class to hide it. Use REGISTER_CLASS_TRAITS for each
* class used with this template.
*
* Concepts from http://www.gotw.ca/gotw/062.htm.
*/
template<class T>
struct HiddenPtrTraits
{
static T *Copy( const T *pCopy );
static void Delete( T *p );
};
#define REGISTER_CLASS_TRAITS(T, CopyExpr) \
template<> T *HiddenPtrTraits<T>::Copy( const T *pCopy ) { return CopyExpr; } \
template<> void HiddenPtrTraits<T>::Delete( T *p ) { delete p; }
template<class T>
class HiddenPtr
{
public:
const T& operator*() const { return *m_pPtr; }
const T* operator->() const { return m_pPtr; }
T& operator*() { return *m_pPtr; }
T* operator->() { return m_pPtr; }
explicit HiddenPtr( T *p = NULL )
{
m_pPtr = p;
}
HiddenPtr( const HiddenPtr<T> &cpy )
{
if( cpy.m_pPtr == NULL )
m_pPtr = NULL;
else
m_pPtr = HiddenPtrTraits<T>::Copy( cpy.m_pPtr );
}
template<class U>
HiddenPtr( const HiddenPtr<U> &cpy )
{
if( cpy.m_pPtr == NULL )
m_pPtr = NULL;
else
m_pPtr = HiddenPtrTraits<U>::Copy( cpy.m_pPtr );
}
~HiddenPtr()
{
HiddenPtrTraits<T>::Delete( m_pPtr );
}
void Swap( HiddenPtr<T> &rhs ) { swap( m_pPtr, rhs.m_pPtr ); }
HiddenPtr<T> &operator=( T *p )
{
HiddenPtr<T> t( p );
Swap( t );
return *this;
}
HiddenPtr<T> &operator=( const HiddenPtr &cpy )
{
HiddenPtr<T> t( cpy );
Swap( t );
return *this;
}
template<class U>
HiddenPtr<T> &operator=( const HiddenPtr<U> &cpy )
{
HiddenPtr<T> t( cpy );
Swap( t );
return *this;
}
private:
T *m_pPtr;
template<class U>
friend class HiddenPtr;
};
template<class T>
inline void swap( HiddenPtr<T> &a, HiddenPtr<T> &b )
{
a.Swap(b);
}
#endif
/*
+1 -1
View File
@@ -16,6 +16,7 @@
#include "global.h"
#include "Steps.h"
#include "StepsUtil.h"
#include "song.h"
#include "RageUtil.h"
#include "RageLog.h"
#include "NoteData.h"
@@ -41,7 +42,6 @@ Steps::Steps()
Steps::~Steps()
{
delete m_pNoteData;
}
void Steps::SetNoteData( const NoteData& noteDataNew )
+2 -1
View File
@@ -8,6 +8,7 @@
#include "Grade.h"
#include "RadarValues.h"
#include "Difficulty.h"
#include "RageUtil_AutoPtr.h"
class Profile;
class NoteData;
struct lua_State;
@@ -76,7 +77,7 @@ protected:
/* We can have one or both of these; if we have both, they're always identical.
* Call Compress() to force us to only have m_sNoteDataCompressed; otherwise, creation of
* these is transparent. */
mutable NoteData *m_pNoteData;
mutable HiddenPtr<NoteData> m_pNoteData;
mutable bool m_bNoteDataIsFilled;
mutable CString m_sNoteDataCompressed;