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

7 Expressions [expr]

7.5 Primary expressions [expr.prim]

7.5.5 Names [expr.prim.id]

7.5.5.1 General [expr.prim.id.general]

If an id-expression E denotes a non-static non-type member of some class C at a point where the current class ([expr.prim.this]) is X and

the id-expression is transformed into a class member access expression using (*this) as the object expression.

If this transformation occurs in the predicate of a precondition assertion of a constructor of Xor a postcondition assertion of a destructor of X, the expression is ill-formed.

[Note 2:

If C is not X or a base class of X, the class member access expression is ill-formed.

Also, if the id-expression occurs within a static or explicit object member function, the class member access is ill-formed.

— _end note_]

This transformation does not apply in the template definition context ([temp.dep.type]).

[Example 1: struct C { bool b; C() pre(b) pre(&this->b) pre(sizeof(b) > 0); }; — _end example_]

If an id-expression E denotes a member M of an anonymous union ([class.union.anon]) U:

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

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

[Note 4:

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 5: template<typename T> struct A { static void f(int) requires false;};void g() { A<int>::f(0); void (*p1)(int) = A<int>::f; decltype(A<int>::f)* p2 = nullptr; }

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

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

— _end example_]

— _end note_]

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

The terminal name of a construct is the component name of that construct that appears lexically last.

[Note 3:

If E is not declared mutable, the type of such an identifier will typically be const qualified.

— _end note_]

Otherwise, if the unqualified-idnames a coroutine parameter, the type of the expression is that of the copy of the parameter ([dcl.fct.def.coroutine]), and the result is that copy.

Otherwise, if the unqualified-idnames a result binding ([dcl.contract.res]) attached to a function _f_with return type U,

Otherwise, if the unqualified-idappears in the predicate of a contract assertion C ([basic.contract]) and the entity is

then the type of the expression is const T.

[Example 1: int n = 0;struct X { bool m(); };struct Y { int z = 0;void f(int i, int* p, int& r, X x, X* px) pre (++n) pre (++i) pre (++(*p)) pre (++r) pre (x.m()) pre (px->m()) pre ([=,&i,*this] mutable { ++n; ++i; ++p; ++r; ++this->z; ++z; int j = 17;[&]{ int k = 34;++i; ++j; ++k; }();return true;}());template <int N, int& R, int* P> void g() pre(++N) pre(++R) pre(++(*P)); int h() post(r : ++r) post(r: [=] mutable { ++r; return true;}());int& k() post(r : ++r); }; — _end example_]

Otherwise, 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.

In all other cases, the type of the expression is the type of the entity.

[Note 4:

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 xvalue if it is move-eligible (see below); an lvalue if the entity is a function, variable, structured binding ([dcl.struct.bind]), result binding ([dcl.contract.res]), data member, or template parameter object; and a prvalue otherwise ([basic.lval]); it is a bit-field if the identifier designates a bit-field.

If an id-expression Eappears in the predicate of a function contract assertion attached to a function _f_and denotes a function parameter of _f_and the implementation introduces any temporary objects to hold the value of that parameter as specified in [class.temporary],

If an id-expression Enames a result binding in a postcondition assertion and the implementation introduces any temporary objects to hold the result object as specified in [class.temporary], and the postcondition assertion is sequenced before the initialization of the result object ([expr.call]),E refers to the most recently initialized such temporary object.

[Example 2: void f() { float x, &r = x;[=]() -> decltype((x)) { decltype(x) y1; decltype((x)) y2 = y1; decltype(r) r1 = y1; decltype((r)) r2 = y2; return y2;};[=](decltype((x)) y) { decltype((x)) z = x; };[=] { [](decltype((x)) y) {}; [x=1](decltype((x)) y) { decltype((x)) z = x; };};} — _end example_]

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

The component names of a qualified-id are those of its nested-name-specifier and unqualified-id.

A declaration that uses a declarative nested-name-specifiershall be a friend declaration or inhabit a scope that contains the entity being redeclared or specialized.

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

If a nested-name-specifier Nis declarative and has a simple-template-id with a template argument list Athat involves a template parameter, let T be the template nominated by N without A.

T shall be a class template.

If the nested-name-specifier is not declarative, the entity shall not be a template.

If Q appears in the predicate of a contract assertion C ([basic.contract]) and the entity is

then the type of the expression is const T.

Otherwise, the type of the expression is the type of the result.

The result is an lvalue if the member is

and a prvalue otherwise.

7.5.5.5 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 1: 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_]