Since this is tagged language-lawyer
, lets see what the standard has to say.
From [class.ctor.gen], emphasis added:
A declarator declares a constructor if it is a function declarator
([dcl.fct]) of the form ptr-declarator ( parameter-declaration-clause
) noexcept-specifieropt attribute-specifier-seqopt where the
ptr-declarator consists solely of an id-expression, an optional
attribute-specifier-seq, and optional surrounding parentheses, and the
id-expression has one of the following forms:
(1.1) in a friend declaration ([class.friend]), the id-expression is a qualified-id that names a constructor ([class.qual]);
(1.2) 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 ([class.pre]) of the immediately-enclosing
entity;
(1.3) otherwise, the id-expression is a qualified-id whose unqualified-id is the injected-class-name of its lookup context.
For the subject of why a name alias is not valid to declare constructor, especially (1.2) is of relevance. It states that the id-expression is the injected-class-name [..]. The latter is defined in [class.pre]:
- A class is a type. Its name becomes a class-name ([class.name]) within its scope.
[..]
- The class-name is also bound in the scope of the class (template) itself; this is known as the injected-class-name.
For purposes of access checking, the injected-class-name is treated as if it were a public member name. [..]
This states very plainly, that the injected-class-name is exactly the name used to declare the class in the first place. There is no allowance in the wording for aliases.
This follows the same mechanism that you see in a class template:
template <typename T> class C { C foo(); };
Now, there is no class named C
, C
is a template, so you would normally expect to have to say C<T> foo();
. But as stated in [class.pre], a class-name is introduced in the scope of the class definition which refers to the actual type. So, even if there is no class C
anywhere, the class-name C
can be used as a shorthand for C<T>
and in the case of constructors and destructors, is the only way to refer to it because their declaration does not allow you to use any type-id, but only class-name.