<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    CWG Issue 1862</TITLE>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<STYLE TYPE="text/css">
  INS { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .INS { text-decoration:none; background-color:#D0FFD0 }
  DEL { text-decoration:line-through; background-color:#FFA0A0 }
  .DEL { text-decoration:line-through; background-color: #FFD0D0 }
  @media (prefers-color-scheme: dark) {
    HTML { background-color:#202020; color:#f0f0f0; }
    A { color:#5bc0ff; }
    A:visited { color:#c6a8ff; }
    A:hover, a:focus { color:#afd7ff; }
    INS { background-color:#033a16; color:#aff5b4; }
    .INS { background-color: #033a16; }
    DEL { background-color:#67060c; color:#ffdcd7; }
    .DEL { background-color:#67060c; }
  }
  SPAN.cmnt { font-family:Times; font-style:italic }
</STYLE>
</HEAD>
<BODY>
<P><EM>This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21
  Core Issues List revision 118b.
  See http://www.open-std.org/jtc1/sc22/wg21/ for the official
  list.</EM></P>
<P>2025-09-28</P>
<HR>
<A NAME="1862"></A><H4>1862.
  
Determining &#8220;corresponding members&#8221; for friendship
</H4>
<B>Section: </B>13.7.5&#160; [<A href="https://wg21.link/temp.friend">temp.friend</A>]
 &#160;&#160;&#160;

 <B>Status: </B>CD5
 &#160;&#160;&#160;

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2014-02-13<BR>


<P>[Accepted as a DR at the November, 2017 meeting.]</P>

<P>During the discussion of <A HREF="1804.html">issue 1804</A>, 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.</P>

<P><B>Proposed resolution (October, 2017):</B></P>

<P>Change 13.7.5 [<A href="https://wg21.link/temp.friend#4">temp.friend</A>] paragraph 4 as follows:</P>

<BLOCKQUOTE>

<P>A <INS>template friend declaration may declare a</INS>
member of a <DEL>class template may be declared</DEL>
<INS>dependent type</INS> to be a friend <DEL>of a
non-template class</DEL>. <INS>The friend declaration shall declare a
function or specify a type with an <I>elaborated-type-specifier</I>,
in either case with a <I>nested-name-specifier</I> ending with a
<I>simple-template-id</I>, <I>C</I>, whose <I>template-name</I> names
a class template. The template parameters of the template friend
declaration shall be deducible from <I>C</I>
(13.10.3.6 [<A href="https://wg21.link/temp.deduct.type">temp.deduct.type</A>]).</INS>
In this case, <DEL>the corresponding member of every
specialization of the primary class template and class template partial
specializations thereof</DEL> <INS>a member of a specialization
<I>S</I> of the class template</INS>
is a friend of the class granting friendship<DEL>. 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</DEL>
<INS>if deduction of the template parameters of <I>C</I> from <I>S</I>
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</INS>. [<I>Example:</I>
</P>

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

<P>&#8212;<I>end example</I>]</P>

</BLOCKQUOTE>

<BR><BR>
</BODY>
</HTML>
