Skip to content

Commit 79cd78c

Browse files
authored
Merge 2019-02 CWG Motion 12
P1185R2 <=> != == Fixes #2692.
2 parents be2863b + d69814f commit 79cd78c

File tree

3 files changed

+141
-42
lines changed

3 files changed

+141
-42
lines changed

source/classes.tex

Lines changed: 109 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6642,28 +6642,56 @@
66426642
declared in the \grammarterm{member-specification} of \tcode{C}
66436643
that is
66446644
\begin{itemize}
6645-
\item a non-static member of \tcode{C} having one parameter of type \tcode{const C\&}, or
6645+
\item a non-static const member of \tcode{C} having one parameter of type \tcode{const C\&}, or
66466646
\item a friend of \tcode{C} having two parameters of type \tcode{const C\&}.
66476647
\end{itemize}
66486648

66496649
\pnum
6650-
\indextext{structural comparison operator|see{operator, structural comparison}}%
6651-
A three-way comparison operator for a class type \tcode{C}
6652-
is a \defnadj{structural comparison}{operator}
6653-
if it is defined as defaulted in the definition of \tcode{C},
6654-
and all three-way comparison operators it invokes
6655-
are structural comparison operators.
6656-
\indextext{strong structural equality|see{equality, strong structural}}%
6657-
A type \tcode{T}
6658-
has \defnadj{strong structural}{equality}
6659-
if, for a glvalue \tcode{x} of type \tcode{const T},
6660-
\tcode{x <=> x} is a valid expression
6661-
of type \tcode{std::strong_ordering} or \tcode{std::strong_equality}
6662-
and either does not invoke a three-way comparison operator
6663-
or invokes a structural comparison operator.
6650+
If the class definition
6651+
does not explicitly declare an \tcode{==} operator function,
6652+
but declares a defaulted three-way comparison operator function,
6653+
an \tcode{==} operator function is declared implicitly
6654+
with the same access as the three-way comparison operator function.
6655+
The implicitly-declared \tcode{==} operator for a class \tcode{X}
6656+
is an inline member and is defined as defaulted in the definition of \tcode{X}.
6657+
If the three-way comparison operator function
6658+
is declared as a non-static const member,
6659+
the implicitly-declared \tcode{==} operator function is a member of the form
6660+
\begin{codeblock}
6661+
bool X::operator==(const X&) const;
6662+
\end{codeblock}
6663+
Otherwise, the implicitly-declared \tcode{==} operator function is of the form
6664+
\begin{codeblock}
6665+
friend bool operator==(const X&, const X&);
6666+
\end{codeblock}
6667+
\begin{note}
6668+
Such a friend function is visible
6669+
to argument-dependent lookup\iref{basic.lookup.argdep}
6670+
only\iref{namespace.memdef}.
6671+
\end{note}
6672+
The operator is a \tcode{constexpr} function if its definition
6673+
would satisfy the requirements for a \tcode{constexpr} function.
6674+
\begin{note}
6675+
The \tcode{==} operator function is declared implicitly even if
6676+
the defaulted three-way comparison operator function is defined as deleted.
6677+
\end{note}
66646678

6665-
\rSec2[class.spaceship]{Three-way comparison}
6666-
\indextext{operator!three-way comparison!defaulted}%
6679+
\pnum
6680+
\indextext{structural comparison operator|see{operator, structural comparison}}%
6681+
A type \tcode{C} has \defnadj{strong structural}{equality} if,
6682+
given a glvalue \tcode{x} of type \tcode{const C}, either:
6683+
\begin{itemize}
6684+
\item
6685+
\tcode{C} is a non-class type and \tcode{x <=> x} is a valid expression
6686+
of type \tcode{std::strong_ordering} or \tcode{std::strong_equality}, or
6687+
\item
6688+
\tcode{C} is a class type with an \tcode{==} operator
6689+
defined as defaulted in the definition of \tcode{C},
6690+
\tcode{x == x} is well-formed when contextually converted to \tcode{bool},
6691+
all of \tcode{C}'s base class subobjects and non-static data members
6692+
have strong structural equality, and
6693+
\tcode{C} has no \tcode{mutable} or \tcode{volatile} subobjects.
6694+
\end{itemize}
66676695

