// 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 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, std::vector > VarVarEnum; // std::vector m_vec; // STDMETHOD(get__NewEnum)(IUnknown** ppUnk) // { // return CreateSTLEnumerator(ppUnk, this, m_vec); // } template HRESULT CreateSTLEnumerator(IUnknown** ppUnk, IUnknown* pUnkForRelease, CollType& collection) { if (ppUnk == NULL) return E_POINTER; *ppUnk = NULL; CComObject* pEnum = NULL; HRESULT hr = CComObject::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 HRESULT CreateEnumerator(IUnknown** ppUnk, ElementType* begin, ElementType* end, IUnknown* pUnk, CComEnumFlags flags) { if (ppUnk == NULL) return E_POINTER; *ppUnk = NULL; CComObject* pEnum = NULL; HRESULT hr = CComObject::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 ICollectionOnSTLCopyImpl : public ICollectionOnSTLImpl { 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(ppUnk, p, p->m_Data); } // STDMETHOD(get__NewEnum)(IUnknown** ppUnk) }; // class ICollectionOnSTLCopyImpl }; // namespace VCUE #endif // !defined(_COLLECTION_H___36A49828_B15B_11D2_BA63_00C04F8EC847___INCLUDED_)