title: Implementation divergence about sfinae on default parameter value
body: <p>I produced a code that has implementation divergence and I want to know which compiler is right and why, or which part of the standard allows those compiler to differ:</p>
  <pre><code>#include &lt;type_traits&gt;
  #include &lt;cstdio&gt;
  
  // Only deleted when the constraint is not met
  template&lt;typename T&gt;
  struct deleted {
      template&lt;typename U = T&gt; requires (not std::is_integral_v&lt;U&gt;)
      deleted() = delete;
  
      template&lt;typename U = T&gt; requires std::is_integral_v&lt;U&gt;
      deleted() {}
  };
  
  struct trigger_error {
      template&lt;typename F&gt;
      operator F () {
          static_assert(not std::is_same_v&lt;F, F&gt;, &quot;Cannot call f with floating point types&quot;);
          return F{};
      }
  };
  
  // Constrained function. Only callabale with integral types
  // When called with something other than integral, display static assert.
  // sfinae still applies even though the static assert is called.
  template&lt;typename T&gt; requires std::is_integral_v&lt;T&gt;
  void f(T) {}
  
  template&lt;typename T&gt; requires (not std::is_integral_v&lt;T&gt;)
  auto f(T, int = trigger_error{}, deleted&lt;T&gt; = {}) {};
  
  // Do sfinae if f is callable. If callable, prints &quot;integrals&quot;
  template&lt;typename T&gt; requires(requires(T t){f(t);})
  auto use_constrains(T) -&gt; void {
      puts(&quot;integrals&quot;);
  }
  
  // Sfinae fails, print &quot;floats&quot; instead
  template&lt;typename T&gt;
  auto use_constrains(T) -&gt; void {
      puts(&quot;floats&quot;);
  }
  
  int main() {
      use_constrains(1);
      //f(1.3); // uncommenting triggers static assert
      use_constrains(1.3);
  }
  </code></pre>
  <p><a href="https://godbolt.org/z/rexhK9TGh" rel="nofollow noreferrer">Live on compiler explorer</a></p>
  <p>To my surprise, the code don't even compiled on Clang and do an hard error on the call to deleted function <code>deleted::deleted()</code>.</p>
  <p>MSVC compiles, but don't do sfinae, and don't do hard error and simply prints <code>&quot;integrals&quot;</code> on both calls.</p>
  <p>Since the three implementations diverges, I wondered who is right and why. Is sfinae applied on the expression of the default value of a parameter?</p>