comparing a string variable to an explicit char* value in C++


I don’t understand why this code compiles and runs:

std::string s;
std::cin >> s;
// if (s == "done") {     // version 1
if ("done" == s) {        // version 2
    std::cout << "We're done here" << std::endl;

Version 1 works as I would expect. The compiler sees that s is a std::string, and uses the std::string definition of == to do the comparison.

However, when comparing a variable to an explicit value, I like to use the trick of putting the explicit value first in case one day I accidentally use = instead and do an assignment instead. Hence, version 2.

Now version 2 works on my compiler (llvm on MacOS) the same way as version 1, but I’m not sure why (or if it’s a reliable result). I would have though that the compiler sees "done" as a char* explicit constant and says, "hey, == makes no sense on char*" and give me a compilation error message. But my compiler doesn’t do that, it compiles without complaint and the code executes the same way as version 1.

What am I misunderstanding here?

>Solution :

The type of "done" is not char*. It is const char[5].

But in any case, it works because if you include <string>, which you must have to use std::string, then (before C++20) you include an overload for operator== of the form

template< class CharT, class Traits, class Alloc >
bool operator==( const std::basic_string<CharT,Traits,Alloc>& lhs,
                 const CharT* rhs );

and one of the form

template< class CharT, class Traits, class Alloc >
bool operator==( const CharT* lhs,
                 const std::basic_string<CharT,Traits,Alloc>& rhs );

See for reference.

std::string is just std::basic_string with CharT being char and Traits and Alloc being some defaults that don’t matter here.

So effectively one overload accepts a const std::string& as left-hand argument and const char* as right-hand argument, and the other accepts the reverse.

const char[N] can be deduced as const char* and it is implicitly convertible to the latter for every N, so the first overload is viable for s == "done" and the second for "done" == s.

The standard library is written with these overloads specifically so that your use will work. Your approach of using the "done" == s variant makes sense, because "done" = s would indeed be an error. operator= can only be overloaded with a class type on the left-hand side.

Since C++20, the overloads look a bit different. In particular it isn’t necessary to have both anymore. The compiler now automatically tries overloads matching the rewritten expression with reversed operands of == when doing overload resolution.

to an explicit value,

explicit constant

I am not sure what you mean here, but "explicit value" and "explicit constant" are not standard terminology. Probably you mean "(string) literal" instead.

and says, "hey, == makes no sense on char*"

It doesn’t work that way. As soon as either side of == is a class type, the compiler has to consider that == may be overloaded to match the expression.

Leave a Reply Cancel reply