title: Confusion with hard error in SFINAE
body: <p>With regards to the following code (<a href="https://wandbox.org/permlink/nhx4pheijpTF1ohf" rel="noreferrer">https://wandbox.org/permlink/nhx4pheijpTF1ohf</a> reproduced below for convenience)</p>
  
  <pre><code>#include &lt;type_traits&gt;
  #include &lt;utility&gt;
  
  namespace foo_name {
  template &lt;typename T&gt;
  void foo();
  template &lt;&gt;
  void foo&lt;int&gt;();
  
  template &lt;typename T&gt;
  struct c_size;
  template &lt;&gt;
  struct c_size&lt;int&gt; : public std::integral_constant&lt;int, 1&gt; {};
  } // namespace foo_name
  
  template &lt;typename Type&gt;
  class Foo {
  public:
      template &lt;typename T&gt;
      static decltype(auto) impl(T&amp;&amp; t) {
          using foo_name::foo;
          return foo(std::forward&lt;T&gt;(t));
      }
  };
  
  class Something {};
  
  template &lt;typename Type, typename T = std::decay_t&lt;Type&gt;&gt;
  using EnableIfHasFoo = std::void_t&lt;
      decltype(Foo&lt;T&gt;::impl(std::declval&lt;T&gt;())),
      decltype(foo_name::c_size&lt;Type&gt;::value)&gt;;
  
  template &lt;typename Type, typename = std::void_t&lt;&gt;&gt;
  class Test {};
  template &lt;typename Type&gt;
  class Test&lt;Type, EnableIfHasFoo&lt;Type&gt;&gt; {};
  
  int main() {
      static_cast&lt;void&gt;(Test&lt;Something&gt;{});
  }
  </code></pre>
  
  <p>The code above exits with an error because the instantiation of <code>Foo&lt;T&gt;::impl()</code> causes a hard error and is not usable in a SFINAE context.  But the strange thing here is that when you switch the order of things in the <code>void_t</code> in <code>EnableIfHasFoo</code> (to the following <a href="https://wandbox.org/permlink/at1KkeCraNwHGmUI" rel="noreferrer">https://wandbox.org/permlink/at1KkeCraNwHGmUI</a>), it will compile</p>
  
  <pre><code>template &lt;typename Type, typename T = std::decay_t&lt;Type&gt;&gt;
  using EnableIfHasFoo = std::void_t&lt;
      decltype(foo_name::c_size&lt;Type&gt;::value),
      decltype(Foo&lt;T&gt;::impl(std::declval&lt;T&gt;()))&gt;;
  </code></pre>
  
  <p>Now the questions are</p>
  
  <ol>
  <li>Why does the code initially not compile?  The instantiation of <code>Foo&lt;T&gt;::impl()</code> is in context of the substitution, so it should work?</li>
  <li>Substituting <code>foo_name::foo(T)</code> in place of the first argument to <code>void_t</code> will make it compile (see <a href="https://wandbox.org/permlink/g3NaPFZxdUPBS7oj" rel="noreferrer">https://wandbox.org/permlink/g3NaPFZxdUPBS7oj</a>), why?  How does adding one extra layer of indirection make the situation different?</li>
  <li>Why does the order in <code>void_t</code> make a difference, does the compiler short circuit the expressions within the type pack?</li>
  </ol>