title: undefined reference to `operator<<(std::ostream&, /* class with non-type template parameters */&)'
body: <p>For a homework assignment, I have to make a class with non-type template parameters and then add <code>std::</code>(<code>i</code>/<code>o</code>)<code>stream</code> operators to it. However when I try to compile clang++ gives a linker error:</p>
  
  <pre class="lang-sh prettyprint-override"><code>$ clang++ -o foo ./*.cpp -std=c++11 -Wall -Wextra -Wpedantic -Wconversion -Wnon-virtual-dtor
  /tmp/16_15-8cda65.o: In function `main':
  main.cpp:(.text+0x108): undefined reference to `operator&lt;&lt;(std::ostream&amp;, Screen&lt;9ul, 9ul&gt; const&amp;)'
  clang: error: linker command failed with exit code 1 (use -v to see invocation)
  </code></pre>
  
  <p>I am aware that template declarations and definitions have to be in the same translation unit, and there are plenty of questions &amp; answers here that point that out.</p>
  
  <p>My abridged code is as follows:</p>
  
  <p>main.cpp:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;iostream&gt;
  
  #include "Screen.h"
  
  int main()
  {
      Screen&lt;9,9&gt; smile =
      {
          {0,0,0,1,1,1,0,0,0},
          {0,1,1,0,0,0,1,1,0},
          {0,1,0,0,0,0,0,1,0},
          {1,0,0,1,0,1,0,0,1},
          {1,0,0,0,0,0,0,0,1},
          {1,0,1,0,0,0,1,0,1},
          {0,1,0,1,1,1,0,1,0},
          {0,1,1,0,0,0,1,1,0},
          {0,0,0,1,1,1,0,0,0}
      };
  
      std::cout &lt;&lt; smile;
  
      return 0;
  }
  </code></pre>
  
  <p>Screen.h:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#ifndef SCREEN_H
  #define SCREEN_H
  
  #include &lt;iostream&gt;
  #include &lt;array&gt;
  #include &lt;initializer_list&gt;
  #include &lt;cstddef&gt;
  
  template &lt;std::size_t W, std::size_t H&gt;
  class Screen
  {
      /////////////
      // FRIENDS //
      /////////////
  
      friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, const Screen&lt;W,H&gt;&amp;);
  
      public:
  
          // declarations of ctors, public members, etc.
  
      private:
  
          //////////
          // DATA //
          //////////
  
          std::array&lt;std::array&lt;bool,W&gt;,H&gt; pixels;
  };
  
  /////////////////
  // NON-MEMBERS //
  /////////////////
  
  // ostream operator
  template &lt;std::size_t W, std::size_t H&gt;
  std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, const Screen&lt;W,H&gt;&amp;);
  
  #include "Screen_impl.h"
  #endif
  </code></pre>
  
  <p>Screen_impl.h:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#ifndef SCREEN_IMPL_H
  #define SCREEN_IMPL_H
  
  #include &lt;iostream&gt;
  #include &lt;array&gt;
  #include &lt;algorithm&gt;
  #include &lt;stdexcept&gt;
  #include &lt;initializer_list&gt;
  #include &lt;cstddef&gt;
  
  // definitions...
  
  /////////////////
  // NON-MEMBERS //
  /////////////////
  
  // ostream operator
  template &lt;std::size_t W, std::size_t H&gt;
  std::ostream&amp; operator&lt;&lt;(std::ostream&amp; lhs, const Screen&lt;W,H&gt;&amp; rhs)
  {
      for (auto y = rhs.pixels.cbegin(); y &lt; rhs.pixels.cend(); ++y)
      {
          for (auto x = y-&gt;cbegin(); x &lt; y-&gt;cend(); ++x)
          {
              if (*x)
                  lhs &lt;&lt; '#';
              else
                  lhs &lt;&lt; ' ';
          }
  
          lhs &lt;&lt; std::endl;
      }
  
      return lhs;
  }
  
  #endif
  </code></pre>