c4927 - illegal conversion.... why?

S

Steve Richter

here is a warning I am getting in a C++ .NET compile:

c:\SrNet\jury\JuryTest.cpp(55) : warning C4927: illegal conversion;
more than one user-defined conversion has been implicitly applied
while calling the constructor 'MyString::MyString(const
wchar_t *)'
c:\SrNet\jury\JuryTest.h(21) : see declaration of
'MyString::MyString'

The class "StringData" uses a, whatever you call it, operator const
whar_t*( ) to represent itself to other classes as a "const whar_t*".
A 2nd class, "MyString" has a constructor that accepts a "const
wchar_t*" when it is instantiated. Its a marriage made in code
heaven.

The classes are below, here is a function that produces the warning.

MyString TestFunc2( )
{
StringData data ;
MyString sData ;
sData = L"abc" ;
data = sData ; // no warnings when
sData = data ; // assigning either way.
return data ; // get the c4927 warning here. wtf?
}

I dont understand the warning. Esp the wording "illegal conversion".
I thought that C++ is all about how a class can be
assigned/converted/casted into another class?

Great NG,

Steve Richter


// ------------------------ MyString -------------------------------
class MyString : public std::basic_string<wchar_t>
{
private:

public:
MyString& operator=( const wchar_t* sVlu )
{ assign( sVlu ) ; return *this ; }
operator const wchar_t*( ) const
{ return c_str( ) ; }

public:
MyString( )
{ }
MyString( const wchar_t* sVlu )
{ assign( sVlu ) ; }
} ;

// ---------------------- StringData ----------------
class StringData
{
private:
std::basic_string<wchar_t> msVlu ;

public:
StringData& operator=( const wchar_t* sData )
{ msVlu = sData ; return *this ; }
operator const wchar_t*( ) const
{ return msVlu.c_str( ) ; }

public:
StringData( )
{ }
} ;
 
C

Carl Daniel [VC++ MVP]

Steve said:
here is a warning I am getting in a C++ .NET compile:

c:\SrNet\jury\JuryTest.cpp(55) : warning C4927: illegal conversion;
more than one user-defined conversion has been implicitly applied
while calling the constructor 'MyString::MyString(const
wchar_t *)'
c:\SrNet\jury\JuryTest.h(21) : see declaration of
'MyString::MyString'

The class "StringData" uses a, whatever you call it, operator const
whar_t*( ) to represent itself to other classes as a "const whar_t*".
A 2nd class, "MyString" has a constructor that accepts a "const
wchar_t*" when it is instantiated. Its a marriage made in code
heaven.

The problem is exactly as the warning states: two (more than one)
user-defined conversion has to be applied to convert StringData to MyString.

1. StringData.operator const wchar_t*
2. MyString(const wchar_t*)

The C++ standard stipulates that only a single user-defined conversion can
be implicitly applied by the compiler.

You have several choices:

1. Add a MyString conversion function to StringData.
2. Add a StringData& constructor to MyString.
3. Write an explicit cast for one of the two conversions required:

return static_cast<const wchar_t*>(data);

-cd
 
S

Steve Richter

Carl Daniel said:
The problem is exactly as the warning states: two (more than one)
user-defined conversion has to be applied to convert StringData to MyString.

1. StringData.operator const wchar_t*
2. MyString(const wchar_t*)

The C++ standard stipulates that only a single user-defined conversion can
be implicitly applied by the compiler.

You have several choices:

1. Add a MyString conversion function to StringData.

what is that, a user written function that returns the convert to
class?
MyString StringData::To_MyString( ) const ;
2. Add a StringData& constructor to MyString.
3. Write an explicit cast for one of the two conversions required:

return static_cast<const wchar_t*>(data);

thanks Carl.

Can anyone explain why this is? I thought the conversion of objects
from one class to another thru "operator class( )" and the constructor
was one of the foundations of C++.

MyString TestFunc( )
{
StringData data ;
return data ; // warning! illegal conversion.
}


-Steve

// ------------------------ MyString -------------------------------
class MyString : public std::basic_string<wchar_t>
{
private:

public:
MyString& operator=( const wchar_t* sVlu )
{ assign( sVlu ) ; return *this ; }
operator const wchar_t*( ) const
{ return c_str( ) ; }

public:
MyString( )
{ }
MyString( const wchar_t* sVlu )
{ assign( sVlu ) ; }
} ;

// ---------------------- StringData ----------------
class StringData
{
private:
std::basic_string<wchar_t> msVlu ;

public:
StringData& operator=( const wchar_t* sData )
{ msVlu = sData ; return *this ; }
operator const wchar_t*( ) const
{ return msVlu.c_str( ) ; }

public:
StringData( )
{ }
} ;
 
C

Carl Daniel [VC++ MVP]

Steve said:
what is that, a user written function that returns the convert to
class?
MyString StringData::To_MyString( ) const ;

Just as you can have an "operator const wchar_t*() const", you can also have
an "StringDate::blush:perator MyString() const".

class MyString;

class StringData
{
public:
// ...
operator MyString() const;
operator const wchar_t*() const { return 0; }
};

class MyString
{
public:
MyString(const wchar_t*) {}
// ...
};

StringData::blush:perator MyString() const
{
return MyString(static_cast<const wchar_t*>(*this));
}

MyString foo()
{
StringData s;
return s;
}

thanks Carl.

Can anyone explain why this is? I thought the conversion of objects
from one class to another thru "operator class( )" and the constructor
was one of the foundations of C++.

It is. You just need to define a more specific conversion. The limit on a
single user defined conversion is in the standard to prevent the compiler
from finding obtuse, unexpected and unwanted ways to compile code that
should be illegal by applying long series of conversions. Most experts
agree that implicit conversions are one of the major sources of errors in
C++, so the limit on only a single implicitly applied user defined
conversion is a good one. If you want StringData to convert to MyString
implicitly, you simply need to provide a one-step conversion.

-cd
 

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