overload resolution in VC 6.0
-
I have a PString class that derives from CString. In it, I overload the + operator so I can add a PString and long variable to give me a new PString. It works fine in VC 5.0, but while converting to VC 6.0, I get a C2666 error saying it cannot determine which overloaded + to use. Here is the code segment: PString strTemp1 = "abc"; long lTemp1 = 123; PString strTemp2 = "def"; (1) strTemp2 = strTemp1 + strTemp2; // works fine. (2) strTemp2 = strTemp1 + lTemp1; // C2666 error. (3) strTemp2 = +(strTemp1, lTemp1); // no error. (4) strTemp2 = ::operator +(strTemp1, lTemp1); // no err class PString : public CString { public: .... PCSGENRL_EXP_TYPE friend PString operator +( const PString& string1, const PString& string2 ); PCSGENRL_EXP_TYPE friend PString operator +( const PString& string, TCHAR ch ); PCSGENRL_EXP_TYPE friend PString operator +( TCHAR ch, const PString& string ); PCSGENRL_EXP_TYPE friend PString operator +( const PString& string, LPCTSTR lpsz ); PCSGENRL_EXP_TYPE friend PString operator +( LPCTSTR lpsz, const PString& string ); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const long& value); PCSGENRL_EXP_TYPE friend PString operator +(const long& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const double& value); PCSGENRL_EXP_TYPE friend PString operator +(const double& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const int& value); PCSGENRL_EXP_TYPE friend PString operator +(const int& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string, const ULONG& value); PCSGENRL_EXP_TYPE friend PString operator +(const ULONG& value,const PString& string); Why does line (2) give an error, while lines (3) and (4) give no compile error? Aren't they the same instruction? Any help would be appreciated. Pat
-
I have a PString class that derives from CString. In it, I overload the + operator so I can add a PString and long variable to give me a new PString. It works fine in VC 5.0, but while converting to VC 6.0, I get a C2666 error saying it cannot determine which overloaded + to use. Here is the code segment: PString strTemp1 = "abc"; long lTemp1 = 123; PString strTemp2 = "def"; (1) strTemp2 = strTemp1 + strTemp2; // works fine. (2) strTemp2 = strTemp1 + lTemp1; // C2666 error. (3) strTemp2 = +(strTemp1, lTemp1); // no error. (4) strTemp2 = ::operator +(strTemp1, lTemp1); // no err class PString : public CString { public: .... PCSGENRL_EXP_TYPE friend PString operator +( const PString& string1, const PString& string2 ); PCSGENRL_EXP_TYPE friend PString operator +( const PString& string, TCHAR ch ); PCSGENRL_EXP_TYPE friend PString operator +( TCHAR ch, const PString& string ); PCSGENRL_EXP_TYPE friend PString operator +( const PString& string, LPCTSTR lpsz ); PCSGENRL_EXP_TYPE friend PString operator +( LPCTSTR lpsz, const PString& string ); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const long& value); PCSGENRL_EXP_TYPE friend PString operator +(const long& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const double& value); PCSGENRL_EXP_TYPE friend PString operator +(const double& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const int& value); PCSGENRL_EXP_TYPE friend PString operator +(const int& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string, const ULONG& value); PCSGENRL_EXP_TYPE friend PString operator +(const ULONG& value,const PString& string); Why does line (2) give an error, while lines (3) and (4) give no compile error? Aren't they the same instruction? Any help would be appreciated. Pat
it probably can't decide between long and int for the second value. try this : strTemp2 = strTemp1 + (long)lTemp1; =c
Smaller Animals Software, Inc. http://www.smalleranimals.com
-
it probably can't decide between long and int for the second value. try this : strTemp2 = strTemp1 + (long)lTemp1; =c
Smaller Animals Software, Inc. http://www.smalleranimals.com
I tried strTemp2 = strTemp1 + (long)lTemp1; and it still gives the C2666 error. I agree that it probably can't decide the type of that second value, but I have tried changing the overload definitions to PCSGENRL_EXP_TYPE friend PString operator +(const PString& string, const long& value); and PCSGENRL_EXP_TYPE friend PString operator +(const PString& string, long& value); and PCSGENRL_EXP_TYPE friend PString operator +(const PString& string, long value); From what I have read on this error in the help pages, if the compiler can't find an exact match, then it will try to do some conversions to get a match. You would think that one of the above 3 overloaded definitions would give an exact match so the compiler wouldn't have to do any conversions. But I guess I am missing something. I assume the first argument is fine because I can add a PString and a PString. So it must be something with the second (long) argument, but I can't figure it out. Pat
-
I have a PString class that derives from CString. In it, I overload the + operator so I can add a PString and long variable to give me a new PString. It works fine in VC 5.0, but while converting to VC 6.0, I get a C2666 error saying it cannot determine which overloaded + to use. Here is the code segment: PString strTemp1 = "abc"; long lTemp1 = 123; PString strTemp2 = "def"; (1) strTemp2 = strTemp1 + strTemp2; // works fine. (2) strTemp2 = strTemp1 + lTemp1; // C2666 error. (3) strTemp2 = +(strTemp1, lTemp1); // no error. (4) strTemp2 = ::operator +(strTemp1, lTemp1); // no err class PString : public CString { public: .... PCSGENRL_EXP_TYPE friend PString operator +( const PString& string1, const PString& string2 ); PCSGENRL_EXP_TYPE friend PString operator +( const PString& string, TCHAR ch ); PCSGENRL_EXP_TYPE friend PString operator +( TCHAR ch, const PString& string ); PCSGENRL_EXP_TYPE friend PString operator +( const PString& string, LPCTSTR lpsz ); PCSGENRL_EXP_TYPE friend PString operator +( LPCTSTR lpsz, const PString& string ); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const long& value); PCSGENRL_EXP_TYPE friend PString operator +(const long& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const double& value); PCSGENRL_EXP_TYPE friend PString operator +(const double& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string,const int& value); PCSGENRL_EXP_TYPE friend PString operator +(const int& value, const PString& string); PCSGENRL_EXP_TYPE friend PString operator +(const PString& string, const ULONG& value); PCSGENRL_EXP_TYPE friend PString operator +(const ULONG& value,const PString& string); Why does line (2) give an error, while lines (3) and (4) give no compile error? Aren't they the same instruction? Any help would be appreciated. Pat
Amusing problem! First, your line (3) is probably not the same as (2), but rather a very different expression that by chance happens to compile. If I'm right, the compiler interprets it as a call to unary
operator +
applied tostrTemp1, lTemp1
, which in turn is parsed as the sequencingoperator ,
applied tostrTemp1
andlTemp1
. In a nutshell, (3) is parsed as:strTemp2 = +(strTemp1, lTemp1) // apply operator , to yield:
strTemp2 = +(lTemp1); // apply unary operator + (idempotent for longs) to yield:
strTemp2 = lTemp1; // apply user defined conversion from long to PStringFor this analysis to hold water, some conversion from
long
toPString
must exist. Otherwise I'm wrong (please confirm this). You can also check this hypothesis simply by printing out the result of (3) and seeing if it corresponds to the "stringed" value oflTemp1
. Then, if (3) actually is ruled out, we are left with solving the riddle of (4) compiling fine and (2) producing a C2666 error. IMHO, the only way for (4) not being equivalent to (2) is that your addition operators are defined in a namespace other than the global namespace, and the::
in::operator +
is making the difference by narrowing the set of addition operators applicable. Again, you're the one who can confirm or deny this. So, if (3) and (4) give no error for the reasons I said (which I'm far from sure), then probably (2) fails legally to compile due to an overabundance of applicable operators and conversion. See this Microsoft article for an analysis of a problem resembling yours. Why VC++ 5.0 compiled fine and 6.0 complains? Well, maybe is 6.0 being more standard compliant with respect to Koening lookup, who knows. As you see, this is just a chain of speculations. Some of them you can easily check out (please inform back). Also, I suggest you post this problem to comp.lang.c++.moderated for more authoritative opinions. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo -
Amusing problem! First, your line (3) is probably not the same as (2), but rather a very different expression that by chance happens to compile. If I'm right, the compiler interprets it as a call to unary
operator +
applied tostrTemp1, lTemp1
, which in turn is parsed as the sequencingoperator ,
applied tostrTemp1
andlTemp1
. In a nutshell, (3) is parsed as:strTemp2 = +(strTemp1, lTemp1) // apply operator , to yield:
strTemp2 = +(lTemp1); // apply unary operator + (idempotent for longs) to yield:
strTemp2 = lTemp1; // apply user defined conversion from long to PStringFor this analysis to hold water, some conversion from
long
toPString
must exist. Otherwise I'm wrong (please confirm this). You can also check this hypothesis simply by printing out the result of (3) and seeing if it corresponds to the "stringed" value oflTemp1
. Then, if (3) actually is ruled out, we are left with solving the riddle of (4) compiling fine and (2) producing a C2666 error. IMHO, the only way for (4) not being equivalent to (2) is that your addition operators are defined in a namespace other than the global namespace, and the::
in::operator +
is making the difference by narrowing the set of addition operators applicable. Again, you're the one who can confirm or deny this. So, if (3) and (4) give no error for the reasons I said (which I'm far from sure), then probably (2) fails legally to compile due to an overabundance of applicable operators and conversion. See this Microsoft article for an analysis of a problem resembling yours. Why VC++ 5.0 compiled fine and 6.0 complains? Well, maybe is 6.0 being more standard compliant with respect to Koening lookup, who knows. As you see, this is just a chain of speculations. Some of them you can easily check out (please inform back). Also, I suggest you post this problem to comp.lang.c++.moderated for more authoritative opinions. Joaquín M López Muñoz Telefónica, Investigación y DesarrolloThanks Joaquin, You are right on in your analysis. The result of line (3) is the value of lTemp1 "stringed", exactly as you broke it down. In fact, I thought my overload of PString + PString was working, but I stepped into the code with the debugger, and it wasn't going to my PString overload of '+', but to the CString overload of '+'. So it was doing a PString to CString conversion for me behind the scenes.. In researching this problem, the only thing I could come up with is that there are 2 ways to override the operators. One is to have a 'friend' function within the class. The other is to define it globally, outside the class. So I took my + overrides out of the PString class and defined them globally. Now things seem to be working just fine. I guess there was some scope issues. BTW, in reading about the C2666 error, I did read that the reason behind errors like this is because Microsoft is implementing/enforcing more of the accepted C++ standards, just as you speculated. Thanks for your analysis on this one. Pat