error C2666: '==' : 2 overloads have similar conversions

Dec 23, 2010 at 11:50am
I have an overloaded comparison (==) operator which works fine until I add an overloading of char* operator. It gives following error then:

--------------------Configuration: myproject1 - Win32 Debug--------------------
Compiling...
stringcat.cpp
E:\vcpp\myproject1\stringcat.cpp(80) : error C2666: '==' : 2 overloads have similar conversions
Error executing cl.exe.

myproject1.exe - 1 error(s), 0 warning(s)


The source code is listed here. Can you please tell me what is the reason of the error and how to correct it?


#include<iostream>
#include<string>

#define MAX 80

using namespace std;

class String
{
char str[MAX];

public:
String()
{
strcpy(str,"");
}

//////////////////////////////////////////////////////////////////////////////

String(char s[])
{
strcpy(str, s);
}

//////////////////////////////////////////////////////////////////////////////

void display() const
{
cout<<str<<endl;
}

//////////////////////////////////////////////////////////////////////////////

String operator+(String sec)
{
String temp;
if(strlen(str)+strlen(sec.str) < MAX)
{
strcpy(temp.str, str);
strcat(temp.str, sec.str);
return temp;
}
else
{
cout<<"\nThe strings cannot be concatenated\n";
exit(0);
}
}

///////////////////////////////////////////////////////////////////////////////

bool operator== (String sec)
{
if(strcmp(str, sec.str)==0)
return true;
else
return false;
}

////////////////////////////////////////////////////////////////////////////////

operator char*()
{
return str;
}



};



int main()
{
String a = "Hello!";
String b = " How are you?";
String c;
c=a+b;
c.display();
if(c=="Hello! How are you?")
cout<<"\nStrings match\n";
else
cout<<"\nStrings do not match\n";
cout<<endl<<static_cast<char*>(a)<<endl<<static_cast<char*>(b)<<endl<<static_cast<char*>(c)<<endl;

return 0;
}
Dec 23, 2010 at 12:21pm
if(c=="Hello! How are you?")
there are two == opertors that can be used here: char* == char*, which would just compare the addresses, and string == string, which would do what you want. string can be converted to char* and char* can be converted to string, so the compiler can't know which one you want.
you could either c==String("Hello! How are you?") or just throw away the char* operator and add a c_str() function (like in std::string).
Last edited on Dec 23, 2010 at 12:21pm
Dec 24, 2010 at 5:40am
Hey Hamsterman !! Thanks for this. But I have two questions now:

1) Why does compiler even think of using char* == char* , when on the left hand side it is an object of my class and not a string.?


2) I agree that I should have used c==String("Hello! How are you?"). Thanks for making me realize my mistake. But in this case, why didnt the compiler give error something like "== not defined to use a constant string on right side".?

Why the error is totally diferent.. i.e. by what logic, compiler starts thinking which of the two overloads [char*==char* and string == string ] to use?

Please make me understand.
Dec 24, 2010 at 10:04am
1) Here you have String == char*. This is one conversion away from both String == String and char* == char*. The compiler doesn't give any priority to your own classes.

2) Actually you should not. You should throw away operator char* instead. It is hardly ever useful.
There was no "not defined" error because of http://www.cplusplus.com/doc/tutorial/typecasting/

Compiler looks for a function which requires fewest conversions. for example if you had an operator == (String, char*) there would have been no error (but of course you shouldn't write an operator for every possible combination)

By the way, you may want to take a look at http://www.cplusplus.com/forum/lounge/33225/
Dec 24, 2010 at 11:25am

1) Why does compiler even think of using char* == char* , when on the left hand side it is an object of my class and not a string.?


By defining a conversion of your String class to char*, you have made the statement c=="Hello! How are you?" ambiguous; you get the error because the compiler does not know which to use.

"c" can be converted to a char* with your new conversion resulting in char*==char* operator, which just compares pointers, or "Hello! How are you?", which is const char*, can be converted to a String resulting in String==String operator. This is because a single argument constructor like String(char s[]) implicitly defines a conversion of char* to String. You can declare the constructor to be "explicit" to prevent its implicit use, but you probably still want conversion of char* to String. You probably don't really want conversion of String to char* though, so I would recommend removing the char* conversion operator in favor of a c_str() as hamsterman suggest.

Other recommendations:

You should define some other operators for some of the things you are doing rather than depending on explicit or implicit conversion operators.

For example, you should probably define operator=(const char*) and operator==, also taking a char* directly. See http://www.cplusplus.com/reference/string/string/ for more examples. Note the comparison functions along with operator+, operator>>, and operator<< are global (non-member) functions listed under "Strings library". Also note the function signature of these and the member function operators; most arguments are passed by const reference rather than by value.


2) I agree that I should have used c==String("Hello! How are you?"). Thanks for making me realize my mistake. But in this case, why didnt the compiler give error something like "== not defined to use a constant string on right side".?


It is defined by implicit conversion of char* to String.


Why the error is totally diferent.. i.e. by what logic, compiler starts thinking which of the two overloads [char*==char* and string == string ] to use?


This should be evident from the above explanation.
Dec 25, 2010 at 10:53am
Wow !! It was such a clear explanation.. Thanks to both jimc and Hamsterman !! :-)
Topic archived. No new replies allowed.