Skip to content

CWG2844 [over.match.oper] The algorithm for enumerating a finite set of built-in candidates is underspecified #362

Description

@t3nsor

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 function F ([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 names F, and
  • accept operand types to which the given operand or operands can be converted according to [over.best.ics], and
  • [...]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions