https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87464
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|normal |enhancement Last reconfirmed| |2022-01-02 Status|UNCONFIRMED |NEW Ever confirmed|0 |1 --- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> --- Reduced: template<bool, typename T> struct enable_if { }; template<typename T> struct enable_if<true, T> { using type = T; }; template<typename T> struct is_const { static constexpr bool value = false; }; template<typename T> struct is_const<const T> { static constexpr bool value = true; }; template<typename T> struct SfinaeTest { SfinaeTest() = default; SfinaeTest(const SfinaeTest&) = default; template<typename TT, typename enable_if< !is_const<TT>::value, int>::type = 0> SfinaeTest(const SfinaeTest<TT>& other) { } }; int main () { SfinaeTest<int> p; SfinaeTest<const int> c; SfinaeTest<int> b_c( c); // expected error. Extra gcc-error: see L:13 } GCC prints two errors, one is the substitution failure error. Clang only prints one, for the invalid constructor call for b_c. Clang has a special case for enable_if constraints, where it prints the boolean condition: <source>:14:4: note: candidate template ignored: requirement '!is_const<const int>::value' was not satisfied [with TT = const int] If we rename the enable_if template, Clang still doesn't show an error, but is closer to GCC's wording: template<bool, typename T> struct require { }; template<typename T> struct require<true, T> { using type = T; }; template<typename T> struct is_const { static constexpr bool value = false; }; template<typename T> struct is_const<const T> { static constexpr bool value = true; }; template<typename T> struct SfinaeTest { SfinaeTest() = default; SfinaeTest(const SfinaeTest&) = default; template<typename TT, typename require< !is_const<TT>::value, int>::type = 0> SfinaeTest(const SfinaeTest<TT>& other) { } }; int main () { SfinaeTest<int> p; SfinaeTest<const int> c; SfinaeTest<int> b_c( c); // expected error. Extra gcc-error: see L:15 } Now clang's note for the template constructor says: <source>:14:4: note: candidate template ignored: substitution failure [with TT = const int]: no type named 'type' in 'require<false, int>' So the only real difference is that gcc prints the cause of the substitution failure as an error.