title: undefined reference for overloaded cout
body: <p>I was trying if I could replace my code for 2-, 3- and 4--dimensional vectors into 1 class, so instead of having <code>vec2&lt;T&gt;</code>, <code>vec3&lt;T&gt;</code> and <code>vec4&lt;T&gt;</code>, use <code>vecN&lt;typenameT,unsignedS&gt;</code>.</p>
  <p>That seems to work well but the overloaded <code>cout</code> function for printing the vectors gives an <code>undefined reference</code> error. I cannot see what I'm doing differently than the usual:</p>
  <p>(minimised) class <code>vectors.hpp</code>:</p>
  <pre><code>#include&lt;vector&gt;
  #include&lt;iostream&gt;
  #include&lt;ranges&gt;
  
  template &lt;typename T, unsigned S&gt;
  class vecN {
    template &lt;typename U&gt; friend std::ostream&amp; operator&lt;&lt; ( std::ostream&amp; out, const vecN&lt;U,S&gt;&amp; v);
    template &lt;typename U&gt; friend std::istream&amp; operator&gt;&gt; ( std::istream&amp;  in,       vecN&lt;U,S&gt;&amp; v);
  protected:
    std::vector&lt;T&gt; 
    data;
  public:
    vecN ( T* xyz ): data ( S ) { std::copy (xyz, xyz+S, data.begin() ); }
  };
  
  // non-members of vecN for vecN
  template &lt;typename T, unsigned S&gt;
  std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, const vecN&lt;T,S&gt;&amp; v) { 
      out &lt;&lt; &quot;( &quot;;
      std::copy(v, std::ostream_iterator&lt;char&gt;(out, &quot;, &quot;));
      out &lt;&lt; &quot;\b\b )&quot;; // use two ANSI backspace characters '\b' to overwrite final &quot;, &quot;
      return out; 
  }
  
  template &lt;typename T, unsigned S&gt;
  std::istream&amp; operator&gt;&gt;(std::istream&amp; in , vecN&lt;T,S&gt; &amp;v) { 
      for ( auto i : std::views::iota(0u, S) )
          in &gt;&gt; v.data[i]; 
      return in;
  }
  
  // aliases for 2-, 3- and 4-dimensional vectors
  template &lt;typename T&gt;
  using vec2 = vecN&lt;T,2&gt;;
  
  template &lt;typename T&gt;
  using vec3 = vecN&lt;T,3&gt;;
  
  template &lt;typename T&gt;
  using vec4 = vecN&lt;T,4&gt;;
  </code></pre>
  <p>Test file <code>main.cpp</code>:</p>
  <pre><code>#include &quot;vectors.hpp&quot;
  int main() {  
    float v[2] = { 10, 20 };
    vec2&lt;float&gt; v2_1 ( v );  
    std::cout &lt;&lt; &quot;vector v2_1 \n&quot; &lt;&lt; v2_1 &lt;&lt; &quot;\n&quot;;  
    return 0;  
  }
  </code></pre>
  <p>When I compile them with:</p>
  <pre><code>g++ -std=c++20 -o test main.cpp vectors.hpp 
  </code></pre>
  <p>then I get the error</p>
  <pre><code>in function `main':
  main.cpp:(.text+0x6a): undefined reference to `std::ostream&amp; operator&lt;&lt; &lt;float&gt;(std::ostream&amp;, vecN&lt;float, 2u&gt; const&amp;)'
  collect2: error: ld returned 1 exit status
  </code></pre>
  <p>But the compiled code for this vector type (float values, size 2) should end up in the <code>test</code> binary, shouldn't it? The types and values are determined correctly, but it does not seem to include the code?</p>