|
|
// This is a part of the Active Template Library.
// Copyright (C) 1995-1999 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
// VCUE_Collection.h
//
// This header contains code that simplifies or enhances use of ATL's collection
// and enumerator classes, ICollectionOnSTLImpl, IEnumOnSTLImpl, CComEnumOnSTL, CComEnumImpl, and CComEnum
//
//////////////////////////////////////////////////////////////////////
#if !defined(_COLLECTION_H___36A49828_B15B_11D2_BA63_00C04F8EC847___INCLUDED_)
#define _COLLECTION_H___36A49828_B15B_11D2_BA63_00C04F8EC847___INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include <AtlCom.h>
namespace VCUE {
// CGenericDataHolder is a class that stores data
// The lifetime of objects of this class is managed via the IUnknown interface
// which makes objects of this class suitable as a source of shared data
// Clients that need access to the data can keep a CGenericDataHolder object alive
// just by holding a COM reference on that object
// This class is used (by default) by ICollectionOnSTLCopyImpl::get__NewEnum to provide data
// to be shared between an enumerator and its clones.
template < class DataType, class ThreadModel = CComObjectThreadModel > class ATL_NO_VTABLE CGenericDataHolder : public IUnknown, public CComObjectRootEx< ThreadModel > { public: typedef CGenericDataHolder< DataType, ThreadModel > thisClass;
BEGIN_COM_MAP(thisClass) COM_INTERFACE_ENTRY(IUnknown) END_COM_MAP()
template < class SourceType > HRESULT Copy(const SourceType& c) { m_Data = c; return S_OK;
} // HRESULT Copy(const SourceType& c)
DataType m_Data;
}; // class ATL_NO_VTABLE CGenericDataHolder
// CreateSTLEnumerator wraps the necessary creation, initialization
// and error handling code for the the creation of a CComEnumOnSTL-style enumerator
// *** EXAMPLE : Using CreateSTLEnumerator to implement get__NewEnum ***
// typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
// _Copy<VARIANT>, std::vector<CComVariant> > VarVarEnum;
// std::vector<CComVariant> m_vec;
// STDMETHOD(get__NewEnum)(IUnknown** ppUnk)
// {
// return CreateSTLEnumerator<VarVarEnum>(ppUnk, this, m_vec);
// }
template <class EnumType, class CollType> HRESULT CreateSTLEnumerator(IUnknown** ppUnk, IUnknown* pUnkForRelease, CollType& collection) { if (ppUnk == NULL) return E_POINTER; *ppUnk = NULL;
CComObject<EnumType>* pEnum = NULL; HRESULT hr = CComObject<EnumType>::CreateInstance(&pEnum);
if (FAILED(hr)) return hr;
hr = pEnum->Init(pUnkForRelease, collection);
if (SUCCEEDED(hr)) hr = pEnum->QueryInterface(ppUnk);
if (FAILED(hr)) delete pEnum;
return hr;
} // HRESULT CreateSTLEnumerator(IUnknown** ppUnk, IUnknown* pUnkForRelease, CollType& collection)
// CreateEnumerator wraps the necessary creation, initialization
// and error handling code for the the creation of a CComEnum-style enumerator
template <class EnumType, class ElementType> HRESULT CreateEnumerator(IUnknown** ppUnk, ElementType* begin, ElementType* end, IUnknown* pUnk, CComEnumFlags flags) { if (ppUnk == NULL) return E_POINTER; *ppUnk = NULL;
CComObject<EnumType>* pEnum = NULL; HRESULT hr = CComObject<EnumType>::CreateInstance(&pEnum);
if (FAILED(hr)) return hr;
hr = pEnum->Init(begin, end, pUnk, flags);
if (SUCCEEDED(hr)) hr = pEnum->QueryInterface(ppUnk);
if (FAILED(hr)) delete pEnum;
return hr;
} // CreateEnumerator
// ICollectionOnSTLCopyImpl derives from ICollectionOnSTLImpl and overrides get__NewEnum
// The new implementation provides each enumerator with its own copy of the collection data.
// (Note that this only applies to enumerators returned directly by get__NewEnum.
// Cloned enumerators use their parent's data as before.
// This is OK because the enumerator never changes the data)
// Use this class when:
// The collection can change while there are outstanding enumerators
// And You don't want to invalidate those enumerators when that happens
// And You are sure that the performance hit is worth it
// And You are sure that the way items are copied between containers works correctly
// (You can adjust this by passing a different class as the Holder parameter)
// Mostly you can use this class in exactly the same
// way that you would use ICollectionOnSTLImpl.
template <class T, class CollType, class ItemType, class CopyItem, class EnumType, class Holder = CGenericDataHolder< CollType > > class ICollectionOnSTLCopyImpl : public ICollectionOnSTLImpl<T, CollType, ItemType, CopyItem, EnumType> { public : STDMETHOD(get__NewEnum)(IUnknown** ppUnk) { typedef CComObject< Holder > HolderObject; HolderObject* p = NULL; HRESULT hr = HolderObject::CreateInstance(&p); if (FAILED(hr)) return hr;
hr = p->Copy(m_coll); if (FAILED(hr)) return hr;
return CreateSTLEnumerator<EnumType>(ppUnk, p, p->m_Data); } // STDMETHOD(get__NewEnum)(IUnknown** ppUnk)
}; // class ICollectionOnSTLCopyImpl
}; // namespace VCUE
#endif // !defined(_COLLECTION_H___36A49828_B15B_11D2_BA63_00C04F8EC847___INCLUDED_)
|