CComPtr pass by reference issue with VC 2005 compiler

S

Stuart Carnie

Due to the tightening of the VC++ compiler in 2005, I have run into a
compiler error (from code that previously worked in 2003) using a
CComPtr<ITypeLib> as an element of a std::list, as follows
std::list<CComPtr<ITypeLib> >. I understand the problem, so am looking
for the correct solution to my problem.

On the line that attempts to call push_back, I receive "error C2664:
'std::allocator<_Ty>::construct' : cannot convert parameter 1 from
'ITypeLib **' to 'ATL::CComPtr<T> *' c:\program files\microsoft visual
studio 8\vc\include\list 1163"

e.g.

std::list<CComPtr<ITypeLib> > typeLibs;

CComPtr<ITypeLib> spTypeLib;

... some code the creates an instance of spTypeLib

list.push_back(spTypeLib); // fails here with the C2664 error.

The problem is the push_back function takes a by reference parameter of
type CComPtr<ITypeLib>, however the CComPtr class overrides operator&,
returning a value of type ITypeLib**.

I want to use the CComPtr, for the benefits of the RAII pattern, and it
simplifies my production code significantly in this set of routines.

My question is "What is the correct way to handle this situation, and
avoid the overloaded operator& issue?"

Cheers,

Stuart
 
S

Stuart Carnie

Stuart said:
Due to the tightening of the VC++ compiler in 2005, I have run into a
compiler error (from code that previously worked in 2003) using a
CComPtr<ITypeLib> as an element of a std::list, as follows
std::list<CComPtr<ITypeLib> >. I understand the problem, so am looking
for the correct solution to my problem.

On the line that attempts to call push_back, I receive "error C2664:
'std::allocator<_Ty>::construct' : cannot convert parameter 1 from
'ITypeLib **' to 'ATL::CComPtr<T> *' c:\program files\microsoft
visual studio 8\vc\include\list 1163"

e.g.

std::list<CComPtr<ITypeLib> > typeLibs;

CComPtr<ITypeLib> spTypeLib;

.. some code the creates an instance of spTypeLib

list.push_back(spTypeLib); // fails here with the C2664 error.

The problem is the push_back function takes a by reference parameter of
type CComPtr<ITypeLib>, however the CComPtr class overrides operator&,
returning a value of type ITypeLib**.

I want to use the CComPtr, for the benefits of the RAII pattern, and it
simplifies my production code significantly in this set of routines.

My question is "What is the correct way to handle this situation, and
avoid the overloaded operator& issue?"

Cheers,

Stuart


Just want to add, that

typeLibs.push_back(reinterpret_cast<CComPtr<ITypeLib> >(spTypeLib));

does not work, receive the following (suspicious) error

"error C2440: 'reinterpret_cast' : cannot convert from
'ATL::CComPtr<T>' to 'ATL::CComPtr<T>'
d:\sourcecode\slx_scorpion\projects\oledb_provider\commonsys\cdynamicobject.cpp
535"

Notice it says cannot convert from same type.
 
C

Carl Daniel [VC++ MVP]

Stuart Carnie said:
Due to the tightening of the VC++ compiler in 2005, I have run into a
compiler error (from code that previously worked in 2003) using a
CComPtr<ITypeLib> as an element of a std::list, as follows
std::list<CComPtr<ITypeLib> >. I understand the problem, so am looking
for the correct solution to my problem.

On the line that attempts to call push_back, I receive "error C2664:
'std::allocator<_Ty>::construct' : cannot convert parameter 1 from
'ITypeLib **' to 'ATL::CComPtr<T> *' c:\program files\microsoft visual
studio 8\vc\include\list 1163"

e.g.

std::list<CComPtr<ITypeLib> > typeLibs;

CComPtr<ITypeLib> spTypeLib;

.. some code the creates an instance of spTypeLib

list.push_back(spTypeLib); // fails here with the C2664 error.

The problem is the push_back function takes a by reference parameter of
type CComPtr<ITypeLib>, however the CComPtr class overrides operator&,
returning a value of type ITypeLib**.

I want to use the CComPtr, for the benefits of the RAII pattern, and it
simplifies my production code significantly in this set of routines.

My question is "What is the correct way to handle this situation, and
avoid the overloaded operator& issue?"

The best solution is to avoid classes that overload operator & - they're
inherently incompatible with the standard library containers (despite the
fact that some combinations may actually work).

The only general soution that I know of is to wrap the type with another
type that forwards the entire public interface except for operator &. With
a smartpoint type, that'll no doubt cause some other problems somewhere
since it'll probably add a conversion to various sequences, which will in
turn make some implicit conversions no longer work (since they'll now
require two user defined conversions instead of one).

ATL actually supplies a wrapper for just this purpose: CAdapt<T>

-cd
 
S

Stuart Carnie

Carl said:
The best solution is to avoid classes that overload operator & - they're
inherently incompatible with the standard library containers (despite the
fact that some combinations may actually work).

The only general soution that I know of is to wrap the type with another
type that forwards the entire public interface except for operator &. With
a smartpoint type, that'll no doubt cause some other problems somewhere
since it'll probably add a conversion to various sequences, which will in
turn make some implicit conversions no longer work (since they'll now
require two user defined conversions instead of one).

ATL actually supplies a wrapper for just this purpose: CAdapt<T>

-cd

Thanks for that..

Out of interest, I had to see what had changed, and it turns out to be
fairly simple:

In <list>, this method has changed between 2003 and 2005

_Nodeptr _Buynode(_Nodeptr _Next,
_Nodeptr _Prev, const _Ty& _Val)
{ // allocate a node and set links and value

// surrounding code removed for clarity

// this line causes the compilation issue.
// 2003 used the new operator to construct the object
this->_Alval.construct(&_Myval(_Pnode), _Val);

// code removed for clarity

}
 
S

Stuart Carnie

Carl said:
The best solution is to avoid classes that overload operator & - they're
inherently incompatible with the standard library containers (despite the
fact that some combinations may actually work).

The only general soution that I know of is to wrap the type with another
type that forwards the entire public interface except for operator &. With
a smartpoint type, that'll no doubt cause some other problems somewhere
since it'll probably add a conversion to various sequences, which will in
turn make some implicit conversions no longer work (since they'll now
require two user defined conversions instead of one).

ATL actually supplies a wrapper for just this purpose: CAdapt<T>

-cd

Thanks for that..

Out of interest, I had to see what had changed, and it turns out to be
fairly simple:

In <list>, this method has changed between 2003 and 2005

_Nodeptr _Buynode(_Nodeptr _Next,
_Nodeptr _Prev, const _Ty& _Val)
{ // allocate a node and set links and value

// surrounding code removed for clarity

// this line causes the compilation issue.
// 2003 used the new operator to construct the object
this->_Alval.construct(&_Myval(_Pnode), _Val);

// code removed for clarity

}
 
S

Stuart Carnie

Carl said:
The best solution is to avoid classes that overload operator & - they're
inherently incompatible with the standard library containers (despite the
fact that some combinations may actually work).

The only general soution that I know of is to wrap the type with another
type that forwards the entire public interface except for operator &. With
a smartpoint type, that'll no doubt cause some other problems somewhere
since it'll probably add a conversion to various sequences, which will in
turn make some implicit conversions no longer work (since they'll now
require two user defined conversions instead of one).

ATL actually supplies a wrapper for just this purpose: CAdapt<T>

-cd

Thanks for that..

Out of interest, I had to see what had changed, and it turns out to be
fairly simple:

In <list>, this method has changed between 2003 and 2005

_Nodeptr _Buynode(_Nodeptr _Next,
_Nodeptr _Prev, const _Ty& _Val)
{ // allocate a node and set links and value

// surrounding code removed for clarity

// this line causes the compilation issue.
// 2003 used the new operator to construct the object
this->_Alval.construct(&_Myval(_Pnode), _Val);

// code removed for clarity

}
 
S

Stuart Carnie

Carl said:
The best solution is to avoid classes that overload operator & - they're
inherently incompatible with the standard library containers (despite the
fact that some combinations may actually work).

The only general soution that I know of is to wrap the type with another
type that forwards the entire public interface except for operator &. With
a smartpoint type, that'll no doubt cause some other problems somewhere
since it'll probably add a conversion to various sequences, which will in
turn make some implicit conversions no longer work (since they'll now
require two user defined conversions instead of one).

ATL actually supplies a wrapper for just this purpose: CAdapt<T>

-cd

Thanks for that..

Out of interest, I had to see what had changed, and it turns out to be
fairly simple:

In <list>, this method has changed between 2003 and 2005

_Nodeptr _Buynode(_Nodeptr _Next,
_Nodeptr _Prev, const _Ty& _Val)
{ // allocate a node and set links and value

// surrounding code removed for clarity

// this line causes the compilation issue.
// 2003 used the new operator to construct the object
this->_Alval.construct(&_Myval(_Pnode), _Val);

// code removed for clarity

}
 
B

Brian Muth

My question is "What is the correct way to handle this situation, and
avoid the overloaded operator& issue?"

Use:

std::list<CComPtr<CAdapt <ITypeLib> > > typeLibs;

Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top