CComPtr pass by reference issue with VC 2005 compiler

  • Thread starter Thread starter Stuart Carnie
  • Start date Start date
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
 
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.
 
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
 
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

}
 
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

}
 
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

}
 
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

}
 
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
 
Back
Top