In COM you occasionally find functions with signatures like this:
HRESULT STDMETHODCALLTYPE GetColorContexts(
UINT cCount,
IWICColorContext **ppIColorContexts,
UINT *pcActualCount)
The problem this presents for me is that ppIColorContexts
must be an initialized array of IWICColorContext *
. I have tried referencing the first element of a Vector
of ATL::CComPtr<IWICColorContext>
with no such luck it won't trigger the ()
operator so it complains about a type mismatch.
vector<ATL::CComPtr<IWICColorContext>>
failed due to type mismatch, CComPtr
overloads operator &
which breaks STL containers.BOOST_SCOPE_EXIT_ALL
works but still means I'm manually managing the lifetime of the COM objects which is something I'd like to get away from.CComPtr
after this call - I dislike this solution because it leaves me with a period of execution where the resource may not get released if something goes wrong.std::unique_ptr<IWICColorContext[]>
with a custom deleter - I have yet to fully explore this possibility but it would ensure that the COM objects would always get released.Ultimately the solution was described by igor tandetnik in the comments above:
Basically in VC2010+ ATL::CComPtr
has a sizeof
that is the same as the pointer they represent (e.g. sizeof(ATL::CComPtr<IWICColorContext>) == sizeof(IWICColorContext*)
), as best I can tell this is because they have no virtual functions and thus need no vTable. This is however highly dangerous as it's relying on a compiler implementation detail. Thus the following works:
std::vector<ATL::CComPtr<IWICColorContext> > > vec(5);
// CComPtrs are created and initialized here
GetColorContexts(vec.size(), &vec[0].m_T, ...);
Mark brought up a very good point that the solution above was completely dependent on compiler implementation which is dangerous. However the solution of only attaching ATL::CComPtr
after the GetColorContexts
call was not palattable either as it would not have been exception safe.
Ultimately my solution (tested this morning) is to create a vector<IWICColorContext*>
temporarily from the vector<CComPtr<IWICColorContext>>
this temporary vector
does not increment the ref count and allows me to maintain exception safety.