Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Bo provided the <em>reason</em> why this is happening (the type <code>T</code> is not deducible in the call to the nested <code>operator&lt;&lt;</code>. A simple workaround for this, and something that I recommend in general, not only here, is not befriending a template, but rather a single free function. For that you will need to <em>define</em> the function inline:</p> <pre><code>template&lt;typename T&gt; struct classA { struct classB { friend inline std::ostream&amp; operator&lt;&lt; (std::ostream &amp;out, const classB &amp;b) { // definition goes here } }; classB root; friend std::ostream&amp; operator&lt;&lt; (std::ostream &amp;out, const classA&lt;U&gt; &amp;tree) { // definition goes here } }; </code></pre> <p>There are a couple of differences among the two approaches. The most important one is that this approach will have the compiler define a non-templated overload for <code>operator&lt;&lt;</code> for each instantiation of the template, which because it is no longer a template, does not depend on deducing the arguments. Another side effects are that the approach is a little <em>tighter</em> (you are only befriending <em>one</em> function, while in your initial approach you befriended the template and all possible instantiations (which can be used as a loophole to gain access to your class internals). Finally the functions so defined will only be found through ADL, so there are less overloads of <code>operator&lt;&lt;</code> for the compiler to consider when the argument is not <code>ClassA&lt;T&gt;</code> or <code>ClassA&lt;T&gt;::ClassB</code>.</p> <hr> <p><em>How access can be gained with your approach</em></p> <pre><code>namespace { struct intruder { ClassA &amp; ref; intruder( ClassA&amp; r ) : ref(r) {} }; template &lt;&gt; std::ostream&amp; operator&lt;&lt; &lt;intruder&gt;( std::ostream&amp; _, ClassA&lt;intruder&gt; const&amp; i ) { std::cout &lt;&lt; i.ref.private_member &lt;&lt; std::endl; return _; } } </code></pre> <p><em>Alternative</em></p> <p>Alternatively you can befriend a particular specialization of a template. That will solve the <code>intruder</code> problem, as it will only be open to <code>operator&lt;&lt;</code> to <code>ClassA&lt;intruder&gt;</code>, which has a much lesser impact. But this will not solve your particular issue, as the type would still not be deducible.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload