title: template class specialization enable_if and default values
body: <p>Given the following</p>
  
  <pre><code>template &lt;typename T, typename Enable=void&gt;
  struct test{};
  
  template &lt;typename T,
      typename std::enable_if&lt; some_trait&lt;T&gt;::value &gt;::type &gt;
  struct test{};
  </code></pre>
  
  <p>assuming <code>some_trait&lt;T&gt;::value</code> is <code>true</code>,  <code>enable_if&lt;T&gt;::type</code> is <code>void</code>, and the specialization is selected.
  However, my query is related to the selection when the follow is the case.</p>
  
  <pre><code>template &lt;typename T,
      typename std::enable_if_t&lt; some_trait&lt;T&gt;::value,T&gt;::type &gt;
  struct test{};
  </code></pre>
  
  <p>When a second non void template parameter for <code>enable_if</code> is provided for <code>::type</code>, the unspecialized template 
  is selected, even when <code>some_trait&lt;T&gt;::value</code> is <code>true</code>, as <code>::type</code> is <code>T</code> instead of <code>void</code>, and so doesn't
  match the default value in the primary template.</p>
  
  <p>My question is where in the standard is the ordering described for which template is chosen, and why is
  the instanciation <code>test&lt;T,void&gt;</code> considered as a better match then <code>test&lt;T,T&gt;</code>.</p>
  
  <p><a href="https://ideone.com/7v4TTS" rel="nofollow noreferrer">https://ideone.com/7v4TTS</a></p>
  
  <p>full sample : </p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  
  template &lt;typename T,typename Enable=void&gt;
  struct test
  {
      const char* value = "Primary";
  };
  
  #if 1// toggle this
  
  template &lt;typename T&gt;
  struct test&lt;T,typename std::enable_if&lt; std::is_same&lt;T,T&gt;::value &gt;::type &gt; 
  {
      const char* value = "Specialization";
  };
  
  #else
  
  template &lt;typename T&gt;                                    
  struct test&lt;T,typename std::enable_if&lt; std::is_same&lt;T,T&gt;::value,T &gt;::type&gt; 
  {                                                          ///  ^    
      const char* value = "Specialization";
  };
  
  #endif
  
  int main() {
      test&lt;int&gt; v;
      std::cout &lt;&lt; v.value &lt;&lt; std::endl;
      return 0;
  }
  </code></pre>