|
// SmartPtr.h
//
// Defines a smart pointer class that does not depend on any ATL headers
#pragma once
///////////////////////////////////////////////////////////////////////
// Name: AreCOMObjectsEqual [template]
// Desc: Tests two COM pointers for equality.
///////////////////////////////////////////////////////////////////////
template <class T1, class T2>
bool AreComObjectsEqual(T1 *p1, T2 *p2)
{
bool bResult = false;
if (p1 == NULL && p2 == NULL)
{
// Both are NULL
bResult = true;
}
else if (p1 == NULL || p2 == NULL)
{
// One is NULL and one is not
bResult = false;
}
else
{
// Both are not NULL. Compare IUnknowns.
IUnknown *pUnk1 = NULL;
IUnknown *pUnk2 = NULL;
if (SUCCEEDED(p1->QueryInterface(IID_IUnknown, (void**)&pUnk1)))
{
if (SUCCEEDED(p2->QueryInterface(IID_IUnknown, (void**)&pUnk2)))
{
bResult = (pUnk1 == pUnk2);
pUnk2->Release();
}
pUnk1->Release();
}
}
return bResult;
}
// _NoAddRefOrRelease:
// This is a version of our COM interface that dis-allows AddRef
// and Release. All ref-counting should be done by the SmartPtr
// object, so we want to dis-allow calling AddRef or Release
// directly. The operator-> returns a _NoAddRefOrRelease pointer
// instead of returning the raw COM pointer. (This behavior is the
// same as ATL's CComPtr class.)
template <class T>
class _NoAddRefOrRelease : public T
{
private:
STDMETHOD_(ULONG, AddRef)() = 0;
STDMETHOD_(ULONG, Release)() = 0;
};
template <class T>
class SmartPtr
{
public:
// Ctor
SmartPtr() : m_ptr(NULL)
{
}
// Ctor
SmartPtr(T *ptr)
{
m_ptr = ptr;
if (m_ptr)
{
m_ptr->AddRef();
}
}
// Copy ctor
SmartPtr(const SmartPtr& sptr)
{
m_ptr = sptr.m_ptr;
if (m_ptr)
{
m_ptr->AddRef();
}
}
// Dtor
~SmartPtr()
{
if (m_ptr)
{
m_ptr->Release();
}
}
// Assignment
SmartPtr& operator=(const SmartPtr& sptr)
{
// Don't do anything if we are assigned to ourselves.
if (!AreComObjectsEqual(m_ptr, sptr.m_ptr))
{
if (m_ptr)
{
m_ptr->Release();
}
m_ptr = sptr.m_ptr;
if (m_ptr)
{
m_ptr->AddRef();
}
}
return *this;
}
// address-of operator
T** operator&()
{
return &m_ptr;
}
// dereference operator
_NoAddRefOrRelease<T>* operator->()
{
return (_NoAddRefOrRelease<T>*)m_ptr;
}
// coerce to underlying pointer type.
operator T*()
{
return m_ptr;
}
// Templated version of QueryInterface
template <class Q> // Q is another interface type
HRESULT QueryInterface(Q **ppQ)
{
return m_ptr->QueryInterface(__uuidof(Q), (void**)ppQ);
}
// safe Release() method
ULONG Release()
{
T *ptr = m_ptr;
ULONG result = 0;
if (ptr)
{
m_ptr = NULL;
result = ptr->Release();
}
return result;
}
// Attach to an existing interface (does not AddRef)
void Attach(T* p)
{
if (m_ptr)
{
m_ptr->Release();
}
m_ptr = p;
}
// Detach the interface (does not Release)
T* Detach()
{
T* p = m_ptr;
m_ptr = NULL;
return p;
}
// equality operator
bool operator==(T *ptr) const
{
return AreComObjectsEqual(m_ptr, ptr);
}
// inequality operator
bool operator!=(T *ptr) const
{
return !operator==(ptr);
}
private:
T *m_ptr;
};
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.