This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-11-18


2797. Meaning of "corresponds" for rewritten operator candidates

Section: 12.2.2.3  [over.match.oper]     Status: review     Submitter: Corentin Jabot     Date: 2023-09-17     Liaison: EWG

Subclause 12.2.2.3 [over.match.oper] paragraph 4 specifies:

A non-template function or function template F named operator== is a rewrite target with first operand o unless a search for the name operator!= in the scope S from the instantiation context of the operator expression finds a function or function template that would correspond (6.4.1 [basic.scope.scope]) to F if its name were operator==, where S is the scope of the class type of o if F is a class member, and the namespace scope of which F is a member otherwise. A function template specialization named operator== is a rewrite target if its function template is a rewrite target.

The meaning of "corresponds" has changed with paper P0847 such that this example from the Working Paper is now ill-formed:

  struct B {
    bool operator==(const B&);
  };
  struct C : B {
    C();
    C(B);
    bool operator!=(const B&);
  };
  bool c1 = B() == C();    // was OK, now ill-formed

The reason is that the definition of "corresponds" now also considers the object parameters, which are different in the example above.

Possible resolution [SUPERSEDED]:

  1. Change and split in 6.4.1 [basic.scope.scope] paragraph 3 as follows:

    ...

    Two functions have corresponding non-object signatures if they have the same non-object-parameter-type-list. Two function templates have corresponding non-object signatures if their template-parameter-lists have the same length, their corresponding template-parameter s are equivalent, and they have equivalent non-object-parameter-type-lists and return types (if any), and, if both are non-static members, they have corresponding object parameters. Two functions or function templates have corresponding signatures if they have corresponding non-object signatures and, if both are non-static members, they have corresponding object parameters.

  2. Change in 6.4.1 [basic.scope.scope] paragraph 4 as follows:

    Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
    • either is a using-declarator , or
    • one declares a type (not a typedef-name) and the other declares a variable, non-static data member other than of an anonymous union (11.5.2 [class.union.anon]), enumerator, function, or function template, or
    • each declares a function or function template and they do not declare corresponding overloads.
    Two function or function template declarations declare corresponding overloads if:
    • both declare functions with the same non-object-parameter-type-list, equivalent (13.7.7.2 [temp.over.link]) trailing requires-clauses (if any, except as specified in 13.7.5 [temp.friend]), and, if both are non-static members, they have corresponding object parameters, corresponding signatures or both declare function templates with corresponding signatures and equivalent template-heads and trailing requires-clauses (if any).
    • both have equivalent (13.7.7.2 [temp.over.link]) template-heads and trailing requires-clauses (if any, except as specified in 13.7.5 [temp.friend]).
  3. Change in 12.2.2.3 [over.match.oper] paragraph 4 as follows:

    A non-template function or function template F named operator== is a rewrite target with first operand o unless a search for the name operator!= in the scope S from the instantiation context of the operator expression finds a function or function template F2 such that would correspond F and F2 have corresponding non-object signatures (6.4.1 [basic.scope.scope]) to F if its name were operator==, where S is the scope of the class type of o if F is a class member, and the namespace scope of which F is a member otherwise. A function template specialization named operator== is a rewrite target if its function template is a rewrite target.

CWG 2023-10-06

CWG raised the question to EWG whether the special rule that allows the example in this issue for backward compatibility should be extended to member functions with explicit object parameters. This is tracked via paper issue 1645.

EWG 2024-03-18

EWG has no consensus to extend the rules to explicit object parameters.

