How does the C++ compiler interpret the == operator? - c++

std::string somestring;
/*...*/
if("STRING_LITERAL" == somestring)
std::cout << "Strings are Equal" << std::endl;
In the sample code above, how does a C++ compiler interpret the ==
operator? As the == operator overloaded by the string class?

If you're using std::string then you should have #included the <string> header. Assuming this is the case then the operator== selected should be the non-member template function from <string> with appropriate template parameters deduced. (ISO/IEC 14882:2003 21.3.7.2 [lib.string::operator==])
template<class charT, class traits, class Allocator>
bool operator==(const charT* lhs,
const basic_string<charT,traits,Allocator>& rhs);
The std::string class (strictly class template specialization) doesn't contain any member overloads for operator==.

Yes. The operator== is implemented as a free standing function, that's why the positioning is irrelevant. It could be
bool operator==(const string& str1, const char* str2){
// ...
}
or
bool operator==(const char* str1, const string& str2){
// ...
}
or even a simple
bool operator==(const string& str1, const string& str2){
// ...
}
With an automatic conversion from char const* to string, as the relevant constructor of std::string is non-explicit.

There is an overload of operator== that does the right thing:
template <class charT, class traits, class Allocator>
bool operator==(const charT* lhs,
const basic_string<charT, traits, Allocator>& rhs);
You can find it in 21.3 ยง1 of the C++0x FDIS on page 635.

From http://www.cplusplus.com/reference/string/operators/ , these overloads are defined:
bool operator== ( const string& lhs, const string& rhs );
bool operator== ( const char* lhs, const string& rhs );
bool operator== ( const string& lhs, const char* rhs );
Note that these are global functions, not methods of the string class (but they'll be implemented using string::compare().

Related

comparing a string variable to an explicit char* value

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 value (literal) 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?
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 https://en.cppreference.com/w/cpp/string/basic_string/operator_cmp 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.
For the class template std::basic_string the equality operator == is overloaded in particular the following way
template<class charT, class traits, class Allocator>
bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs);
So the first argument maybe a C string literal without requiring any conversion (except the standard implicit conversion from an array type to pointer to the array element type).
Actually the operator has three overloads
template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT, traits, Allocator>& lhs,
const basic_string<charT, traits, Allocator>& rhs) noexcept;
template<class charT, class traits, class Allocator>
bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs);
and
template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT, traits, Allocator>& lhs,
const charT* rhs);

c++20: std::string equality operator [duplicate]

This question already has answers here:
Operator overloading : member function vs. non-member function?
(2 answers)
Is there any advantage to implementing functions as free functions rather than members in C++?
(6 answers)
Closed 26 days ago.
This post was edited and submitted for review 26 days ago and failed to reopen the post:
Original close reason(s) were not resolved
I cpp doc we see:
template< class CharT, class Traits, class Alloc >
bool operator==( const std::basic_string<CharT,Traits,Alloc>& lhs,
const CharT* rhs ); (until C++20)
template< class CharT, class Traits, class Alloc >
constexpr bool operator==( const std::basic_string<CharT,Traits,Alloc>& lhs,
const CharT* rhs ); (since C++20)
template< class CharT, class Traits, class Alloc >
bool operator==( const CharT* lhs,
const std::basic_string<CharT,Traits,Alloc>& rhs ); (until C++20)
My question is:
Why if c++20 gives us feature to 'reverse' operators equality operator is still non class member function? What is the reason?
Update:
Code example:
#include <iostream>
#include <string>
struct MyString {
std::string m_val;
MyString(const char* val) : m_val(val) {}
bool operator==(const char* other) const { return m_val == other; }
};
int main() {
MyString tata = "tata";
std::cout << ("mama" == tata) << std::endl;
return 0;
}
This code compiles with c++20 but not with c++17.
Here equality operator is a member of a class. Why did not std implementation go this way?

Operators for non-primitive boxed types

