Title
Instantiation of constrained non-template friends
Status
drafting
Section
13.9.2 [temp.inst]
Submitter
David Friberg

Created on 2022-06-09.00:00:00 last changed 24 months ago

Messages

Date: 2022-11-11.16:02:54

CWG 2022-11-10

The friend definitions should conflict with friend definitions from other instantiations of the same class template, consistent with how non-constrained friends would work. Note that the enclosing dependent class type does not appear in the friend function's signature, which is unusual.

Date: 2022-11-11.16:02:54

Suggested resolution:

  1. Change in 13.7.5 [temp.friend] paragraph 9 as follows:

    A non-template friend declaration with a requires-clause shall be a definition. A friend function template with a constraint that depends on a template parameter from an enclosing template shall be a definition. Such a constrained friend function or function template declaration does not declare the same function or function template as a declaration in inhabiting any other scope.
  2. Change in 13.9.2 [temp.inst] paragraph 17 as follows:

    The type-constraints and requires-clause of a template specialization or member templated function are not instantiated along with the specialization or function itself, even for a member function of a local class; substitution into the atomic constraints formed from them is instead performed as specified in 13.5.3 [temp.constr.decl] and 13.5.2.3 [temp.constr.atomic] when determining whether the constraints are satisfied or as specified in 13.5.3 [temp.constr.decl] when comparing declarations.

    [ Note 7: ... ]

    [ Example 10: ... ]

    [ Example:

      struct Base {};
    
      template<int N>
      struct S : Base {
        friend int foo(Base&) requires (N == 1) { return 1; }  // #1
        friend int foo(Base&) requires (N == 2) { return 3; }  // #2
      };
      S<1> s1;
      S<2> s2;          // OK, no conflict between #1 and #2
      int x = foo(s1);  // OK, selects #1
      int y = foo(s2);  // OK, selects #2
    

    -- end example ]

    [ Example 11: ... ]

Date: 2022-06-15.07:09:09

Consider:

  struct Base {};

  template<int N>
  struct S : public Base {
    friend int foo(Base&) requires (N == 1) { return 1; }
    friend int foo(Base&) requires (N == 2) { return 3; }
  };

  int main() {
    S<1> s1{};
    S<2> s2{};  // #1
  }

The current wording does not seem to cover what happens for this case. In particular, 13.9.2 [temp.inst] paragraph 17 does not cover constrained non-template friends.

See also the Itanium ABI issue 24.

History
Date User Action Args
2022-11-11 16:02:54adminsetmessages: + msg7024
2022-11-11 16:02:54adminsetstatus: open -> drafting
2022-06-15 07:09:09adminsetmessages: + msg6852
2022-06-09 00:00:00admincreate