title: Explicit specialization of friend function for a class template
body: <p>I was reading litb's answer to a question <a href="https://stackoverflow.com/a/1297622/955273">here</a>, where he details how to create a <strong>specialized friend function of a class template</strong>.</p>
  
  <p>I tried to create an exemplar which did just what he suggests (<em>code at the end</em>):</p>
  
  <pre><code>// use '&lt;&gt;' to specialize the function template with the class template's type
  friend std::ostream&amp; operator&lt;&lt; &lt;&gt;(std::ostream&amp; os, const foo&lt;T&gt;&amp; f)
  </code></pre>
  
  <p>It results in a <strong>compiler error</strong>:</p>
  
  <pre><code>error: defining explicit specialization ‘operator&lt;&lt; &lt;&gt;’ in friend declaration
  </code></pre>
  
  <p>Explicitly declaring the template parameter in the specialization doesn't work either:</p>
  
  <pre><code>friend std::ostream&amp; operator&lt;&lt; &lt;T&gt;(std::ostream&amp; os, const foo&lt;T&gt;&amp; f) // same error
  </code></pre>
  
  <p>On the other hand, changing from using a specialization to use a <strong>friend function template</strong> instead <em>does</em> work:</p>
  
  <pre><code>template&lt;typename U&gt;
  friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const foo&lt;U&gt;&amp; f) // this works
  </code></pre>
  
  <p>So my questions are:</p>
  
  <ul>
  <li>what is causing the first error?</li>
  <li>how can I explicitly specialize the <code>ostream operator</code> for the surrounding class template specialization?</li>
  </ul>
  
  <p><strong>Exemplar code below:</strong></p>
  
  <pre><code>#include &lt;iostream&gt;
  
  // fwd declarations
  template&lt;typename T&gt; struct foo;
  template&lt;typename T&gt; std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, const foo&lt;T&gt;&amp;);
  
  template&lt;typename T&gt;
  struct foo
  {
      foo(T val)
          : _val(val)
      {}
  
      friend std::ostream&amp; operator&lt;&lt; &lt;&gt;(std::ostream&amp; os, const foo&lt;T&gt;&amp; f) // error line
      //template&lt;typename U&gt;
      //friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const foo&lt;U&gt;&amp; f) // this works
      {
          return os &lt;&lt; "val=" &lt;&lt; f._val;
      }
  
      T _val;
  };
  
  
  int main()
  {
      foo&lt;std::string&gt; f("hello world");
      std::cout &lt;&lt; f &lt;&lt; std::endl;
      exit(0);
  }
  </code></pre>