title: Template default type vs default value
body: <p>This question follows a <a href="https://stackoverflow.com/q/40250368/1460794">previous one</a>.</p>
  
  <hr>
  
  <h2>Case 1: Default type</h2>
  
  <p>The following program does not compile and reports <code>error C2995: 'T foo(void)': function template has already been defined</code>:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  
  template &lt; typename T, typename = std::enable_if_t&lt; std::is_integral&lt;T&gt;::value&gt; &gt;
  T foo() { std::cout &lt;&lt; "integral" &lt;&lt; std::endl; return T(); }
  
  template &lt; typename T, typename = std::enable_if_t&lt; !std::is_integral&lt;T&gt;::value&gt; &gt;
  T foo() { std::cout &lt;&lt; "non-integral" &lt;&lt; std::endl; return T(); }
  
  int main() {
      foo&lt;int&gt;();
      foo&lt;float&gt;();
  }
  </code></pre>
  
  <p>Each of the templates are <em>alternately</em> used and ignored (SFINAE), by the two <code>foo</code> instantiations. So I assume the compiler at some point sees:</p>
  
  <pre><code>template &lt; typename T, typename = void &gt;
  T foo() { std::cout &lt;&lt; "integral" &lt;&lt; std::endl; return T(); }
  
  template &lt; typename T, typename = void &gt;
  T foo() { std::cout &lt;&lt; "non-integral" &lt;&lt; std::endl; return T(); }
  </code></pre>
  
  <p>Both definitions are the same and the error is somewhat understandable. Maybe less understandable is why the compiler hadn't assigned different internal function names by this point.</p>
  
  <hr>
  
  <h2>Case 2: Default value</h2>
  
  <p>Now, the program can be fixed by, rather than using default types, we use default values:</p>
  
  <pre><code>template &lt; typename T, std::enable_if_t&lt; std::is_integral&lt;T&gt;::value&gt;* = nullptr &gt;
  T foo() { std::cout &lt;&lt; "integral" &lt;&lt; std::endl; return T(); }
  
  template &lt; typename T, std::enable_if_t&lt; !std::is_integral&lt;T&gt;::value&gt;* = nullptr &gt;
  T foo() { std::cout &lt;&lt; "non-integral" &lt;&lt; std::endl; return T(); }
  </code></pre>
  
  <p>Here, following the same procedure, I derive:</p>
  
  <pre><code>template &lt; typename T, void* = nullptr &gt;
  T foo() { std::cout &lt;&lt; "integral" &lt;&lt; std::endl; return T(); }
  
  template &lt; typename T, void* = nullptr &gt;
  T foo() { std::cout &lt;&lt; "non-integral" &lt;&lt; std::endl; return T(); }
  </code></pre>
  
  <p>Which, had that been the substitution, would have had the same definition and would not have compiled. So clearly the compiler is not doing that, or if it is, it doesn't stop there and ends up with something like:</p>
  
  <pre><code>int foo_int() { std::cout &lt;&lt; "integral" &lt;&lt; std::endl; return int(); }
  
  float foo_float() { std::cout &lt;&lt; "non-integral" &lt;&lt; std::endl; return float(); }
  
  int main() {
      foo_int();
      foo_float();
  }
  </code></pre>
  
  <hr>
  
  <p>Why does the compiler manage to get two different functions in the second case, but not the first?</p>
  
  <p>What algorithm does the standard specify for interpreting template default types vs. default values? </p>