I have the following class definition:
template <typename T>
class MyBox {
public:
MyBox(T value) { _value = value; }
operator T() const { return _value; }
private:
T _value;
};
typedef MyBox<int> MyInt;
typedef MyBox<std::string> MyString;
When I try to use operators on my typedefs like this
bool first = MyInt(1) == MyInt(1); // works
bool second = std::string(MyString("a")) == std::string(MyString("a")); //works
bool third = MyString("a") == MyString("a"); // does not compile
the compiler complains about the third comparison
no operator "==" matches these operands. operand types are: MyString == MyString
and this happens with any other non-primitve boxing (e.g. MyBox<float> works but MyBox<std::map<int,int> > not. Why is that so?
This is especially unclear to me because for the first and second comparison the operator T() is used - why can't that be done automatically for MyString as well?
UPDATE: Is there a simple solution to this other than providing the specific operators for each non-primitive template? And what to do with MyString("a") == std::string("a")?
The reasons on why it works for built-in types, but does't work for custom types is answered in the following SO quesiton: using user-defined conversions with implicit conversions in comparisons. In short, this is because type conversion does not happen for template-deduced types. And while built-in operator== for int is not a template (and thus can be found using type conversion when MyBox<int> is used), operator== for std::string is a template.
However, the question mentioned above doesn't have details on how to solve this problem. Here is how: add following free functions
template<class T>
bool operator==(const MyBox<T>& lhs, const MyBox<T>& rhs) {
return static_cast<const T&>(lhs) == static_cast<const T&>(rhs);
}
template<class T>
bool operator==(const MyBox<T>& lhs, const T& rhs) {
return static_cast<const T&>(lhs) == rhs;
}
template<class T>
bool operator==(const T& lhs, const MyBox<T>& rhs) {
return lhs == static_cast<const T&>(rhs);
}

How does the const char* and string comparison work in C++?

Consider the following code snippet:
#include <iostream>
int main() {
std::string str = "Hello";
const char *cstr = "Hello";
if (cstr == str) {
std::cout<<"Both are same string.";
}
return 0;
}
I am having difficulty guessing how the const char* and string comparison work:
if (cstr == str) {
As per my understanding, the overloaded operator of the left operand (cstr in this case) is called with str as the argument. Now there is no overloading of == for const char*. So how does the above comparison even work?
Had the comparison been str==cstr, I would have no issues accepting it (as == for std::string is overloaded and it accepts const char* as an argument for comparison).
Note:- I am using gcc-4.8.1 for compiling the above code.
As per my understanding, the overloaded operator of the left operand (cstr in this case) is called with str as the argument. Now there is no overloading of == for const char*.
The operator is actually for std::string, and looks conceptually similar to this:
bool operator==(const char* const lhs, const std::string& rhs);
(though it reality it is templated).
This operator of std::string is added specifically for the operation you mention (comparing a std::string with a char*, when the char* is provided as the left-hand-side operand in the comparison).
Had the comparison been str==cstr, I would have no issues accepting it (as == for std::string is overloaded and it accepts const char* as an argument for comparison).
Both are present (specifically to support this situation).
From http://en.cppreference.com/w/cpp/string/basic_string/operator_cmp.
Compare a basic_string object and null-terminated array of T
template< class CharT, class traits, class Alloc >
bool operator==(const CharT* lhs, const basic_string<CharT,Traits,Alloc>& rhs);
template< class CharT, class traits, class Alloc >
bool operator==(const basic_string<CharT,Traits,Alloc>& lhs, const CharT* rhs);
...

Do I need to manually declare >= and <= operators?

If I already have operator > and operator < defined (and operator ==), do I need to define operator >= and operator <=, or will the compiler declare them for me if I intentionally don't declare them?
Also, if I have operator == defined, will the compiler declare operator != for me?
No, the Compiler won't declare/define any of the operators you did not define manually. However, Boost.Operators might be to your liking - it does exactly what you want the compiler to do.
The compiler won't do anything itself for you here, but it's
relatively simple to generate automatically by inheriting from
an appropriate class, something like:
template< typename DerivedType >
class ComparisonOperators
{
public:
friend bool operator!=(
DerivedType const& lhs,
DerivedType const& rhs )
{
return !(lhs == rhs);
}
friend bool operator<=(
DerivedType const& lhs,
DerivedType const& rhs )
{
return !(rhs < lhs);
}
friend bool operator>(
DerivedType const& lhs,
DerivedType const& rhs )
{
return rhs < lhs;
}
friend bool operator>=(
DerivedType const& lhs,
DerivedType const& rhs )
{
return !(lhs < rhs);
}
protected:
~ComparisonOperators() {}
} ;
Define < and == in your class, and derive from this, and
you'll get all of the operators:
class MyClass : public ComparisonOperators<MyClass>
{
// ...
public:
bool operator==( MyClass const& other ) const;
bool operator<( MyClass const& other ) const;
// ...
};
Just a note: I've manually simplified the version I actual use,
which defines == and < as well, looks for the member
functions compare and isEqual, and uses compare for ==
and != when there is no isEqual. I don't think I've
introduced any errors, but you never know.
There are already some good answers here using boost and inheritance. But as someone noted - using inheritance for operator creation seems... wrong.
I know #defines are "taboo" in C++, but still that's what I use here.
I have a #define in my general utility include that goes like this:
#define CREATE_COMPARITORS(name) \
inline bool operator>(const name &o){return o<*this;} \
inline bool operator<=(const name &o){return not (o<*this);} \
inline bool operator>=(const name &o){return not (*this<o);} \
inline bool operator!=(const name &o){return not (*this==o);}
Then if I have a class, all I need to declare is operator< and operator==:
class ttt{
//...
bool operator<(const ttt &o);
bool operator==(const ttt &o);
CREATE_COMPARITORS(ttt);
//...
};