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
[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 declareddependent type to be a friendof 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 thereofa 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 generatedif 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>::Dill-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]