Description
Full name of submitter: Brian Bi
Reference (section label): [over.match.oper]
Issue description: Consider the following example, which is accepted by Clang, but rejected by GCC:
#include <concepts>
struct S1 {
operator int*() { return nullptr; }
};
struct S2 {
template <class T>
operator T() requires std::same_as<T, int*> {
return nullptr;
}
};
int main() {
S1 s1;
S2 s2;
return s1 - s2;
}
The question is whether the implementation is required to find the built-in candidate std::ptrdiff_t operator-(int*, int*)
, and select that candidate. The problem is that [over.built] specifies that there are an infinite number of built-in candidates, including one of the form std::ptrdiff_t operator-(T*, T*)
for every object type T
. If there are infinitely many built-in candidates, the implementation cannot iterate through all of them to determine whether each candidate is viable.
One plausible approach is: look for non-template conversion functions in each operand of class type. If at least one operand yields a non-empty list of such non-template conversion functions, then consider the built-in candidates that have parameters of types that result from those conversion functions (or can be converted from one of those resulting types by a standard conversion). Under this approach, the code should be accepted. If this is the algorithm we want, we should specify it normatively so that GCC can also implement it.
[over.match.oper]/3.3 restricts the built-in candidate set to those that "accept operand types to which the given operand or operands can be converted according to [over.best.ics]". We can specify the algorithm normatively by restricting this set further.
Suggested resolution: Add a bullet before [over.match.oper]/3.3:
- [...]
- accept the same number of operands, and
- have at least one parameter type to which a standard conversion sequence ([over.ics.scs]) exists from either the corresponding operand E or, in the case where E has a class type, any type
T
specified by a non-template conversion functionF
([class.conv.fct]) that is a member of E's class and would be viable ([over.match.viable]) for a call of the form(
E).
N()
, where N is a hypothetical id-expression that namesF
, and- accept operand types to which the given operand or operands can be converted according to [over.best.ics], and
- [...]