66686696
\pnum
66696697
The direct base class subobjects of \tcode{C},
@@ -6681,12 +6709,70 @@
66816709
derived-to-base conversions\iref{over.best.ics},
66826710
class member access expressions\iref{expr.ref}, and
66836711
array subscript expressions\iref{expr.sub} applied to \tcode{x}.
6684-
The type of the expression $\tcode{x}_i$ \tcode{<=>} $\tcode{x}_i$
6685-
is denoted by $\tcode{R}_i$.
6686-
It is unspecified
6687-
whether virtual base class subobjects are compared more than once.
6712+
It is unspecified whether virtual base class subobjects
6713+
appear more than once in the expanded list of subobjects.
6714+
6715+
\rSec2[class.eq]{Equality operators}
6716+
\indextext{operator!equality!defaulted}%
6717+
\indextext{operator!inequality!defaulted}%
6718+
6719+
\pnum
6720+
A defaulted equality operator\iref{expr.eq} function
6721+
shall have a declared return type \tcode{bool}.
6722+
6723+
\pnum
6724+
A defaulted \tcode{==} operator function for a class \tcode{C}
6725+
is defined as deleted
6726+
unless, for each $\tcode{x}_i$ in the expanded list of subobjects
6727+
for an object \tcode{x} of type \tcode{C},
6728+
$\tcode{x}_i\tcode{ == }\tcode{x}_i$ is a valid expression and
6729+
contextually convertible to \tcode{bool}.
66886730

66896731
\pnum
6732+
The return value \tcode{V} of a defaulted \tcode{==} operator function
6733+
with parameters \tcode{x} and \tcode{y} is determined
6734+
by comparing corresponding elements $\tcode{x}_i$ and $\tcode{y}_i$
6735+
in the expanded lists of subobjects for \tcode{x} and \tcode{y}
6736+
until the first index $i$
6737+
where $\tcode{x}_i\tcode{ == }\tcode{y}_i$ yields a result value which,
6738+
when contextually converted to \tcode{bool}, yields \tcode{false}.
6739+
If no such index exists, \tcode{V} is \tcode{true}.
6740+
Otherwise, \tcode{V} is \tcode{false}.
6741+
6742+
\pnum
6743+
A defaulted \tcode{!=} operator function for a class \tcode{C}
6744+
with parameters \tcode{x} and \tcode{y} is defined as deleted if
6745+
\begin{itemize}
6746+
\item
6747+
overload resolution\iref{over.match}, as applied to \tcode{x == y}
6748+
(also considering synthesized candidates
6749+
with reversed order of parameters\iref{over.match.oper}),
6750+
results in an ambiguity or a function
6751+
that is deleted or inaccessible from the operator function, or
6752+
\item
6753+
\tcode{x == y} cannot be contextually converted to \tcode{bool}.
6754+
\end{itemize}
6755+
Otherwise, the operator function yields \tcode{(x == y) ?\ false :\ true}.
6756+
6757+
\pnum
6758+
\begin{example}
6759+
\begin{codeblock}
6760+
struct D {
6761+
int i;
6762+
friend bool operator==(const D& x, const D& y) = default;
6763+
// OK, returns \tcode{x.i == y.i}
6764+
bool operator!=(const D& z) const = default; // OK, returns \tcode{(*this == z) ?\ false :\ true}
6765+
};
6766+
\end{codeblock}
6767+
\end{example}
6768+
6769+
\rSec2[class.spaceship]{Three-way comparison}
6770+
\indextext{operator!three-way comparison!defaulted}%
6771+
6772+
\pnum
6773+
Given an expanded list of subobjects for an object \tcode{x} of type \tcode{C},
6774+
the type of the expression $\tcode{x}_i$ \tcode{<=>} $\tcode{x}_i$
6775+
is denoted by $\tcode{R}_i$.
66906776
If the declared return type
66916777
of a defaulted three-way comparison operator function
66926778
is \tcode{auto},
@@ -6756,13 +6842,11 @@
67566842
\end{note}
67576843
\end{itemize}
67586844

6759-
\rSec2[class.rel.eq]{Other comparison operators}
6845+
\rSec2[class.rel]{Relational operators}
67606846
\indextext{operator!relational!defaulted}%
6761-
\indextext{operator!equality!defaulted}%
6762-
\indextext{operator!inequality!defaulted}%
67636847

67646848
\pnum
6765-
A defaulted relational\iref{expr.rel} or equality\iref{expr.eq} operator function
6849+
A defaulted relational\iref{expr.rel} operator function
67666850
for some operator \tcode{@}
67676851
shall have a declared return type \tcode{bool}.
67686852

@@ -6796,7 +6880,6 @@
67966880
\begin{codeblock}
67976881
struct C {
67986882
friend std::strong_equality operator<=>(const C&, const C&);
6799-
friend bool operator==(const C&, const C&) = default; // OK, returns \tcode{x <=> y == 0}
68006883
bool operator<(const C&) const = default; // OK, function is deleted
68016884
};
68026885
\end{codeblock}

source/overloading.tex

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,18 +1072,14 @@
10721072
\end{itemize}
10731073

