From b66749568bbbf8634b26e8cc8d90aeb2e9a29f59 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 22 Jul 2019 14:12:11 -0700 Subject: [PATCH 1/2] P1630R1 Spaceship needs a tune-up Definition of 'usable function' not added: it was already added by CWG motion 6 (P1186R3). --- source/classes.tex | 48 ++++++++++++++++----------- source/compatibility.tex | 31 ++++++++++++++++++ source/overloading.tex | 71 ++++++++++++++++++++++++---------------- 3 files changed, 101 insertions(+), 49 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index ebbbd07952..53fd8e975e 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -6708,6 +6708,12 @@ \item a friend of \tcode{C} having two parameters of type \tcode{const C\&}. \end{itemize} +\pnum +A defaulted comparison operator function for class \tcode{C} +is defined as deleted if +any non-static data member of \tcode{C} is of reference type or +\tcode{C} is a union-like class\iref{class.union.anon}. + \pnum If the class definition does not explicitly declare an \tcode{==} operator function, @@ -6744,15 +6750,22 @@ given a glvalue \tcode{x} of type \tcode{const C}, either: \begin{itemize} \item - \tcode{C} is a non-class type and \tcode{x <=> x} is a valid expression - of type \tcode{std::strong_ordering} or \tcode{std::strong_equality}, or +\tcode{C} is a non-class type and +\tcode{x <=> x} is a valid expression +of type \tcode{std::strong_ordering} or \tcode{std::strong_equality}, or + \item - \tcode{C} is a class type with an \tcode{==} operator - defined as defaulted in the definition of \tcode{C}, - \tcode{x == x} is well-formed when contextually converted to \tcode{bool}, - all of \tcode{C}'s base class subobjects and non-static data members - have strong structural equality, and - \tcode{C} has no \tcode{mutable} or \tcode{volatile} subobjects. +\tcode{C} is a class type +where all of the following hold: +\begin{itemize} +\item All of \tcode{C}'s base class subobjects and non-static data members +have strong structural equality. +\item \tcode{C} has no mutable or volatile non-static data members. +\item At the end of the definition of \tcode{C}, +overload resolution performed for the expression \tcode{x == x} succeeds and +finds either a friend or public member \tcode{==} operator +that is defined as defaulted in the definition of \tcode{C}. +\end{itemize} \end{itemize} \pnum @@ -6807,15 +6820,12 @@ with parameters \tcode{x} and \tcode{y} is defined as deleted if \begin{itemize} \item - overload resolution\iref{over.match}, as applied to \tcode{x == y} - (also considering synthesized candidates - with reversed order of parameters\iref{over.match.oper}), - results in an ambiguity or a function - that is deleted or inaccessible from the operator function, or + overload resolution\iref{over.match}, as applied to \tcode{x == y}, + does not result in a usable function, or \item - \tcode{x == y} cannot be contextually converted to \tcode{bool}. + \tcode{x == y} is not a prvalue of type \tcode{bool}. \end{itemize} -Otherwise, the operator function yields \tcode{(x == y) ?\ false :\ true}. +Otherwise, the operator function yields \tcode{!(x == y)}. \pnum \begin{example} @@ -6824,7 +6834,7 @@ int i; friend bool operator==(const D& x, const D& y) = default; // OK, returns \tcode{x.i == y.i} - bool operator!=(const D& z) const = default; // OK, returns \tcode{(*this == z) ?\ false :\ true} + bool operator!=(const D& z) const = default; // OK, returns \tcode{!(*this == z)} }; \end{codeblock} \end{example} @@ -6990,10 +7000,8 @@ \begin{itemize} \item overload resolution\iref{over.match}, -as applied to \tcode{x <=> y} -results in an ambiguity -or a function that is deleted or inaccessible from the operator function, -or +as applied to \tcode{x <=> y}, +does not result in a usable function, or \item the operator \tcode{@} diff --git a/source/compatibility.tex b/source/compatibility.tex index bdcd591c17..3a4e167eb9 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -2004,6 +2004,37 @@ }; \end{codeblock} +\rSec2[diff.cpp17.over]{\ref{over}: overloading} + +\diffref{over.match.oper} +\change +Equality and inequality expressions can now find +reversed and rewritten candidates. +\rationale +Improve consistency of equality with three-way comparison +and make it easier to write the full complement of equality operations. +\effect +Equality and inequality expressions between two objects of different types, +where one is convertible to the other, +could invoke a different operator. +Equality and inequality expressions between two objects of the same type +could become ambiguous. +\begin{codeblock} +struct A { + operator int() const; +}; + +bool operator==(A, int); // \#1 +// \#2 is built-in candidate: \tcode{bool operator==(int, int);} +// \#3 is built-in candidate: \tcode{bool operator!=(int, int);} + +int check(A x, A y) { + return (x == y) + // ill-formed; previously well-formed + (10 == x) + // calls \#1, previously selected \#2 + (10 != x); // calls \#1, previously selected \#3 +} +\end{codeblock} + \rSec2[diff.cpp17.temp]{\ref{temp}: templates} \diffref{temp.names} diff --git a/source/overloading.tex b/source/overloading.tex index 2cb76eb615..cd92452641 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -1077,13 +1077,15 @@ that is not a function template specialization. \end{itemize} +\item +The rewritten candidate set is determined as follows: +\begin{itemize} \item For the relational\iref{expr.rel} operators, the rewritten candidates include all member, non-member, and built-in candidates -for the operator \tcode{<=>} -for which the rewritten expression -\tcode{(x <=> y) @ 0} is well-formed using that \tcode{operator<=>}. +for the expression \tcode{x <=> y}. +\item For the relational\iref{expr.rel} and three-way comparison\iref{expr.spaceship} @@ -1092,29 +1094,27 @@ a synthesized candidate, with the order of the two parameters reversed, for each member, non-member, and built-in candidate -for the operator \tcode{<=>} -for which the rewritten expression -\tcode{0 @ (y <=> x)} is well-formed using that \tcode{operator<=>}. +for the expression +\tcode{y <=> x}. +\item For the \tcode{!=} operator\iref{expr.eq}, the rewritten candidates include all member, non-member, and built-in candidates -for the operator \tcode{==} -for which the rewritten expression \tcode{(x == y)} is well-formed -when contextually converted to \tcode{bool} using that operator \tcode{==}. +for the expression \tcode{x == y}. +\item For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, -for each member, non-member, and built-in candidate for the operator \tcode{==} -for which the rewritten expression \tcode{(y == x)} is well-formed -when contextually converted to \tcode{bool} using that operator \tcode{==}. +for each member, non-member, and built-in candidate +for the expression \tcode{y == x}. +\item +For all other operators, the rewritten candidate set is empty. +\end{itemize} \begin{note} A candidate synthesized from a member candidate has its implicit object parameter as the second parameter, thus implicit conversions are considered for the first, but not for the second, parameter. \end{note} -In each case, rewritten candidates are not considered -in the context of the rewritten expression. -For all other operators, the rewritten candidate set is empty. \end{itemize} \pnum @@ -1165,26 +1165,39 @@ \end{example} \pnum -If a rewritten candidate is selected by overload resolution -for a relational or three-way comparison operator \tcode{@}, +If a rewritten \tcode{operator<=>} candidate +is selected by overload resolution +for an operator \tcode{@}, \tcode{x @ y} -is interpreted as the rewritten expression: +is interpreted as \tcode{0 @ (y <=> x)} if the selected candidate is a synthesized candidate with reversed order of parameters, or \tcode{(x <=> y) @ 0} otherwise, using the selected rewritten \tcode{operator<=>} candidate. -If a rewritten candidate is selected by overload resolution -for a \tcode{!=} operator, -\tcode{x != y} is interpreted as \tcode{(y == x) ?\ false :\ true} -if the selected candidate is a synthesized candidate -with reversed order of parameters, or -\tcode{(x == y) ?\ false :\ true} otherwise, -using the selected rewritten \tcode{operator==} candidate. -If a rewritten candidate is selected by overload resolution -for an \tcode{==} operator, -\tcode{x == y} is interpreted as \tcode{(y == x) ?\ true :\ false} -using the selected rewritten \tcode{operator==} candidate. +Rewritten candidates for the operator \tcode{@} +are not considered in the context of the resulting expression. + +\pnum +If a rewritten \tcode{operator==} candidate +is selected by overload resolution +for an operator \tcode{@}, +its return type shall be \cv{} \tcode{bool}, and +\tcode{x @ y} is interpreted as: +\begin{itemize} +\item +if \tcode{@} is \tcode{!=} +and the selected candidate is a synthesized candidate +with reversed order of parameters, +\tcode{!(y == x)}, +\item +otherwise, if \tcode{@} is \tcode{!=}, +\tcode{!(x == y)}, +\item +otherwise (when \tcode{@} is \tcode{==}), +\tcode{y == x}, +\end{itemize} +in each case using the selected rewritten \tcode{operator==} candidate. \pnum If a built-in candidate is selected by overload resolution, the From 5d1bb1c7f8ed44016c38bfeb9797e363d52cfc51 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 1 Aug 2019 20:42:13 -0700 Subject: [PATCH 2/2] [over.match.oper] Replace "member, non-member, and built-in candidates" with "non-rewritten candidates" This simplifies the wording, implicitly explains why we're considering only some candidates, and avoids overtly suggesting that we could ever pick a reversed-parameter-order built-in candidate. --- source/overloading.tex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/overloading.tex b/source/overloading.tex index cd92452641..2e867d6d10 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -1083,7 +1083,7 @@ \item For the relational\iref{expr.rel} operators, the rewritten candidates include -all member, non-member, and built-in candidates +all non-rewritten candidates for the expression \tcode{x <=> y}. \item For the @@ -1093,19 +1093,19 @@ the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, -for each member, non-member, and built-in candidate +for each non-rewritten candidate for the expression \tcode{y <=> x}. \item For the \tcode{!=} operator\iref{expr.eq}, the rewritten candidates -include all member, non-member, and built-in candidates +include all non-rewritten candidates for the expression \tcode{x == y}. \item For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, -for each member, non-member, and built-in candidate +for each non-rewritten candidate for the expression \tcode{y == x}. \item For all other operators, the rewritten candidate set is empty.