Currently CComPtr::operator= is implemented using a helper function AtlComPtrAssign() that has the following signature:
IUnknown* AtlComPtrAssign( IUnknown** pp, IUnknown* lp);
and has to be called like this:
T* operator=( const CComPtr<T>& lp) throw()
{
if(*this!=lp) {
return static_cast<T*>(AtlComPtrAssign((IUnknown**)&p, lp));
}
return *this;
}
which causes problems if I try to store a use CComPtr with T being a class implementing more than one COM interface – the conversion to IUnknown* becomes ambiguous and compilation fails.
My question is – what’s the need for using such helper function that has exactly these parameters? Why not do like this:
template<classT>
T* AtlComPtrAssign( T** pp, T* lp);
and call it for any reasonable T? What’s the need for this upcast to IUnknown* and then reverse downcast to T*?
IUnknowns there, there is always just one.AtlComPtrAssignis that in early days the function optionally resided in ATL.DLL unless choosing certain options one would prefer static link to ATL.I believe that with earlier versions of ATL you could use
CComPtrwith a class too. I remember using it and it was very convenient – you could have both automatic reference counting and raw class pointer (as opposed to interface pointer), but at some point such use was no longer available due to compiler errors and one would need a custom template class instead of standard CComPtr to achieve the same functionality.