Strange C2664 in Visual Studio 2005 C++ release candidate (v8.0.50727.26)

I'm converting a project from VS 6.0 SP5 to VS 2005 rc.  I'm getting this really odd C2664 error.  Unfortunately, the project is very complex and I have not yet been able to reproduce this behavior with a simple example.  I can, however, offer proof  of its strangeness:

   DBString dbx = m_scCal.operator const DBString();
   DBString dby = m_scCal;
   DBString dbz = ( const DBString )m_scCal;

Of the three example statements above, only the first one compiles.  I have no idea how it is that an explicit invocation of a converstion operator via the "." syntax can work, but explicit conversion through the type-cast syntax does not.

The error I get depends on whether or not I attempt an explicit or implicit conversion of the original type.

Note: the typedef "typedef CPVString DBString" exists in the preprocessor input stream for these source files.


An explicit conversion attempt yields:

c:\development\turboese_64\database\schema\objects.cpp(39) : error C2440: 'initializing' : cannot convert from 'const ft_structure_code' to 'CPVString'

No constructor could take the source type, or constructor overload resolution was ambiguous

An implicit conversion attempt yields the more informative:

c:\development\turboese_64\database\schema\objects.cpp(1606) : error C2664: 'CConstraintBase::ConstraintTypeToEnum' : cannot convert parameter 1 from 'ft_text' to 'const CPVString &'

Qualification conversion
followed by
Call to user-defined-conversion 'TDBField<managed_type>::operator const DBString(void) const'
with
[
   managed_type=DBFieldString
]
c:\development\turboese_64\database\dbenviron.h(906) : see declaration of 'TDBField<managed_type>::operator const DBString'
with
[
   managed_type=DBFieldString
]
followed by
Exactly the same type
followed by
Call to user-defined-conversion 'TDBField<managed_type>::operator const DBFieldString &(void) const'
with
[
   managed_type=DBFieldString
]
c:\development\turboese_64\database\dbenviron.h(912) : see declaration of 'TDBField<managed_type>::operator const DBFieldString &'
with
[
   managed_type=DBFieldString
]
followed by
Binding to reference

The above error seems particularly strange, given that the diagnostic information it provides seems to show a perfectly acceptable conversion path. Why didn't it use it

I set up the following code fragment in an attempt to reproduce this behavior, but it works perfectly:

typedef
char _TCHAR;
typedef const char *LPCTSTR;

class CPVString
{
   public : CPVString ();
              CPVString ( _TCHAR, int );
              CPVString ( LPCTSTR lpch, int nLength );

   public : virtual ~CPVString ();

   public : CPVString ( const CPVString & );
              CPVString ( LPCTSTR );
};

typedef CPVString DBString;

DBString ConvertToDBString()
{
    return ( DBString() );
}

template < class managed_type, int nBindingCount = 4 > class TDBField
{
   public : operator const DBString () const { return ( ConvertToDBString() ); }
};

typedef TDBField< bool > ft_Foo;

class CBar
{
   public : void SomeFunc()
const
              {
                  DBString dby = ( const DBString )m_fooData;
              }

   private : ft_Foo m_fooData;
};

The above is extracted directly from my code, although the various class definitions did not originally reside in the same include file and have also been truncated for brevity.




 



 



Answer this question

Strange C2664 in Visual Studio 2005 C++ release candidate (v8.0.50727.26)

  • Andr&amp;#233; Brisebois

    This has been resolved.  It turns out that the template actually generates two conversion operators.  The first conversion operator always converts to class C1 &.  The second conversion operator always converts to const class T1, where T1 is a template parameter.

    If, by coincidence T1 was a C1 (or was derived from C1) then the compiler would determine that the conversion operator choice was ambiguous.  In VC 6.0, you could get away with this if you invoked the conversion operator through a static type cast.  In VC 2005 RC, this isn't good enough and the selection is still considered ambiguous.

    This is a real pain for me, but I can't find any language rule that says this behavior is wrong.

    C'est la vie.

  • Strange C2664 in Visual Studio 2005 C++ release candidate (v8.0.50727.26)