Determining “corresponding members” for friendship
13.7.5 [temp.friend]
Richard Smith

Created on 2014-02-13.00:00:00 last changed 2 months ago


Date: 2017-10-15.00:00:00

Proposed resolution (October, 2017):

Change 13.7.5 [temp.friend] paragraph 4 as follows:

A template friend declaration may declare a member of a class template may be declared dependent type to be a friend of a non-template class. The friend declaration shall declare a function or specify a type with an elaborated-type-specifier, in either case with a nested-name-specifier ending with a simple-template-id, C, whose template-name names a class template. The template parameters of the template friend declaration shall be deducible from C ( [temp.deduct.type]). In this case, the corresponding member of every specialization of the primary class template and class template partial specializations thereof a member of a specialization S of the class template is a friend of the class granting friendship. For explicit specializations and specializations of partial specializations, the corresponding member is the member (if any) that has the same name, kind (type, function, class template, or function template), template parameters, and signature as the member of the class template instantiation that would otherwise have been generated if deduction of the template parameters of C from S succeeds, and substituting the deduced template arguments into the friend declaration produces a declaration that would be a valid redeclaration of the member of the specialization. [Example:

  template<class T> struct A {
    struct B { };
    void f();
    struct D {
      void g();
    T h();
    template<T U> T i();
  template<> struct A<int> {
    struct B { };
    int f();
    struct D {
      void g();
    template<int U> int i();
  template<> struct A<float*> {
    int *h();
  class C {
    template<class T> friend struct A<T>::B;      // grants friendship to A<int>::B even though
                                                  // it is not a specialization of A<T>::B
    template<class T> friend void A<T>::f();      // does not grant friendship to A<int>::f()
                                                  // because its return type does not match
    template<class T> friend void A<T>::D::g();   // does not grant friendship to A<int>::D::g()
                                                  // because A<int>::D is not a specialization of A<T>::D ill-formed, A<T>::D does not end with a simple-template-id
    template<class T> friend int *A<T*>::h();     // grants friendship to A<int*>::h() and A<float*>::h()
    template<class T> template<T U>               // grants friendship to instantiations of A<T>::i() and to A<int>::i()
      friend T A<T>::i();                         // and thereby to all specializations of those function templates

end example]

Date: 2017-11-15.00:00:00

[Accepted as a DR at the November, 2017 meeting.]

During the discussion of issue 1804, it was noted that the process of determining whether a member of an explicit or partial specialization corresponds to a member of the primary template is not well specified. In particular, it should be clarified that the primary template should not be instantiated during this process; instead, the template arguments from the specialization should simply be substituted into the member declaration.

Date User Action Args
2020-12-15 00:00:00adminsetstatus: dr -> cd5
2018-02-27 00:00:00adminsetmessages: + msg6119
2018-02-27 00:00:00adminsetstatus: drafting -> dr
2014-07-07 00:00:00adminsetstatus: open -> drafting
2014-02-13 00:00:00admincreate