[expr.prim.id] (original) (raw)

7 Expressions [expr]

7.5 Primary expressions [expr.prim]

7.5.4 Names [expr.prim.id]

id-expression: unqualified-id qualified-id

An id-expression that denotes a non-static data member or non-static member function of a class can only be used:

A potentially-evaluated id-expressionthat denotes an immediate function ([dcl.constexpr]) shall appear only

For an id-expression that denotes an overload set, overload resolution is performed to select a unique function ([over.match], [over.over]).

[ Note

:

A program cannot refer to a function with a trailing requires-clausewhose constraint-expression is not satisfied, because such functions are never selected by overload resolution.

[ Example

:

template struct A { static void f(int) requires false; }

void g() { A::f(0);
void (p1)(int) = A::f;
decltype(A::f)
p2 = nullptr;
}

In each case, the constraints of f are not satisfied.

In the declaration of p2, those constraints are required to be satisfied even thoughf is an unevaluated operand.

end example

]

end note

]

7.5.4.1 Unqualified names [expr.prim.id.unqual]

unqualified-id: identifier operator-function-id conversion-function-id literal-operator-id ~ type-name ~ decltype-specifier template-id

[ Note

:

Within the definition of a non-static member function, anidentifier that names a non-static member is transformed to a class member access expression ([class.mfct.non-static]).

end note

]

The result is the entity denoted by the identifier.

If the entity is a local entity and naming it from outside of an unevaluated operand within the declarative region where the unqualified-id appears would result in some intervening lambda-expressioncapturing it by copy ([expr.prim.lambda.capture]), the type of the expression is the type of a class member access expression ([expr.ref]) naming the non-static data member that would be declared for such a capture in the closure object of the innermost such intervening lambda-expression.

[ Note

:

If that lambda-expression is not declared mutable, the type of such an identifier will typically be const qualified.

end note

]

The type of the expression is the type of the result.

[ Note

:

If the entity is a template parameter object for a template parameter of type T ([temp.param]), the type of the expression is const T.

end note

]

[ Note

:

The type will be adjusted as described in [expr.type]if it is cv-qualified or is a reference type.

end note

]

The expression is an lvalue if the entity is a function, variable, structured binding ([dcl.struct.bind]), data member, or template parameter object and a prvalue otherwise ([basic.lval]); it is a bit-field if the identifier designates a bit-field.

[ Example

:

void f() { float x, &r = x; [=] { decltype(x) y1;
decltype((x)) y2 = y1;

decltype(r) r1 = y1;        
decltype((r)) r2 = y2;      

}; }

end example

]

7.5.4.2 Qualified names [expr.prim.id.qual]

qualified-id: nested-name-specifier template unqualified-id

nested-name-specifier: :: type-name :: namespace-name :: decltype-specifier :: nested-name-specifier identifier :: nested-name-specifier template simple-template-id ::

A nested-name-specifier that denotes a class, optionally followed by the keyword template ([temp.names]), and then followed by the name of a member of either that class ([class.mem]) or one of its base classes, is aqualified-id; [class.qual] describes name lookup for class members that appear in qualified-ids.

The result is the member.

The type of the result is the type of the member.

The result is an lvalue if the member is a static member function or a data member and a prvalue otherwise.

[ Note

:

A class member can be referred to using a qualified-id at any point in its potential scope ([basic.scope.class]).

end note

]

Wheretype-name ​::​~ type-name is used, the two type-names shall refer to the same type (ignoring cv-qualifications); this notation denotes the destructor of the type so named ([expr.prim.id.dtor]).

The nested-name-specifier ​::​ names the global namespace.

A nested-name-specifier that names anamespace, optionally followed by the keywordtemplate ([temp.names]), and then followed by the name of a member of that namespace (or the name of a member of a namespace made visible by ausing-directive), is aqualified-id; [namespace.qual] describes name lookup for namespace members that appear in qualified-ids.

The result is the member.

The type of the result is the type of the member.

The result is an lvalue if the member is a function, a variable, or a structured binding ([dcl.struct.bind]) and a prvalue otherwise.

A nested-name-specifier that denotes anenumeration, followed by the name of an enumerator of that enumeration, is a qualified-idthat refers to the enumerator.

The result is the enumerator.

The type of the result is the type of the enumeration.

The result is a prvalue.

Otherwise, it is looked up in the context in which the entire qualified-id occurs.

In each of these lookups, only names that denote types or templates whose specializations are types are considered.

7.5.4.3 Destruction [expr.prim.id.dtor]

An id-expression that denotes the destructor of a type Tnames the destructor of Tif T is a class type ([class.dtor]), otherwise the id-expression is said to name a pseudo-destructor.

[ Example

:

struct C { }; void f() { C * pc = new C; using C2 = C; pc->C::C2();
C().C::
C();
using T = int; 0 .T::T();
0.T::
T();
}

end example

]