A using-alias-directive introduces an identifier that serves as an alias for a namespace or type within the immediately enclosing compilation unit or namespace body.
Within member declarations in a compilation unit or namespace body that contains a using-alias-directive, the identifier introduced by the using-alias-directive can be used to reference the given namespace or type. For example:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }
Here, within member declarations in the N3
namespace, A
is an alias for N1.N2.A
, and thus class N3.B
derives from class N1.N2.A
. The same effect can be obtained by creating an alias R
for N1.N2
and then referencing R.A
:
namespace N3 { using R = N1.N2; class B: R.A {} }
The identifier of a using-alias-directive must be unique within the declaration space of the compilation unit or namespace that immediately contains the using-alias-directive. For example:
namespace N3 { class A {} } namespace N3 { using A = N1.N2.A; // Error, A already exists }
Here, N3
already contains a member A
, so it is an error for a using-alias-directive to use that identifier. It is likewise an error for two or more using-alias-directives in the same compilation unit or namespace body to declare aliases by the same name.
A using-alias-directive makes an alias available within a particular compilation unit or namespace body, but it does not contribute any new members to the underlying declaration space. In other words, a using-alias-directive is not transitive but rather affects only the compilation unit or namespace body in which it occurs. In the example
namespace N3 { using R = N1.N2; } namespace N3 { class B: R.A {} // Error, R unknown }
the scope of the using-alias-directive that introduces R
only extends to member declarations in the namespace body in which it is contained, and R
is thus unknown in the second namespace declaration. However, placing the using-alias-directive in the containing compilation unit causes the alias to become available within both namespace declarations:
using R = N1.N2; namespace N3 { class B: R.A {} } namespace N3 { class C: R.A {} }
Just like regular members, names introduced by using-alias-directives are hidden by similarly named members in nested scopes. In the example
using R = N1.N2; namespace N3 { class R {} class B: R.A {} // Error, R has no member A }
the reference to R.A
in the declaration of B
causes an error because R
refers to N3.F
, not N1.N2
.
The order in which using-alias-directives are written has no significance, and resolution of the namespace-or-type-name referenced by a using-alias-directive is neither affected by the using-alias-directive itself nor by other using-directives in the immediately containing compilation unit or namespace body. In other words, the namespace-or-type-name of a using-alias-directive is resolved as if the immediately containing compilation unit or namespace body had no using-directives. In the example
namespace N1.N2 {} namespace N3 { using R1 = N1; // OK using R2 = N1.N2; // OK using R3 = R1.N2; // Error, R1 unknown }
the last using-alias-directive is in error because it is not affected by the first using-alias-directive.
A using-alias-directive can create an alias for any namespace or type, including the namespace within which it appears and any namespace or type nested within that namespace.
Accessing a namespace or type through an alias yields exactly the same result as accessing the namespace or type through its declared name. In other words, given
namespace N1.N2 { class A {} } namespace N3 { using R1 = N1; using R2 = N1.N2; class B { N1.N2.A a; // refers to N1.N2.A R1.N2.A b; // refers to N1.N2.A R2.A c; // refers to N1.N2.A } }
the names N1.N2.A
, R1.N2.A
, and R2.A
are completely equivalent and all refer to the class whose fully qualified name is N1.N2.A
.