title: Template partial specialization for integral non-type parameters and non-integral non-types, difference between g++ and clang
body: <h2>The following is a simple template partial specialization:</h2>
  <pre><code>// #1
  template &lt;typename T, T n1, T n2&gt;
  struct foo { 
      static const char* scenario() {
          return &quot;#1 the base template&quot;;
      }
  };
  
  // #2
  // partial specialization where T is unknown and n1 == n2
  template &lt;typename T, T a&gt;
  struct foo&lt;T, a, a&gt; { 
      static const char* scenario() {
          return &quot;#2 partial specialization&quot;;
      }
  };
  </code></pre>
  <p>The main below gets different results on <code>g++ (6.1)</code> and <code>clang++ (3.8.0)</code>:</p>
  <pre><code>extern const char HELLO[] = &quot;hello&quot;;
  double d = 2.3;
  
  int main() {
      cout &lt;&lt;   foo&lt;int, 1, 2&gt;                    ::scenario() &lt;&lt; endl;                   
      cout &lt;&lt;   foo&lt;int, 2, 2&gt;                    ::scenario() &lt;&lt; endl;                   
      cout &lt;&lt;   foo&lt;long, 3, 3&gt;                   ::scenario() &lt;&lt; endl;                  
      cout &lt;&lt;   foo&lt;double&amp;, d, d&gt;                ::scenario() &lt;&lt; endl;               
      cout &lt;&lt;   foo&lt;double*, &amp;d, &amp;d&gt;              ::scenario() &lt;&lt; endl;             
      cout &lt;&lt;   foo&lt;double*, nullptr, nullptr&gt;    ::scenario() &lt;&lt; endl;   
      cout &lt;&lt;   foo&lt;int*, nullptr, nullptr&gt;       ::scenario() &lt;&lt; endl;      
      cout &lt;&lt;   foo&lt;nullptr_t, nullptr, nullptr&gt;  ::scenario() &lt;&lt; endl; 
      cout &lt;&lt;   foo&lt;const char*, HELLO, HELLO&gt;    ::scenario() &lt;&lt; endl;
  }
  </code></pre>
  <h2>Results on <code>g++</code> and <code>clang++</code></h2>
  <p><code><b>#</b> | <b>The code</b>                          | <b>g++ (6.1)</b>       |  <b>clang++ (3.8.0)</b> |</code><br/>
  <code>1 | foo&lt;int, 1, 2&gt;                    | #1 as expected  |  #1 as expected  |</code><br/>
  <code>2 | foo&lt;int, 2, 2&gt;                    | #2 as expected  |  #2 as expected  |</code><br/>
  <code>3 | foo&lt;long, 3, 3&gt;                   | #2 as expected  |  #2 as expected  |</code><br/>
  <code>4 | foo&lt;double&amp;, d, d&gt;                | #1 -- why?      |  #2 as expected  |</code><br/>
  <code>5 | foo&lt;double*, &amp;d, &amp;d&gt;              | #2 as expected  |  #2 as expected  |</code><br/>
  <code>6 | foo&lt;double*, nullptr, nullptr&gt;    | #2 as expected  |  #1 -- why?      |</code><br/>
  <code>7 | foo&lt;int*, nullptr, nullptr&gt;       | #2 as expected  |  #1 -- why?      |</code><br/>
  <code>8 | foo&lt;nullptr_t, nullptr, nullptr&gt;  | #2 as expected  |  #1 -- why?      |</code><br/>
  <code>9 | foo&lt;const char*, HELLO, HELLO&gt;    | #2 as expected  |  #2 as expected  |</code><br/></p>
  <h2>Which one is right?</h2>
  <p>Code: <a href="https://godbolt.org/z/4GfYqxKn3" rel="noreferrer">https://godbolt.org/z/4GfYqxKn3</a></p>
  <hr />
  <p><sub><strong>EDIT, Dec-2021:</strong></sub></p>
  <p><sub>Along the years since the original post, the results have changed, <a href="https://godbolt.org/z/sadnWrsb9" rel="noreferrer">and were even identical for <code>gcc</code> and <code>clang</code> at a certain point in time</a>, but checking again, <code>g++ (11.2)</code> and <code>clang++ (12.0.1)</code> <a href="https://godbolt.org/z/97ajTMc3e" rel="noreferrer">changed their results on references (case 4), but still differ on it</a>. It seems that currently <code>gcc</code> is getting it all right and <code>clang</code> is wrong on the reference case. </sub></p>
  <p><code><b>#</b> | <b>The code</b>                          | <b>g++ (11.2)</b>      | <b>clang++ (12.0.1)</b> |</code><br/>
  <code>1 | foo&lt;int, 1, 2&gt;                    | #1 as expected  |  #1 as expected  |</code><br/>
  <code>2 | foo&lt;int, 2, 2&gt;                    | #2 as expected  |  #2 as expected  |</code><br/>
  <code>3 | foo&lt;long, 3, 3&gt;                   | #2 as expected  |  #2 as expected  |</code><br/>
  <code>4 | foo&lt;double&amp;, d, d&gt;                | #2 as expected  |  #1 -- why?      |</code><br/>
  <code>5 | foo&lt;double*, &amp;d, &amp;d&gt;              | #2 as expected  |  #2 as expected  |</code><br/>
  <code>6 | foo&lt;double*, nullptr, nullptr&gt;    | #2 as expected  |  #2 as expected  |</code><br/>
  <code>7 | foo&lt;int*, nullptr, nullptr&gt;       | #2 as expected  |  #2 as expected  |</code><br/>
  <code>8 | foo&lt;nullptr_t, nullptr, nullptr&gt;  | #2 as expected  |  #2 as expected  |</code><br/>
  <code>9 | foo&lt;const char*, HELLO, HELLO&gt;    | #2 as expected  |  #2 as expected  |</code><br/></p>