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-11


1862. Determining “corresponding members” for friendship

Section: 13.7.5  [temp.friend]     Status: CD5     Submitter: Richard Smith     Date: 2014-02-13

[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.

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 (13.10.3.6 [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]