From 925daa0d6aa8f8c41a291dc3ef75b94569427aa0 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 4 Mar 2019 13:27:15 +0100 Subject: [PATCH 1/5] P1185R2 <=> != == --- source/classes.tex | 133 +++++++++++++++++++++++++++++++++-------- source/overloading.tex | 35 ++++++++--- source/templates.tex | 13 ++-- 3 files changed, 139 insertions(+), 42 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index f4ed78d86f..f344933558 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -6642,28 +6642,51 @@ declared in the \grammarterm{member-specification} of \tcode{C} that is \begin{itemize} -\item a non-static member of \tcode{C} having one parameter of type \tcode{const C\&}, or +\item a non-static const member of \tcode{C} having one parameter of type \tcode{const C\&}, or \item a friend of \tcode{C} having two parameters of type \tcode{const C\&}. \end{itemize} \pnum -\indextext{structural comparison operator|see{operator, structural comparison}}% -A three-way comparison operator for a class type \tcode{C} -is a \defnadj{structural comparison}{operator} -if it is defined as defaulted in the definition of \tcode{C}, -and all three-way comparison operators it invokes -are structural comparison operators. -\indextext{strong structural equality|see{equality, strong structural}}% -A type \tcode{T} -has \defnadj{strong structural}{equality} -if, for a glvalue \tcode{x} of type \tcode{const T}, -\tcode{x <=> x} is a valid expression -of type \tcode{std::strong_ordering} or \tcode{std::strong_equality} -and either does not invoke a three-way comparison operator -or invokes a structural comparison operator. +If the class definition +does not explicitly declare an \tcode{==} operator function, +but declares a defaulted three-way comparison operator function, +an \tcode{==} operator function is declared implicitly +with the same access as the three-way comparison operator function. +The implicitly-declared \tcode{==} operator for a class \tcode{X} +is an inline member and is defined as defaulted in the definition of \tcode{X}. +If the three-way comparison operator function +is declared as a non-static const member, +the implicitly-declared \tcode{==} operator function is a member of the form +\begin{codeblock} +bool X::operator==(const X&) const; +\end{codeblock} +Otherwise, the implicitly-declared \tcode{==} operator function is of the form +\begin{codeblock} +friend bool operator==(const X&, const X&); +\end{codeblock} +The operator is a \tcode{constexpr} function if its definition +would satisfy the requirements for a \tcode{constexpr} function. +\begin{note} +The \tcode{==} operator function is declared implicitly even if +the defaulted three-way comparison operator function is defined as deleted. +\end{note} -\rSec2[class.spaceship]{Three-way comparison} -\indextext{operator!three-way comparison!defaulted}% +\pnum +\indextext{structural comparison operator|see{operator, structural comparison}}% +A type \tcode{C} has \defnadj{strong structural}{equality} if, +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 +\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. +\end{itemize} \pnum The direct base class subobjects of \tcode{C}, @@ -6681,12 +6704,73 @@ derived-to-base conversions\iref{over.best.ics}, class member access expressions\iref{expr.ref}, and array subscript expressions\iref{expr.sub} applied to \tcode{x}. -The type of the expression $\tcode{x}_i$ \tcode{<=>} $\tcode{x}_i$ -is denoted by $\tcode{R}_i$. -It is unspecified -whether virtual base class subobjects are compared more than once. +It is unspecified whether virtual base class subobjects +appear more than once in the expanded list of subobjects. + +\rSec2[class.eq]{Equality operators} +\indextext{operator!equality!defaulted}% +\indextext{operator!inequality!defaulted}% \pnum +A defaulted equality operator\iref{expr.eq} function +shall have a declared return type \tcode{bool}. + +\pnum +A defaulted \tcode{==} operator function for a class \tcode{C} +is defined as deleted +unless, for each $\tcode{x}_i$ in the expanded list of subobjects +for an object \tcode{x} of type \tcode{C}, +$\tcode{x}_i\tcode{ == }\tcode{x}_i$ is a valid expression and +contextually convertible to \tcode{bool}. + +\pnum +The return value \tcode{V} of a defaulted \tcode{==} operator function +with parameters \tcode{x} and \tcode{y} is determined +by comparing corresponding elements $\tcode{x}_i$ and $\tcode{y}_i$ +in the expanded lists of subobjects for \tcode{x} and \tcode{y} +until the first index $i$ +where $\tcode{x}_i\tcode{ == }\tcode{y}_i$ yields a result value which, +when contextually converted to \tcode{bool}, yields \tcode{false}. +If no such index exists, \tcode{V} is \tcode{true}. +Otherwise, \tcode{V} is \tcode{false}. + +\pnum +A defaulted \tcode{!=} operator function for a class \tcode{C} +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 +\item + \tcode{x == y} or \tcode{y == x} + cannot be contextually converted to \tcode{bool}. +\end{itemize} +Otherwise, the operator function yields \tcode{(x == y) ? false : true} +if an operator \tcode{==} with the original order of parameters was selected, +or \tcode{(y == x) ? false : true} otherwise. + +\pnum +\begin{example} +\begin{codeblock} +struct D { + 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} +}; +\end{codeblock} +\end{example} + +\rSec2[class.spaceship]{Three-way comparison} +\indextext{operator!three-way comparison!defaulted}% + +\pnum +Given an expanded list of subobjects for an object \tcode{x} of type \tcode{C}, +the type of the expression $\tcode{x}_i$ \tcode{<=>} $\tcode{x}_i$ +is denoted by $\tcode{R}_i$. If the declared return type of a defaulted three-way comparison operator function is \tcode{auto}, @@ -6756,13 +6840,11 @@ \end{note} \end{itemize} -\rSec2[class.rel.eq]{Other comparison operators} +\rSec2[class.rel]{Relational operators} \indextext{operator!relational!defaulted}% -\indextext{operator!equality!defaulted}% -\indextext{operator!inequality!defaulted}% \pnum -A defaulted relational\iref{expr.rel} or equality\iref{expr.eq} operator function +A defaulted relational\iref{expr.rel} operator function for some operator \tcode{@} shall have a declared return type \tcode{bool}. @@ -6796,7 +6878,6 @@ \begin{codeblock} struct C { friend std::strong_equality operator<=>(const C&, const C&); - friend bool operator==(const C&, const C&) = default; // OK, returns \tcode{x <=> y == 0} bool operator<(const C&) const = default; // OK, function is deleted }; \end{codeblock} diff --git a/source/overloading.tex b/source/overloading.tex index 26a6c0013a..071495eadb 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -1072,18 +1072,14 @@ \end{itemize} \item -For the -relational\iref{expr.rel} and -equality\iref{expr.eq} operators, +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 -relational\iref{expr.rel}, -equality\iref{expr.eq}, -and +relational\iref{expr.rel} and three-way comparison\iref{expr.spaceship} operators, the rewritten candidates also include @@ -1093,6 +1089,18 @@ for the operator \tcode{<=>} for which the rewritten expression \tcode{0 @ (y <=> x)} is well-formed using that \tcode{operator<=>}. +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 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{==}. \begin{note} A candidate synthesized from a member candidate has its implicit object parameter as the second parameter, thus implicit conversions @@ -1151,8 +1159,8 @@ \end{example} \pnum -If a rewritten candidate -is selected by overload resolution for an operator \tcode{@}, +If a rewritten candidate is selected by overload resolution +for a relational or three-way comparison operator \tcode{@}, \tcode{x @ y} is interpreted as the rewritten expression: \tcode{0 @ (y <=> x)} @@ -1160,6 +1168,17 @@ 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. \pnum If a built-in candidate is selected by overload resolution, the diff --git a/source/templates.tex b/source/templates.tex index 9643f0ab24..6ff9d6482b 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -371,11 +371,8 @@ shall have one of the following (optionally cv-qualified) types: \begin{itemize} -\item a type that is literal, -has strong structural equality\iref{class.compare.default}, -has no \tcode{mutable} or \tcode{volatile} subobjects, -and in which if there is a defaulted member \tcode{operator<=>}, -then it is declared public, +\item a type that is literal and + has strong structural equality\iref{class.compare.default}, \item an lvalue reference type, @@ -418,7 +415,7 @@ \end{note} \begin{example} \begin{codeblock} -struct A { friend auto operator<=>(const A&, const A&) = default; }; +struct A { friend bool operator==(const A&, const A&) = default; }; template void f() { i++; // error: change of template-parameter value @@ -1282,7 +1279,7 @@ struct A { constexpr A(const char*) {} - friend auto operator<=>(const A&, const A&) = default; + friend bool operator==(const A&, const A&) = default; }; X z; // OK, string literal is a constructor argument to \tcode{A} @@ -1947,7 +1944,7 @@ have the same type and value after conversion to the type of the \grammarterm{template-parameter}, where they are considered to have the same value if they compare equal -with \tcode{operator<=>}, and} +with \tcode{operator==}, and} \item {their corresponding template \grammarterm{template-argument}{s} refer to the same template.} \end{itemize} From caa5c8aedecdf68cfda4f5d95ec9d20451953117 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 5 Mar 2019 19:05:25 +0100 Subject: [PATCH 2/5] [class.compare.default] Add a note that friends are found by ADL only. --- source/classes.tex | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/classes.tex b/source/classes.tex index f344933558..b5c639d482 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -6664,6 +6664,11 @@ \begin{codeblock} friend bool operator==(const X&, const X&); \end{codeblock} +\begin{note} +Such a friend function is visible +to argument-dependent lookup\iref{basic.lookup.argdep} +only\iref{namespace.memdef}. +\end{note} The operator is a \tcode{constexpr} function if its definition would satisfy the requirements for a \tcode{constexpr} function. \begin{note} From 007c0c1a619417f94c2c4efb57be71c09f2c2870 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 6 Mar 2019 21:32:09 +0100 Subject: [PATCH 3/5] [temp.type] Do not refer to operator==, which excludes built-in ==. --- source/templates.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 6ff9d6482b..e97a4afb3a 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -1944,7 +1944,7 @@ have the same type and value after conversion to the type of the \grammarterm{template-parameter}, where they are considered to have the same value if they compare equal -with \tcode{operator==}, and} +with the \tcode{==} operator\iref{expr.eq}, and} \item {their corresponding template \grammarterm{template-argument}{s} refer to the same template.} \end{itemize} From c0058816fdfe079095ca8717ad692dc2d498d6a3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 11 Mar 2019 20:11:46 -0700 Subject: [PATCH 4/5] [class.eq] Remove redundant repetition of the operator== symmetry rule. --- source/classes.tex | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index b5c639d482..a181523a20 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -6750,12 +6750,9 @@ results in an ambiguity or a function that is deleted or inaccessible from the operator function, or \item - \tcode{x == y} or \tcode{y == x} - cannot be contextually converted to \tcode{bool}. + \tcode{x == y} cannot be contextually converted to \tcode{bool}. \end{itemize} -Otherwise, the operator function yields \tcode{(x == y) ? false : true} -if an operator \tcode{==} with the original order of parameters was selected, -or \tcode{(y == x) ? false : true} otherwise. +Otherwise, the operator function yields \tcode{(x == y) ?\ false :\ true}. \pnum \begin{example} From d69814f61077f7e549ccc39a21fc3b90db4223d6 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 11 Mar 2019 20:12:17 -0700 Subject: [PATCH 5/5] [temp.param] "a type that is literal" -> "a literal type". --- source/templates.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index e97a4afb3a..9d725db851 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -371,7 +371,7 @@ shall have one of the following (optionally cv-qualified) types: \begin{itemize} -\item a type that is literal and +\item a literal type that has strong structural equality\iref{class.compare.default}, \item an lvalue reference type,