Possible resolutionv [SUPERSEDED]:

  1. Change and split in 6.4.1 [basic.scope.scope] paragraph 3 as follows:

    ...

    Two functions have corresponding non-object signatures if they have the same non-object-parameter-type-list. Two function templates have corresponding non-object signatures if their template-parameter-lists have the same length, their corresponding template-parameter s are equivalent, and they have equivalent non-object-parameter-type-lists and return types (if any), and, if both are non-static members, they have corresponding object parameters. Two functions or function templates have corresponding signatures if they have corresponding non-object signatures and, if both are non-static members, they have corresponding object parameters.

  2. Change in 6.4.1 [basic.scope.scope] paragraph 4 as follows:

    Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
    • either is a using-declarator , or
    • one declares a type (not a typedef-name) and the other declares a variable, non-static data member other than of an anonymous union (11.5.2 [class.union.anon]), enumerator, function, or function template, or
    • each declares a function or function template and they do not declare corresponding overloads.
    Two function or function template declarations declare corresponding overloads if:
    • both declare functions with the same non-object-parameter-type-list, equivalent (13.7.7.2 [temp.over.link]) trailing requires-clauses (if any, except as specified in 13.7.5 [temp.friend]), and, if both are non-static members, they have corresponding object parameters, corresponding signatures or both declare function templates with corresponding signatures and equivalent template-heads and trailing requires-clauses (if any).
    • both have equivalent (13.7.7.2 [temp.over.link]) template-heads and trailing requires-clauses (if any, except as specified in 13.7.5 [temp.friend]).
  3. Change in 12.2.2.3 [over.match.oper] paragraph 4 as follows:

    A non-template function or function template F named operator== is a rewrite target with first operand o unless a search for the name operator!= in the scope S from the instantiation context of the operator expression finds a function or function template F2 such that would correspond F2 is an implicit object member function and F and F2 have corresponding non-object signatures (6.4.1 [basic.scope.scope]) to F if its name were operator==, where S is the scope of the class type of o if F is a class member, and the namespace scope of which F is a member otherwise. A function template specialization named operator== is a rewrite target if its function template is a rewrite target.

CWG 2024-11-18

Subclause 9.9 [namespace.udecl] paragraph 11 needs to change. Limit to both F and F2 being implicit object member functions.

Possible resolution:

  1. Change and split in 6.4.1 [basic.scope.scope] paragraph 3 as follows:

    ...

    Two functions have corresponding non-object signatures if they have the same non-object-parameter-type-list. Two function templates have corresponding non-object signatures if their template-parameter-lists have the same length, their corresponding template-parameter s are equivalent, and they have equivalent non-object-parameter-type-lists and return types (if any), and, if both are non-static members, they have corresponding object parameters. Two functions or function templates have corresponding signatures if they have corresponding non-object signatures and, if both are non-static members, they have corresponding object parameters.

  2. Change in 6.4.1 [basic.scope.scope] paragraph 4 as follows:

    Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
    • either is a using-declarator , or
    • one declares a type (not a typedef-name) and the other declares a variable, non-static data member other than of an anonymous union (11.5.2 [class.union.anon]), enumerator, function, or function template, or
    • each declares a function or function template and they do not declare corresponding overloads.
    Two function or function template declarations declare corresponding overloads if:
    • both declare functions with the same non-object-parameter-type-list, equivalent (13.7.7.2 [temp.over.link]) trailing requires-clauses (if any, except as specified in 13.7.5 [temp.friend]), and, if both are non-static members, they have corresponding object parameters, corresponding signatures or both declare function templates with corresponding signatures and equivalent template-heads and trailing requires-clauses (if any).
    • both have equivalent (13.7.7.2 [temp.over.link]) template-heads and trailing requires-clauses (if any, except as specified in 13.7.5 [temp.friend]).
  3. Change in 9.9 [namespace.udecl] paragraph 11 as follows:

    The set of declarations named by a using-declarator that inhabits a class C does not include member functions and member function templates of a base class that, when declared in C, would correspond to (and thus would conflict with) a declaration of a function or function template in C.
  4. Change in 12.2.2.3 [over.match.oper] paragraph 4 as follows:

    A non-template function or function template F named operator== is a rewrite target with first operand o unless F is not an implicit object function and search for the name operator!= in the scope S from the instantiation context of the operator expression finds a function or function template F2 such that would correspond F2 is an implicit object member function and F and F2 have corresponding non-object signatures (6.4.1 [basic.scope.scope]) to F if its name were operator==, where S is the scope of the class type of o if F is a class member, and the namespace scope of which F is a member otherwise. A function template specialization named operator== is a rewrite target if its function template is a rewrite target.