ATL - Compiler error C2594 (ambiguous conversions from/to IUnknown) when assigning to coclass smart pointer (CComPtr) - multiple inheritance of IUnknown

I have a coclass CMyClass with the inheritance list as shown below:

   class ATL_NO_VTABLE CMyClass :
      public CComObjectRootEx<CComObjectThreadModel>,
      public CComCoClass<CMyClass, &CLSID_MyClass>,
      public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_MYLib>,
      public ISupportErrorInfo,
      public IConnectionPointContainerImpl<CMyClass>
   {
      DECLARE_GET_CONTROLLING_UNKNOWN()
      DECLARE_PROTECT_FINAL_CONSTRUCT()

      BEGIN_COM_MAP(CMyClass)
         COM_INTERFACE_ENTRY(IMyClass)
         COM_INTERFACE_ENTRY(IDispatch)
         COM_INTERFACE_ENTRY(ISupportErrorInfo)
         COM_INTERFACE_ENTRY(IConnectionPointContainer)
      END_COM_MAP()
      BEGIN_CONNECTION_POINT_MAP(CMyClass)
      END_CONNECTION_POINT_MAP()

      // ... Plus all other stuff here
   }


However, I'm getting a problem with the following code:

   CComPtr<CMyClass> pmyClass1;
   CComPtr<CMyClass> pmyClass2;
   pmyClass1 = pmyClass2;


I get the following compiler errors:

   atlbase.h(483) : error C2594: 'argument' : ambiguous conversions from 'class CMyClass *const ' to 'struct IUnknown *'
        atlbase.h(482) : while compiling class-template member function 'class CMyClass *__thiscall ATL::CComPtr<class CMyClass>::operator =(const class ATL::CComPtr<class CMyClass> &)'

   atlbase.h(483) : error C2594: 'type cast' : ambiguous conversions from 'struct IUnknown *' to 'class CMyClass *'
        atlbase.h(482) : while compiling class-template member function 'class CMyClass *__thiscall ATL::CComPtr<class CMyClass>::operator =(const class ATL::CComPtr<class CMyClass> &)'


Any idea how to resolve this error? I know this is obviously due to IUnknown being on multiple inheritance branches. Do I need to use COM_INTERFACE_ENTRY2 macro or cast operators perhaps? Only restriction I have is I MUST template my smart pointers to the coclasses rather than the interfaces.
XtreemAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dariusz DziaraProgrammerCommented:
Parameter for CComPtr template should be COM interface (inherits from IUnknown).
For example you should use:
CComPtr<IMyClass> pIMyClass1;

The way of object creation from C++ class is described in MSDN and depends on ATL version.
XtreemAuthor Commented:
Please see the last sentence of my Question. I MUST template my smart pointers to the coclasses rather than the interfaces. Reason for this is to be able to access __cdecl functions on the COM object.  And I am led to believe it is quite ok to use CComPtr with coclasses (not just interfaces) as CComPtr is for any COM component and coclasses are COM components.
Dariusz DziaraProgrammerCommented:
MSDN states for CComPtr:
"T - A COM interface specifying the type of pointer stored"

CComPtr implements for example QueryInterface() method which is simply implemented by calling wrapped interface QueryInterface() method.

"atlbase.h(483) : error C2594: 'argument' : ambiguous conversions from 'class CMyClass *const ' to 'struct IUnknown *' "

It means that CMyClass inherits more than one time IUnknown interface because
IMyClass, ISupportErrorInfo,  IConnectionPointContainerImpl all inherits from IUnknown.

To access __cdecl functions on the COM object you could simply cast interface type onto CMyClass * but in some cases it can be dangerous (when some ATL debugging macroes are used you will not have directly pointer to object but pointer to some proxy object).
I think that better idea is to implement some additional (auxiliary) interface that simply wraps your "__cdecl functions".




PMI ACP® Project Management

Prepare for the PMI Agile Certified Practitioner (PMI-ACP)® exam, which formally recognizes your knowledge of agile principles and your skill with agile techniques.

XtreemAuthor Commented:
Ok, the restriction I stated remains true, so whether or not it is better to use interface rather than coclass, I cannot change this (this is a work situation). The problem at hand is, as you rightly said, that there is multiple inheritance of IUnknown, which I stated in the Question.

This Question discusses a similar problem, but I don't know if the solution lies therein:
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21451062.html

This is why I suggested the solution may lie with the COM_INTERFACE_ENTRY2 macro or cast operators...
Dariusz DziaraProgrammerCommented:
"Ok, the restriction I stated remains true" ?
I do not understand it clearly. Do you
1) need to declare
CComPtr<CMyClass> pmyClass1;
what I am convinced is incorrect 'cause CMyClass is not an interface ?
2) need to call __cdecl functions
in this case you can declare
CComPtr<IMyClass> pIMyClass1;
and then cast it
CMyClass *pMyClass = (CMyClass *)(IMyClass *)pIMyClass1;
However it won't work if you enable reference count debugging by defining
_ATL_DEBUG_INTERFACES
XtreemAuthor Commented:
The reason is 2) - I need to call __cdecl functions. But the reason I said I am led to believe it is quite ok to use CComPtr with coclasses (not just interfaces) is due to the responses to a previous recent Question I asked:
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21771199.html

I would like to put this to my team at work as it was decided that we should use coclass smart pointers (as opposed to interface smart pointers) in order to access __cdecl functions. I just tried your double casting of the interface smart pointer to a coclass pointer in our code and it worked. But is there a good reason we should do this instead of using coclass smart pointers (so I can put this to my team)?
Dariusz DziaraProgrammerCommented:
Maybe the reason is to avoid such problems when something was not designed (as I guess) for some purpose :)
The problem lies exactly here:
pmyClass1 = pmyClass2;
it is in operator=() which calls AtlComPtrAssign(IUnknown **pp, IUnknown *p)
Anyway, honestly if there's solution to this problem I simply don't know it, sorry.
I even tried COM_INTERFACE_ENTRY2(IUnknown, ISomeInterface) but it didn't helped. I think it is used rather in QueryInterface() implementation to avoid such ambiguity.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
XtreemAuthor Commented:
mrblue's Answers didn't resolve the problem, so please either close and refund or (preferably) leave the Question open a while longer to see if anyone else comes back with a solution.

Thanks.
VenabiliCommented:
Noone will help you further if you just ignore an expert comment... One simple "Does not work" would be enough
XtreemAuthor Commented:
I replied to mrblue last on 04/12/2006 12:00PM BST with the reasoning behind why his possible Answer(s) wouldn't solve my particular problem. mrblue's latest comment on 04/12/2006 07:25PM BST, if you read it, is not another solution, but rather a clarification of why I have the problem in the first place.

To quote mrblue, "honestly if there's solution to this problem I simply don't know it, sorry" and "I even tried COM_INTERFACE_ENTRY2(IUnknown, ISomeInterface) but it didn't helped".

So saying "Does not work" to this would make no sense as it wasn't a solution. If you mean to say I must reply to all expert comments, regardless of what they're commenting about, then I apologise.
VenabiliCommented:
I had to type all that I thought...
I do not know of a solution either. In fact I do not really believe that there is a solution and the last comment is a pretty good explanation why it is like this- that is why I recommend award :)

What I was saying is that it is better if you can reply to all experts - this way the next person that opens the question will see that you care. :)
XtreemAuthor Commented:
Ok, then I'll let this go through Cleanup using your recommendation.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.