The program is ill-formed in C++20 and onwards as explained here in this stackoverflow question's answer. In the above you'll find answer for pre and post C++20. It's just that not all compilers have implemented/applied this change yet. Demo. Only gcc correctly rejects this in C++20 while and msvc and clang both accepts this and looks like they have not yet made this change in their implementation.

On Thu, 18 Jan 2024 at 13:14, Stephan Bergmann via Std-Discussion <std-discussion@lists.isocpp.org> wrote:
My naive understanding is that

> emplate<typename T> struct S { S<T>(); };

is not well-formed:  [class.ctor.general]/1.2 requires that:

"otherwise, in a member-declaration that belongs to the
member-specification of a class or class template, the id-expression is
the injected-class-name (11.1) of the immediately-enclosing entity;"

(which is the case here), and [class.pre]/2 defines that:

"The class-name is also bound in the scope of the class (template)
itself; this is known as the injected-class-name."

and [class.pre]/1 requires that:

"A class declaration where the class-name in the class-head-name is a
simple-template-id shall be an explicit specialization (13.9.4) or a
partial specialization (13.7.6)."

(which is not the case here).

Yet, what puzzles me is that compilers generally seem to accept the
above (see <https://godbolt.org/z/P83Psv7nx>, where the failure produced
by GCC -std=c++20 looks more like it mis-parses this than that it
genuinely wants to reject this as not well-formed).  What am I missing?
--
Std-Discussion mailing list
Std-Discussion@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion