title: SFINAE without void_t (maybe a template specialization question)
body: <p>Sorry for the title, I am not sure about the category of my question.
  I am trying to do an is_incrementable with SFINAE. This works fine, however when I try to understand it more deeply, and when I remove the void_t then the code snippet does not work as expected.</p>
  <p>The original code:</p>
  <pre><code>#include &lt;iostream&gt;
  
  template&lt; typename, typename = void &gt;
  struct is_incrementable : std::false_type { };
  
  template&lt; typename T &gt;
  struct is_incrementable&lt;T,
            std::void_t&lt;decltype( ++std::declval&lt;T&amp;&gt;() )&gt;
  
         &gt; : std::true_type { };
  
  int main()
  {
      std::cout &lt;&lt; is_incrementable&lt;int&gt;::value &lt;&lt; std::endl;  // prints 1
      std::cout &lt;&lt; is_incrementable&lt;std::string&gt;::value &lt;&lt; std::endl;  // prints 0
      return 0;
  }
  </code></pre>
  <p>i)  <code>is_incrementable&lt;int&gt;::value</code> evaluates to <code>is_incrementable&lt;int, void&gt;::value</code> which is the original template class and the specialization, too. In this case the compiler choses the specialized version, so value eguals to 1.
  For the string version, the specialization fails, SFINAE kicks in, so we have the base template only. (value equals to 0)</p>
  <p>ii) When I change the code, and remove the void_t</p>
  <pre><code>template&lt; typename, typename = void &gt; 
  struct is_incrementable : std::false_type { };
  
  template&lt; typename T &gt;
  struct is_incrementable&lt;T,
          decltype( ++std::declval&lt;T&amp;&gt;() )    // void_t is removed              
         &gt; : std::true_type { };
  
  int main()
  {
      std::cout &lt;&lt; is_incrementable&lt;int&gt;::value &lt;&lt; std::endl;  // prints 0
      std::cout &lt;&lt; is_incrementable&lt;std::string&gt;::value &lt;&lt; std::endl;  // prints 0
      return 0;
  }
  </code></pre>
  <p>0 and 0 is printed.
  <code>is_incrementable&lt;int&gt;::value</code> means <code>is_incrementable&lt;int, void&gt;::value</code>, the specialization is
  <code>is_incrementable&lt;int, int&gt;::value</code> (I think), so we use the basic template. For the string the specialization fails anyway.</p>
  <p>My question:
  iii)
  The funny part.
  If now I change the first line to use int as the default type</p>
  <pre><code>#include &lt;iostream&gt;
  
  template&lt; typename, typename = int &gt;  // !!! int is used now
  struct is_incrementable : std::false_type { };
  
  template&lt; typename T &gt;
  struct is_incrementable&lt;T,
          decltype( ++std::declval&lt;T&amp;&gt;() )  // void_t is removed 
         &gt; : std::true_type { };
  
  int main()
  {
      std::cout &lt;&lt; is_incrementable&lt;int&gt;::value &lt;&lt; std::endl;  // prints 0
      std::cout &lt;&lt; is_incrementable&lt;std::string&gt;::value &lt;&lt; std::endl;  // prints 0
      return 0;
  }
  </code></pre>
  <p>then again 0 and 0 are printed.
  Why?
  <code>is_incrementable&lt;int&gt;::value</code> means (I think) <code>is_incrementable&lt;int, int&gt;::value</code>
  and
  <code>decltype( ++std::declval&lt;T&amp;&gt;() )</code>    should be int as well.
  So I think the compiler should use the specialized version. (and 1 should be printed)</p>
  <p>If I remove
  <code>decltype( ++std::declval&lt;T&amp;&gt;() )  </code>
  and write <code>int</code> then 1 and 1 printed (which are the expected print outs).</p>
  <p>Could someone explain me what is happening in iii) please.</p>