title: Function template overload resolution with a pointer argument
body: <p>The following code demonstrates the core of a C++ template metaprogramming pattern I have been using to determine whether a type <code>T</code> is an instantiation of a specific class template:</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  template&lt;class A, class B&gt;
  struct S{};
  
  template&lt;class A, class B&gt;
  constexpr bool isS(const S&lt;A,B&gt;*) {return true;}
  
  template&lt;class T&gt;
  constexpr bool isS(const T*) {return false;}
  
  int main() {
    S&lt;int,char&gt; s;
    std::cout&lt;&lt;isS(&amp;s)&lt;&lt;std::endl;
    return 0;
  }
  </code></pre>
  
  <p>It features two overloads of a <code>constexpr</code> function template <code>isS</code>, and it outputs <code>1</code>, as expected. If I remove the pointer from the second <code>isS</code>, i.e. replace it with</p>
  
  <pre><code>template&lt;class T&gt;
  constexpr bool isS(const T) {return false;}
  </code></pre>
  
  <p>the program unexpectedly outputs <code>0</code>. If both versions of <code>isS</code> make it through to the overload resolution phase of compilation, then the output implies that the compiler is choosing the second overload. I have tested this under GCC, Clang and vc++ using the online compilers <a href="http://rextester.com/l/cpp_online_compiler_visual" rel="nofollow noreferrer">here</a>, and they all produce the same result. Why does this happen? </p>
  
  <p>I have read Herb Sutter's <a href="http://www.gotw.ca/publications/mill17.htm" rel="nofollow noreferrer">"Why Not Specialize Function Templates"</a> article several times, and it seems that both <code>isS</code> functions should be considered to be base templates. If this is so, then it is a question of which one is the most specialised. Going by intuition and <a href="https://stackoverflow.com/a/4435618/1292784">this answer</a>, I would expect the first <code>isS</code> to be the most specialised, because <code>T</code> can match every instantiation of <code>S&lt;A,B&gt;*</code>, and there are many possible instantiations of <code>T</code> that cannot match <code>S&lt;A,B&gt;*</code>. I'd like to locate the paragraph in the working draft that defines this behaviour, but I'm not entirely sure what phase of compilation is causing the problem. Is it something to do with <em>"14.8.2.4 Deducing template arguments during partial ordering"</em>?</p>
  
  <p>This issue is particularly surprising given that the following code, in which the first <code>isS</code> takes a reference to <code>const S&lt;A,B&gt;</code> and the second takes a <code>const T</code>, outputs the expected value <code>1</code>:</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  template&lt;class A, class B&gt;
  struct S{};
  
  template&lt;class A, class B&gt;
  constexpr bool isS(const S&lt;A,B&gt;&amp;) {return true;}
  
  template&lt;class T&gt;
  constexpr bool isS(const T) {return false;}
  
  int main() {
    S&lt;int,char&gt; s;
    std::cout&lt;&lt;isS(s)&lt;&lt;std::endl;
    return 0;
  }
  </code></pre>
  
  <p>So the problem seems to be something to do with how pointers are treated.</p>