7 Expressions [expr]

7.6 Compound expressions [expr.compound]

7.6.1 Postfix expressions [expr.post]

7.6.1.5 Class member access [expr.ref]

A postfix expression followed by a dot . or an arrow ->, optionally followed by the keyword template, and then followed by an id-expression or a splice-expression, is a postfix expression.
[Note 1: 
If the keyword template is used and followed by an id-expression, the unqualified name is considered to refer to a template ([temp.names]).
If a simple-template-id results and is followed by a ​::​, the id-expression is a qualified-id.
— end note]
For a dot that is followed by an expression that designates a static member or an enumerator, the first expression is a discarded-value expression ([expr.context]); if the expression after the dot designates a non-static data member, the first expression shall be a glvalue.
A postfix expression that is followed by an arrow shall be a prvalue having pointer type.
The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the form using a dot.49
The postfix expression before the dot is evaluated;50 the result of that evaluation, together with the id-expression or splice-expression, determines the result of the entire postfix expression.
If the object expression is of scalar type, E2 shall name the pseudo-destructor of that same type (ignoring cv-qualifications) and E1.E2 is a prvalue of type “function of () returning void.
[Note 2: 
This value can only be used for a notional function call ([expr.prim.id.dtor]).
— end note]
Otherwise, the object expression shall be of class type.
The class type shall be complete unless the class member access appears in the definition of that class.
[Note 3: 
The program is ill-formed if the result differs from that when the class is complete ([class.member.lookup]).
— end note]
[Note 4: 
[basic.lookup.qual] describes how names are looked up after the . and -> operators.
— end note]
If E2 is a splice-expression, then let T1 be the type of E1.
E2 shall designate either a member of the T1 or a direct base class relationship (T1, B).
If E2 designates a bit-field, E1.E2 is a bit-field.
The type and value category of E1.E2 are determined as follows.
In the remainder of [expr.ref], cq represents either const or the absence of const and vq represents either volatile or the absence of volatile.
cv represents an arbitrary set of cv-qualifiers, as defined in [basic.type.qualifier].
If E2 designates an entity that is declared to have type “reference to T”, then E1.E2 is an lvalue of type T.
In that case, if E2 designates a static data member, E1.E2 designates the object or function to which the reference is bound, otherwise E1.E2 designates the object or function to which the corresponding reference member of E1 is bound.
Otherwise, one of the following rules applies.
  • If E2 designates a static data member and the type of E2 is T, then E1.E2 is an lvalue; the expression designates the named member of the class.
    The type of E1.E2 is T.
  • Otherwise, if E2 designates a non-static data member and the type of E1 is “cq1 vq1 X”, and the type of E2 is “cq2 vq2 T”, the expression designates the corresponding member subobject of the object designated by E1.
    If E1 is an lvalue, then E1.E2 is an lvalue; otherwise E1.E2 is an xvalue.
    Let the notation vq12 stand for the “union” of vq1 and vq2; that is, if vq1 or vq2 is volatile, then vq12 is volatile.
    Similarly, let the notation cq12 stand for the “union” of cq1 and cq2; that is, if cq1 or cq2 is const, then cq12 is const.
    If the entity designated by E2 is declared to be a mutable member, then the type of E1.E2 is “vq12 T.
    If the entity designated by E2 is not declared to be a mutable member, then the type of E1.E2 is “cq12 vq12 T.
  • If E2 denotes an overload set, the expression shall be the (possibly-parenthesized) left-hand operand of a member function call ([expr.call]), and function overload resolution ([over.match]) is used to select the function to which E2 refers.
    The type of E1.E2 is the type of E2 and E1.E2 refers to the function referred to by E2.
    • If E2 refers to a static member function, E1.E2 is an lvalue.
    • Otherwise (when E2 refers to a non-static member function), E1.E2 is a prvalue.
      [Note 5: 
      Any redundant set of parentheses surrounding the expression is ignored ([expr.prim.paren]).
      — end note]
  • If E2 designates a nested type, the expression E1.E2 is ill-formed.
  • If E2 designates a member enumerator and the type of E2 is T, the expression E1.E2 is a prvalue of type T whose value is the value of the enumerator.
  • If E2 designates a direct base class relationship and the type of E1 is cv T, the expression designates the direct base class subobject of type B of the object designated by E1.
    If E1 is an lvalue, then E1.E2 is an lvalue; otherwise, E1.E2 is an xvalue.
    The type of E1.E2 is “cv B.
    [Note 6: 
    This can only occur in an expression of the form e1.[:e2:].
    — end note]
    [Example 1: struct B { int b; }; struct C : B { int get() const { return b; } }; struct D : B, C { }; constexpr int f() { D d = {1, {}}; // b unambiguously refers to the direct base class of type B, // not the indirect base class of type B B& b = d.[: std::meta::bases_of(^^D, std::meta::access_context::current())[0] :]; b.b += 10; return 10 * b.b + d.get(); } static_assert(f() == 110); — end example]
  • Otherwise, the program is ill-formed.
If E2 designates a non-static member (possibly after overload resolution), the program is ill-formed if the class of which E2 designates a direct member is an ambiguous base ([class.member.lookup]) of the designating class ([class.access.base]) of E2.
[Note 7: 
The program is also ill-formed if the naming class is an ambiguous base of the class type of the object expression; see [class.access.base].
— end note]
If E2 designates a non-static member (possibly after overload resolution) and the result of E1 is an object whose type is not similar ([conv.qual]) to the type of E1, the behavior is undefined.
[Example 2: struct A { int i; }; struct B { int j; }; struct D : A, B {}; void f() { D d; static_cast<B&>(d).j; // OK, object expression designates the B subobject of d reinterpret_cast<B&>(d).j; // undefined behavior } — end example]
49)49)
Note that (*(E1)) is an lvalue.
50)50)
If the class member access expression is evaluated, the subexpression evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.