This is an error in MSVC; clang and gcc are right.
The problem is that SFINAE only happens when overload resolution is allowed, not earlier. I mean, if a function is poorly formed even before you called it, this is a mistake.
If you use S<true> , for example, an instance of the entire class is created. It will look something like this:
struct S_true { template<typename = void> S() {} template<typename = > S(int) {} };
As you can see, the second constructor is completely poorly formed, it is not a correct definition, because there is no type found (due to std::enable_if ). So SFINAE can't even hit, the class definition is poorly formed and diagnosed.
You need to make the template parameter b part of the list of template parameters for both constructors (look at @bolov answer).
source share