Repository navigation
[class.compare.default] p1 The condition of implicitly defining a defaulted comparison operator function CWG2546 #5336
Description
Activity
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
So even if the implicit exception specification is not needed,
decltype(&C::operator<)is ill-formed.IIUC this is a bug of clang. Please report it here.
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
So even if the implicit exception specification is not needed,
decltype(&C::operator<)is ill-formed.IIUC this is a bug of clang. Please report it here.
No, the defaulted function is not deleted.
HasNoLessThan operator <=>(C const&, C const&)is a usable candidate and a rewritten candidate forx < y, as per [class.compare.secondary] p2 and [over.match.oper#3.4]. Instead, I think it is a bug of GCC, which says that defaulted operator function is deleted.Are you explaining why the comment in [class.compare.secondary] p3 is wrong? I believe it's right, extremely.
When the rewritten candidate is found, a nested overload resolution is performed for the written expression and then fails. According to [over.match.general] p4, the rewritten candidate is not usable.
Are you explaining why the comment in [class.compare.secondary] p3 is wrong? I believe it's right, extremely.
When the rewritten candidate is found, a nested overload resolution is performed for the written expression and then fails. According to [over.match.general] p4, the rewritten candidate is not usable.
"the rewritten candidate is not usable" No, it is usable. First,
HasNoLessThan operator <=>(C const&, C const&)is a candidate forx < y, and all operands of the expression can be as the arguments in the call ofHasNoLessThan operator <=>(C const&, C const&)since the operands are of typeconst C. According to [over.match.general] p2 and [over.match.general] p3,HasNoLessThan operator <=>(C const&, C const&)is the unique best viable function. Hence, the overload resolution succeeds.a nested overload resolution is performed for the written expression and then fails.
IMO, overload resolution only considers the candidate itself. It shouldn't consider subsequent interpretation for the expression. The clue is here:
If a rewritten operator<=> candidate is selected by overload resolution for an operator @, x @ y is interpreted as...
That is, only after the overload resolution for the expression
x@yhas succeeded and selectedrewritten operator<=> candidatewill further interpretation be done. [class.compare.secondary] p2 just requires thatoverload resolution ([over.match]), as applied to x @ y, does not result in a usable candidate
It didn't say the reinterpretation of
x < y, in this case, which is(x <=> y) < 0, shall have a usable candidate or be well-formed.
[over.match.general] p1 states that
Overload resolution is a mechanism for selecting the best function to call given a list of expressions that are to be the arguments of the call and a set of candidate functions that can be called based on the context of the call.
For expression
x < y, the set of candidate functions is{ HasNoLessThan operator <=>(C const&, C const&) }as per [over.match.oper] p3 and the list of arguments arex, yas per [over.match.oper] p7. Anyway, the overload resolution can succeed.If the comment is the intent of [class.compare.secondary] p2, it may be improved to
The operator function with parameters x and y is defined as deleted if
- the candidate selected by overload resolution, as applied to
x @ y, is not a rewritten candidate, or
- For expression x @ y, it is ill-formed.
the candidate selected by overload resolution for
x < yisHasNoLessThan operator <=>(C const&, C const&), which is a rewritten candidate, the first bullet is not violated. Since the selected candidate isa rewritten operator<=> candidate, the expressionx < yis interpreted as(x <=> y) < 0, which is ill-formed; the first operand of<has typeHasNoLessThanwhile the second has the typeint, they are not comparable.- the candidate selected by overload resolution, as applied to
a nested overload resolution is performed for the written expression and then fails.
Another example that can prove we shouldn't augment the extent of considering overload resolution for this definition is:
struct HasNoLessThan { operator int(){ return 0; } }; struct C{ friend HasNoLessThan operator <=>(C const&, C const&); bool operator <(C const&) const = default; }; int main(){ using ptr = decltype(&C::operator<); }
Both implementations accept this example. The nested overload resolution will be performed for the operator
<within(x<=>y) < 0. The selected candidate is the built-in one, which would violate the second bullet in [class.compare.secondary] p2. It is not reasonable to augment the extent of the overload resolution.The "selected candidate" in [class.compare.secondary] p2 is
operator <=>, not the second-order overload resolution foroperator<.The fixes in CWG2546 should address this, too.
Reacted by XMH and A. Jiang- changed the title
[-][class.compare.default] p1 The condition of implicitly defining a defaulted comparison operator function[/-][+][class.compare.default] p1 The condition of implicitly defining a defaulted comparison operator function CWG2546[/+]on Mar 7, 2022
[class.compare.default] p1 just says
Consider this example
Since
&C::operator<appears as an unevaluated operand, functionC::operator <is not odr-used by this expression. However, Clang reports a diagnosis that:[except.spec] p11 says
So, It is reasonable to check the definition of the defaulted function. However, we just define two contexts that can cause the implicit definition for the defaulted function. Checking the expressions in the implicit definition is not defined to be odr-used nor constant evaluation of the function. It seems that we lack the case that determines the exception specification of a defaulted comparison operator function.
Improvement: