Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
josuttis_nm_c20_the_complete_guide.pdf
Скачиваний:
53
Добавлен:
27.03.2023
Размер:
5.85 Mб
Скачать

1.4 Overload Resolution with Rewritten Expressions

17

struct D : public B {

auto operator<=> (const D&) const = default;

};

the compiler does not compile any call with relational operators because it cannot decide which ordering category the base class has. In that case, you need operator<=> in the base class too.

However, checks for equality work, because in D, operator== is automatically declared equivalent to the following:

struct D : public B {

auto operator<=> (const D&) const = default; bool operator== (const D&) const = default;

};

This means that we have the following behavior:

D d1, d2;

d1 > d2; // ERROR: cannot deduce comparison category of operator<=>

d1 != d2; // OK (note: only tries operator<=> and B::operator== of a base class)

Equality checks always use only operator== of a base class (which might be generated according to a defaulted operator<=> though). Any operator< or operator!= in the base class is ignored.

The same applies, if D has a member of type B.

1.4Overload Resolution with Rewritten Expressions

Let us finally elaborate on the evaluation of expressions with comparison operators with the support of rewritten calls.

Calling Equality Operators

To compile

x != y

the compiler might now try all of the following:

x.operator!=(y)

// calling member operator!= for x

operator!=(x, y)

// calling a free-standing operator!= for x and y

!x.operator==(y)

// calling member operator== for x

!operator==(x, y)

// calling a free-standing operator== for x and y

!x.operator==(y)

// calling member operator== generated by operator<=> for x

!y.operator==(x)

// calling member operator== generated by operator<=> for y

The last form is tried to support an implicit type conversion for the first operand, which requires that the operand is a parameter.

18

Chapter 1: Comparisons and Operator <=>

In general, the compiler tries to call:

A free-standing operator !=: operator!=(x, y) or a member operator !=: x.operator!=(y)

Having both operators != defined is an ambiguity error.

A free-standing operator ==: !operator==(x, y) or a member operator ==: !x.operator==(y)

Note that the member operator == may be generated from a defaulted operator<=> member. Again, having both operators == defined is an ambiguity error. This also applies if the member

operator== is generated due to a defaulted operator<=>.

When an implicit type conversion for the first operand v is necessary, the compiler also tries to reorder the operands. Consider:

42 != y // 42 implicitly converts to the type of y

In that case, the compiler tries to call in that order:

A free-standing or member operator !=

A free-standing or member operator == (note that the member operator == may be generated from a defaulted operator<=> member)1

Note that a rewritten expression never tries to call a member operator !=.

Calling Relational Operators

For the relational operators we have similar behavior, except that the rewritten statements fall back on the new operator <=> and compare the result with 0. The operator behaves like a three-way comparison function returning a negative value for less, 0 for equal, and a positive value for greater (the returned value is not a numeric value; it is only a value that supports the corresponding comparisons).

For example, to compile

x <= y

the compiler might now try all of the following:

x.operator<=(y)

// calling member operator<= for x

operator<=(x, y)

// calling a free-standing operator<= for x and y

x.operator<=>(y) <= 0

// calling member operator<=> for x

operator<=>(x, y) <= 0

// calling a free-standing operator<=> for x and y

0 <= y.operator<=>(x)

// calling member operator<=> for y

Again, the last form is tried to support an implicit type conversion for the first operand, for which it has to become a parameter.

1 The original C++20 standard was fixed here slightly with http://wg21.link/p2468r2.