Problem:
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.
Attempted solutions:
vector<ATL::CComPtr<IWICColorContext>>
failed due to type mismatch,as noted in the comments this has other issues asIt seems that this was fixed in C++11 and was included in the STL in VC2010CComPtr
overloadsoperator &
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.
Unattempted solutions:
- Custom data structure - this is likely what I'll have to do if there is not a more elegant solution, but at least it would allow me to take advantage of destruction semantics properly.
- Attach a
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 asizeof
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: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 theGetColorContexts
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 thevector<CComPtr<IWICColorContext>>
this temporaryvector
does not increment the ref count and allows me to maintain exception safety.