Skip to content

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

Open
@t3nsor

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions