[basic.lookup.qual] (original) (raw)
6 Basics [basic]
6.5 Name lookup [basic.lookup]
6.5.3 Qualified name lookup [basic.lookup.qual]
The name of a class or namespace member or enumerator can be referred to after the:: scope resolution operator ([expr.prim.id.qual]) applied to anested-name-specifier that denotes its class, namespace, or enumeration.
If a:: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types.
If the name found does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed.
[ Example
:
class A {
public:
static int n;
};
int main() {
int A;
A::n = 42;
A b;
}
— end example
]
[ Note
:
Multiply qualified names, such as N1::N2::N3::n, can be used to refer to members of nested classes ([class.nest]) or members of nested namespaces.
— end note
]
In a declaration in which the declarator-id is aqualified-id, names used before the qualified-idbeing declared are looked up in the defining namespace scope; names following the qualified-id are looked up in the scope of the member's class or namespace.
[ Example
:
class X { }; class C { class X { }; static const int number = 50; static X arr[number]; }; X C::arr[number];
— end example
]
A name prefixed by the unary scope operator :: ([expr.prim.id.qual]) is looked up in global scope, in the translation unit where it is used.
The name shall be declared in global namespace scope or shall be a name whose declaration is visible in global scope because of ausing-directive ([namespace.qual]).
The use of ::allows a global name to be referred to even if its identifier has beenhidden.
[ Example
:
struct C {
typedef int I;
};
typedef int I1, I2;
extern int* p;
extern int* q;
p->C::I::I();I2();
q->I1::
struct A {
A();
};
typedef A AB;
int main() {
AB* p;
p->AB::AB();
}
— end example
]
6.5.3.1 Class members [class.qual]
The name shall represent one or more members of that class or of one of its base classes ([class.derived]).
[ Note
:
For example, the constructor is not an acceptable lookup result in anelaborated-type-specifier so the constructor would not be used in place of the injected-class-name.
— end note
]
Such a constructor name shall be used only in the declarator-id of a declaration that names a constructor or in a using-declaration.
[ Example
:
struct A { A(); }; struct B: public A { B(); };
A::A() { } B::B() { }
B::A ba;
A::A a;
struct A::A a2;
— end example
]
A class member name hidden by a name in a nested declarative region or by the name of a derived class member can still be found if qualified by the name of its class followed by the :: operator.
6.5.3.2 Namespace members [namespace.qual]
For a namespace X and name m, the namespace-qualified lookup set is defined as follows: Let be the set of all declarations of m in X and the inline namespace set ofX ([namespace.def]) whose potential scope ([basic.scope.namespace]) would include the namespace in which m is declared at the location of the nested-name-specifier.
If is not empty, is ; otherwise, is the union of for all namespaces nominated by using-directives inX and its inline namespace set.
Given X::m (where X is a user-declared namespace), or given ::m (where X is the global namespace), if is the empty set, the program is ill-formed.
Otherwise, if has exactly one member, or if the context of the reference is a using-declaration, is the required set of declarations of m.
Otherwise if the use ofm is not one that allows a unique declaration to be chosen from, the program is ill-formed.
[ Example
:
int x; namespace Y { void f(float); void h(int); }
namespace Z { void h(double); }
namespace A { using namespace Y; void f(int); void g(int); int i; }
namespace B { using namespace Z; void f(char); int i; }
namespace AB { using namespace A; using namespace B; void g(); }
void h() { AB::g();
AB::f(1);
AB::f('c');
AB::x++;
AB::i++;
AB::h(16.8);
}
— end example
]
[ Note
:
The same declaration found more than once is not an ambiguity (because it is still a unique declaration).
[ Example
:
namespace A { int a; }
namespace B { using namespace A; }
namespace C { using namespace A; }
namespace BC { using namespace B; using namespace C; }
void f()
{
BC::a++;
}
namespace D { using A::a; }
namespace BD { using namespace B; using namespace D; }
void g()
{
BD::a++;
}
— end example
]
— end note
]
[ Example
:
Because each referenced namespace is searched at most once, the following is well-defined:
namespace B { int b; }
namespace A { using namespace B; int a; }
namespace B { using namespace A; }
void f()
{
A::a++;
B::a++;
A::b++;
B::b++;
}
— end example
]
During the lookup of a qualified namespace member name, if the lookup finds more than one declaration of the member, and if one declaration introduces a class name or enumeration name and the other declarations introduce either the same variable, the same enumerator, or a set of functions, the non-type name hides the class or enumeration name if and only if the declarations are from the same namespace; otherwise (the declarations are from different namespaces), the program is ill-formed.
[ Example
:
namespace A { struct x { }; int x; int y; }
namespace B { struct y { }; }
namespace C {
using namespace A;
using namespace B;
int i = C::x;
int j = C::y;
}
— end example
]
[ Example
:
namespace A { namespace B { void f1(int); } using namespace B; } void A::f1(int){ }
— end example
]
[ Example
:
namespace A { namespace B { void f1(int); } }
namespace C { namespace D { void f1(int); } }
using namespace A; using namespace C::D; void B::f1(int){ }
— end example
]