VC++: Cast operator not used?

A

A. W. Dunstan

I'm porting some code to Visual C++ and have run into a problem - the
compiler won't use a user-written cast operator.

The code uses an envelope-letter approach to passing (potentially)
large pieces of data around, and requires that certain methods return
an Envelope with a specific kind of Letter as it's content. I have a
cast operator that converts from what I've got to what should be
returned, but it seems that the compiler only looks at constructors
for the return type.

The code works fine with the SGI MIPSPRO and Linux GCC compilers.
With MS Visual C++ .NET (v. 7.1.3008) it says:

CDP3x3LinearTransform.c++(196): error C2668: 'DataPacket::DataPacket' :
ambiguous call to overloaded function
DataPacket.h(53): could be 'DataPacket::DataPacket(Letter &)'
DataPacket.h(52): or 'DataPacket::DataPacket(const DataPacket &)'
DataPacket.h(51): or 'DataPacket::DataPacket(const Envelope<T> &)'


where the offending line in CDP3x3LinearTransform.c++ looks like this:

DataPacket
CDP3x3LinearTransform::Output() const {
ChannelDataPacket result;
//... compute result here...
return result; // line 196
}

In this case I've got a ChannelDataPacket and need to return a
DataPacket. ChannelDataPacket is NOT derived from DataPacket (even
tho' you'd expect that, given their names), but they ARE related.
ChannelDataPacket DOES have a conversion operator to convert itself to
a DataPacket, however (see below). I've found two work-arounds:

#1: Call the cast operator explicitly:

return result.operator omiDataPacket();

#2: Explicitly cause the cast operator to be called by adding code:

DataPacket dp;
dp = result;
return dp;

I have two objections to both of these workarounds: a) If it won't
work as written, what's the point in having a cast operator? and b)
This is done in about 150 different places in 70 different classes.
That's just way too much typing for someone as lazy as I am.


Questions:

- Is this a known problem with VC++? I've looked in the MS knowledge
base and found nothing, but I might be looking for the wrong thing.

- Is there some way of getting the VC++ compiler to notice (and use)
the cast operator without having to inflict a MS-specific kludge all
over the code?


Thanks!


Code:

//---------------------------------------------
// The Envelope to be wrapped around a Letter.
//---------------------------------------------
class EnvelopeBase
{
public:
virtual ~EnvelopeBase();
EnvelopeBase();
EnvelopeBase(Letter::WriteAndCopyModeType wcm);
EnvelopeBase(const EnvelopeBase& from);
EnvelopeBase& operator=(const EnvelopeBase& rhs);
};


template < class T >
class Envelope : public EnvelopeBase
{
public:
virtual ~Envelope();
Envelope();
Envelope( const Envelope& );
Envelope( Letter& letter );

Envelope& operator=( const Envelope& );
T* operator->();
const T* operator->() const;
};



//---------------------------------------------
// Letter - What gets put inside an Envelope.
//---------------------------------------------
class Letter
{
public:
enum WriteAndCopyModeType { ValueImmediate, ValueDelayed,
Pointer };
enum ExemplarType { exemplar };
virtual ~Letter();
Letter();
Letter( const String& );
Letter( const Letter& );

protected:
friend class Envelope< Letter >;
};


//---------------------------------------------
// DataPacketLetter - the data we're interested in.
//---------------------------------------------
class DataPacketLetter : public Letter
{
public:
virtual ~DataPacketLetter();
DataPacketLetter();
DataPacketLetter( const DataPacketLetter& );
DataPacketLetter( ExemplarType );
DataPacketLetter( const String& );

protected:
DataPacketLetter( const String&, ExemplarType );
};


//---------------------------------------------
// DataPacket - the data we're interested in, wrapped in an Envelope.
//---------------------------------------------
class DataPacket : public Envelope< DataPacketLetter >
{
public:
virtual ~DataPacket();
DataPacket();
DataPacket( const Envelope< DataPacketLetter >& from );
DataPacket( const DataPacket& from );
DataPacket( Letter& letter );
DataPacket& operator=( const DataPacket& rhs );
operator DataPacketLetter&() const;
};




//---------------------------------------------
// ChannelDataPacket(Letter) - the data we're interested in, wrapped &
unwrapped.
//---------------------------------------------
class ChannelDataPacketLetter : public DataPacketLetter
{
public:
virtual ~ChannelDataPacketLetter();
ChannelDataPacketLetter();
ChannelDataPacketLetter( int theInitialSize );
ChannelDataPacketLetter( const ChannelDataPacketLetter& );
ChannelDataPacketLetter( ExemplarType );
ChannelDataPacketLetter( const String& );
};


class ChannelDataPacket : public Envelope< ChannelDataPacketLetter >
{
public:
virtual ~ChannelDataPacket();
ChannelDataPacket();
ChannelDataPacket( float theValue );
ChannelDataPacket( const ChannelDataPacket& theOriginal );
ChannelDataPacket( Letter& letter );
ChannelDataPacket& operator=( const ChannelDataPacket& theRhs );
ChannelDataPacket& operator=( const float& theRhs );
operator ChannelDataPacketLetter&() const;
operator DataPacket() const;
operator float() const;
};
 

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top