title: C++ operator << overloading for std::vector with separate declaration / definition ok for template but not for concrete type
body: <p>I want to overload the <code>&lt;&lt;</code> operator to print vectors. This works fine for template arguments <code>vector&lt;T&gt;</code> (with explicit template instantiations) but not for a concrete <code>vector&lt;complex&lt;double&gt;&gt;</code> argument when the code is split into a declaration in foo.h and a definition in foo.cpp.</p>
  
  <p>So while this works:</p>
  
  <pre><code>// foo.h
  
  template &lt; typename T &gt;
  std::ostream&amp; operator &lt;&lt; (std::ostream&amp; os, const std::vector&lt; T &gt;&amp; v);
  
  
  // foo.cpp
  #include "foo.h" // and using directives
  
  template &lt; typename T &gt;
  inline ostream&amp; operator &lt;&lt; ( ostream&amp; os, const vector&lt; T &gt;&amp; v ) 
  {
      os &lt;&lt; "[";
      for (auto vv : v) os &lt;&lt; " " &lt;&lt; vv;
      os &lt;&lt; " ]";
  
      return os;
  }
  
  template ostream&amp; operator &lt;&lt; ( ostream&amp; os, const vector&lt; double &gt;&amp; v); // double
  
  template ostream&amp; operator &lt;&lt; ( ostream&amp; os, const vector&lt; int &gt;&amp; v); // int
  </code></pre>
  
  <p>When adding to the header a <code>vector&lt;complex&lt;double&gt;&gt;</code> argument variant</p>
  
  <pre><code>// foo.h
  std::ostream&amp; operator &lt;&lt; ( std::ostream&amp; os, const std::vector&lt;std::complex&lt;double&gt;&gt;&amp; v)
  </code></pre>
  
  <p>and the implementation to the source</p>
  
  <pre><code>// foo.cpp
  std::ostream&amp; operator &lt;&lt; ( std::ostream&amp; os, const std::vector&lt;std::complex&lt;double&gt;&gt;&amp; v) 
  {   
      os &lt;&lt; "[";
      for (auto vv : v)
          os &lt;&lt; " ( " &lt;&lt; vv.real() &lt;&lt; ((vv.imag() &gt;= 0 ) ? " +" : " ") &lt;&lt; vv.imag() &lt;&lt; "i )";
      os &lt;&lt; " ]";
      return os;
  }
  </code></pre>
  
  <p>I get the error</p>
  
  <blockquote>
    <p>undefined reference to <code>operator&lt;&lt;(std::ostream&amp;, std::vector&lt;std::complex&lt;double&gt;, std::allocator&lt;std::complex&lt;double&gt; &gt; &gt; const&amp;)</code></p>
  </blockquote>
  
  <p>when trying to call that operator</p>
  
  <p><strong>If I move the implementation to the header file, the code works.</strong> </p>
  
  <p>Since the whole type, i.e <code>complex&lt;double&gt;</code> is known, I didn't treat the last operator overload as templated but rather as a "regular" thing (there is no "pattern" to fill in for the compiler, isn't it?) 
  But even when I treat it as a specialized template</p>
  
  <pre><code>template&lt; &gt;
  std::ostream&amp; operator &lt;&lt; ( std::ostream&amp; os, const std::vector&lt;std::complex&lt;double&gt;&gt;&amp; v);
  </code></pre>
  
  <p>it does not work.</p>
  
  <p>The answer to <a href="https://stackoverflow.com/questions/38700941/best-way-to-specialise-operator-for-stdostream-and-stdvector-with-generic">this related question</a> says to simply NOT overload the vector type but it doesn't explain the above mentioned behavior and I am curious about <em>why</em> this happens.</p>