10741074
\item
1075-
For the
1076-
relational\iref{expr.rel} and
1077-
equality\iref{expr.eq} operators,
1075+
For the relational\iref{expr.rel} operators,
10781076
the rewritten candidates include
10791077
all member, non-member, and built-in candidates
10801078
for the operator \tcode{<=>}
10811079
for which the rewritten expression
10821080
\tcode{(x <=> y) @ 0} is well-formed using that \tcode{operator<=>}.
10831081
For the
1084-
relational\iref{expr.rel},
1085-
equality\iref{expr.eq},
1086-
and
1082+
relational\iref{expr.rel} and
10871083
three-way comparison\iref{expr.spaceship}
10881084
operators,
10891085
the rewritten candidates also include
@@ -1093,6 +1089,18 @@
10931089
for the operator \tcode{<=>}
10941090
for which the rewritten expression
10951091
\tcode{0 @ (y <=> x)} is well-formed using that \tcode{operator<=>}.
1092+
For the \tcode{!=} operator\iref{expr.eq},
1093+
the rewritten candidates
1094+
include all member, non-member, and built-in candidates
1095+
for the operator \tcode{==}
1096+
for which the rewritten expression \tcode{(x == y)} is well-formed
1097+
when contextually converted to \tcode{bool} using that operator \tcode{==}.
1098+
For the equality operators,
1099+
the rewritten candidates also include a synthesized candidate,
1100+
with the order of the two parameters reversed,
1101+
for each member, non-member, and built-in candidate for the operator \tcode{==}
1102+
for which the rewritten expression \tcode{(y == x)} is well-formed
1103+
when contextually converted to \tcode{bool} using that operator \tcode{==}.
10961104
\begin{note}
10971105
A candidate synthesized from a member candidate has its implicit
10981106
object parameter as the second parameter, thus implicit conversions
@@ -1151,15 +1159,26 @@
11511159
\end{example}
11521160

11531161
\pnum
1154-
If a rewritten candidate
1155-
is selected by overload resolution for an operator \tcode{@},
1162+
If a rewritten candidate is selected by overload resolution
1163+
for a relational or three-way comparison operator \tcode{@},
11561164
\tcode{x @ y}
11571165
is interpreted as the rewritten expression:
11581166
\tcode{0 @ (y <=> x)}
11591167
if the selected candidate is a synthesized candidate
11601168
with reversed order of parameters,
11611169
or \tcode{(x <=> y) @ 0} otherwise,
11621170
using the selected rewritten \tcode{operator<=>} candidate.
1171+
If a rewritten candidate is selected by overload resolution
1172+
for a \tcode{!=} operator,
1173+
\tcode{x != y} is interpreted as \tcode{(y == x) ?\ false :\ true}
1174+
if the selected candidate is a synthesized candidate
1175+
with reversed order of parameters, or
1176+
\tcode{(x == y) ?\ false :\ true} otherwise,
1177+
using the selected rewritten \tcode{operator==} candidate.
1178+
If a rewritten candidate is selected by overload resolution
1179+
for an \tcode{==} operator,
1180+
\tcode{x == y} is interpreted as \tcode{(y == x) ?\ true :\ false}
1181+
using the selected rewritten \tcode{operator==} candidate.
11631182

11641183
\pnum
11651184
If a built-in candidate is selected by overload resolution, the

source/templates.tex

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,8 @@
371371
shall have one of the following (optionally cv-qualified) types:
372372

373373
\begin{itemize}
374-
\item a type that is literal,
375-
has strong structural equality\iref{class.compare.default},
376-
has no \tcode{mutable} or \tcode{volatile} subobjects,
377-
and in which if there is a defaulted member \tcode{operator<=>},
378-
then it is declared public,
374+
\item a literal type that
375+
has strong structural equality\iref{class.compare.default},
379376

380377
\item an lvalue reference type,
381378

@@ -418,7 +415,7 @@
418415
\end{note}
419416
\begin{example}
420417
\begin{codeblock}
421-
struct A { friend auto operator<=>(const A&, const A&) = default; };
418+
struct A { friend bool operator==(const A&, const A&) = default; };
422419
template<const X& x, int i, A a> void f() {
423420
i++; // error: change of template-parameter value
424421

@@ -1282,7 +1279,7 @@
12821279

12831280
struct A {
12841281
constexpr A(const char*) {}
1285-
friend auto operator<=>(const A&, const A&) = default;
1282+
friend bool operator==(const A&, const A&) = default;
12861283
};
12871284

12881285
X<A, "Pyrophoricity"> z; // OK, string literal is a constructor argument to \tcode{A}
@@ -1947,7 +1944,7 @@
19471944
have the same type and value
19481945
after conversion to the type of the \grammarterm{template-parameter},
19491946
where they are considered to have the same value if they compare equal
1950-
with \tcode{operator<=>}, and}
1947+
with the \tcode{==} operator\iref{expr.eq}, and}
19511948
\item {their corresponding template \grammarterm{template-argument}{s} refer
19521949
to the same template.}
19531950
\end{itemize}

0 commit comments

Comments
 (0)