General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
Aqualified name is a name that appears on the right hand side of the scope resolution operator::
(see alsoqualified identifiers).A qualified name may refer to a
If there is nothing on the left hand side of the::
, the lookup considers only declarations inthe global namespace scope. This makes it possible to refer to such names even if they were hidden by a local declaration:
Before name lookup can be performed for the name on the right hand side of::
, lookup must be completed for the name on its left hand side (unless adecltype expression is used, or there is nothing on the left). This lookup, which may be qualified or unqualified, depending on whether there's another::
to the left of that name, considers only namespaces, class types, enumerations, and templates whose specializations are types. If the name found on the left does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed:
struct A{staticint n;}; int main(){int A; A::n=42;// OK: unqualified lookup of A to the left of :: ignores the variable A b;// Error: unqualified lookup of A finds the variable A} template<int>struct B: A{}; namespace N{template<int>void B(); int f(){return B<0>::n;// Error: N::B<0> is not a type}}
When a qualified name is used as adeclarator, thenunqualified lookup of the names used in the same declarator that follow that qualified name, but not the names that precede it, is performed in the scope of the member's class or namespace:
class X{}; constexprint number=100; struct C{class X{};staticconstint number=50;static X arr[number];}; X C::arr[number], brr[number];// Error: look up for X finds ::X, not C::XC::X C::arr[number], brr[number];// OK: size of arr is 50, size of brr is 100
If::
is followed by the character~
that is in turn followed by an identifier (that is, it specifies a destructor or pseudo-destructor), that identifier is looked up in the same scope as the name on the left hand side of::
struct C{typedefint I;}; typedefint I1, I2; externint*p,*q; struct A{ ~A();}; typedef A AB; int main(){ p->C::I::~I();// The name I after ~ is looked up in the same scope as I before ::// (that is, within the scope of C, so it finds C::I) q->I1::~I2();// The name I2 is looked up in the same scope as I1// (that is, from the current scope, so it finds ::I2) AB x; x.AB::~AB();// The name AB after ~ is looked up in the same scope as AB before ::// (that is, from the current scope, so it finds ::AB)}
EnumeratorsIf the lookup of the left-hand side name comes up with anenumeration (either scoped or unscoped), the lookup of the right-hand side must result in an enumerator that belongs that enumeration, otherwise the program is ill-formed. | (since C++11) |
If the lookup of the left hand side name comes up with a class/struct or union name, the name on the right hand side of::
is looked up in the scope of that class (and so may find a declaration of a member of that class or of its base), with the following exceptions:
This section is incomplete Reason: micro-examples for the above |
If the right hand side of::
names the same class as the left hand side, the name designates theconstructor of that class. Such qualified name can only be used in a declaration of a constructor and in theusing-declaration for aninheriting constructor. In those lookups where function names are ignored (that is, when looking up a name on the left of::
, when looking up a name inelaborated type specifier, orbase specifier), the same syntax resolves to the injected-class-name:
struct A{ A();}; struct B: A{ B();}; A::A(){}// A::A names a constructor, used in a declarationB::B(){}// B::B names a constructor, used in a declaration B::A ba;// B::A names the type A (looked up in the scope of B)A::A a;// Error: A::A does not name a type struct A::A a2;// OK: lookup in elaborated type specifier ignores functions// so A::A simply names the class A as seen from within the scope of A// (that is, the injected-class-name)
Qualified name lookup can be used to access a class member that is hidden by a nested declaration or by a derived class. A call to a qualified member function is never virtual:
struct B{virtualvoid foo();}; struct D: B{void foo() override;}; int main(){ D x; B& b= x; b.foo();// Calls D::foo (virtual dispatch) b.B::foo();// Calls B::foo (static dispatch)}
If the name on the left of::
refers to a namespace or if there is nothing on the left of::
(in which case it refers to the global namespace), the name that appears on the right hand side of::
is looked up in the scope of that namespace, except that
namespace N{template<typename T>struct foo{}; struct X{};} N::foo<X> x;// Error: X is looked up as ::X, not as N::X
Qualified lookup within the scope of anamespaceN
first considers all declarations that are located inN
and all declarations that are located in theinline namespace members ofN
(and, transitively, in their inline namespace members). If there are no declarations in that set then it considers declarations in all namespaces named byusing-directives found inN
and in all transitive inline namespace members ofN
. The rules are applied recursively:
int x; namespace Y{void f(float);void h(int);} namespace Z{void h(double);} namespace A{usingnamespace Y;void f(int);void g(int);int i;} namespace B{usingnamespace Z;void f(char);int i;} namespace AB{usingnamespace A;usingnamespace B;void g();} void h(){ AB::g();// AB is searched, AB::g found by lookup and is chosen AB::g(void)// (A and B are not searched) AB::f(1);// First, AB is searched. There is no f// Then, A, B are searched// A::f, B::f found by lookup// (but Y is not searched so Y::f is not considered)// Overload resolution picks A::f(int) AB::x++;// First, AB is searched. There is no x// Then A, B are searched. There is no x// Then Y and Z are searched. There is still no x: this is an error AB::i++;// AB is searched. There is no i// Then A, B are searched. A::i and B::i found by lookup: this is an error AB::h(16.8);// First, AB is searched. There is no h// Then A, B are searched. There is no h// Then Y and Z are searched// Lookup finds Y::h and Z::h. Overload resolution picks Z::h(double)}
It is allowed for the same declaration to be found more than once:
namespace A{int a;} namespace B{usingnamespace A;} namespace D{using A::a;} namespace BD{usingnamespace B;usingnamespace D;} void g(){ BD::a++;// OK: finds the same A::a through B and through D}
This section is incomplete Reason: the rest of N4861 6.5.3.2[namespace.qual], try to shorten their examples |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 215 | C++98 | the name preceding:: must be a class name or namespacename, so template parameters were not allowed there | the name must designate a class, namespace or dependent type |
CWG 318 | C++98 | if the right hand side of:: names the same classas the left hand side, the qualified name was always considered to name the constructor of that class | only name the constructor when acceptable (e.g. not in an elaborated type specifier) |