I'm trying to understand the new default comparison operators introduced in C++20. My issue is about when an explicitly defaulted comparison operator gets implicitly defined. The following code example illustrates the question:
#include <iostream>
struct B
{
operator bool() const { return true; }
};
struct D : B
{
bool operator==(const D&) const = default;
};
bool operator==(B, B) { return false; }
int main ()
{ D d;
std::cout << (d == d);
}
/* Outputs:
0 in gcc 10.1
1 in msvc 19.26
*/
The output of this program is compiler-dependent. It seems that MSVC defines the operator== for class D when it is encounters the declaration as defaulted, hence it doesn't use the operator== that is defined later for class B. By contrast, gcc waits with the implicit definition of D's operator== until it is actually needed, by which time the operator== defined for B is in scope, and gets used. Which behavior, if either, is correct ?
A related question, is why a defaulted operator== can't be declared for a class with reference members ? I could see that reference members could pose a problem with the MSVC approach, because a reference member might refer to an incomplete type when the defaulting declaration for operator== is encountered. With the gcc approach, the reference's type would always be complete before gcc attempts to define the defaulted operator.
If operator<=> is defaulted and operator== is not declared at all, then operator== is implicitly defaulted.
The equality operators in C++ are is equal to(==) and is not equal to(!=). They do the task as they are named. The binary equality operators compare their operands for strict equality or inequality. The equality operators, equal to (==) and not equal to (!
The equality operator (==) is used to compare two values or expressions. It is used to compare numbers, strings, Boolean values, variables, objects, arrays, or functions.
Checking for equality in C and C++ identifier == identifier; The == sign is used to compare primitive types such as char, int, float, etc. The comparison operator returns true if the two identifiers are equal.
The first four operators in the list above have a higher precedence than the equality operators ( == and != ). See the precedence information in the table Precedence and Associativity of C Operators. The operands can have integral, floating, or pointer type. The types of the operands can be different.
The relational and equality operators test the following relationships: The first four operators in the list above have a higher precedence than the equality operators ( == and != ). See the precedence information in the table Precedence and Associativity of C Operators. The operands can have integral, floating, or pointer type.
The equality comparison function (whether defaulted or not) is called whenever values are compared using == or != and overload resolution selects this overload. Like defaulted special member functions, a defaulted comparison function is defined if odr-used or needed for constant evaluation .
Inequality operator != The inequality operator != returns true if its operands are not equal, false otherwise. For the operands of the built-in types, the expression x != y produces the same result as the expression ! (x == y). For more information about type equality, see the Equality operator section.
GCC is wrong here (not unsurprisingly considering its results). When creating the definition of a defaulted comparison operator, the standard says:
Name lookups in the defaulted definition of a comparison operator function are performed from a context equivalent to its function-body.
And the function body of a defaulted function is where = default
is. Therefore, the bool operator==(B, B)
function should not be visible to the function body of the defaulted comparison operator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With