https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101113
--- Comment #3 from David Mazieres <gcc at nospam dot scs.stanford.edu> --- (In reply to TC from comment #2) > https://eel.is/c++draft/class.copy.ctor#5 > > I don't think this code is valid. The constraint (which isn't checked until > overload resolution time anyway) can't suppress the outright ill-formedness > of the declaration. Admittedly, 11.4.5.3/5 makes no mention of constraints: A declaration of a constructor for a class X is ill-formed if its first parameter is of type cv X and either there are no other parameters or else all other parameters have default arguments. A member function template is never instantiated to produce such a constructor signature. - https://timsong-cpp.github.io/cppwp/n4868/class.copy.ctor#5 On the other hand, suppressed functions should not participate in overload resolution. Here's some normative language to the same effect 12.4.3/3: Second, for a function to be viable, if it has associated constraints ([temp.constr.decl]), those constraints shall be satisfied ([temp.constr.constr]). - https://timsong-cpp.github.io/cppwp/n4868/over.match.viable#3 So here's another example that doesn't involve 11.4.5.3/5: #include <type_traits> template<typename T> struct S2 { static T *fn() requires (!std::is_reference_v<T>) { return nullptr; } static std::nullptr_t fn() requires std::is_reference_v<T> { return {}; } }; void f() { auto p = S2<int&>::fn(); } $ g++ -std=c++20 -c -o constructor.o constructor.cc constructor.cc: In instantiation of 'struct S2<int&>': constructor.cc:11:20: required from here constructor.cc:4:13: error: forming pointer to reference type 'int&' 4 | static T *fn() requires (!std::is_reference_v<T>) { return nullptr; } | ^~ make: *** [<builtin>: constructor.o] Error 1 So I guess your argument is that there's a certain level of well-formedness required even before the constraints can be evaluated, and an X::X(X) method is as non-sensical as a type like "int&*". That seems like a reasonable position, though I wish the standard were more explicit. I apologize for wasting your time if this was a bogus bug report. For the record, in case the closed bug report comes up in anyone's web search, an easy fix is to rely on the fact that templates won't be instantiated to bad copy constructors: template<bool B> struct S { S() {} template<bool B2> S(S<B2>) requires B2 {} }; S<false> sf; S<true> st;