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, is a postfix expression.
The postfix expression before the dot or arrow is evaluated;51 the result of that evaluation, together with the id-expression, determines the result of the entire postfix expression.
[Note 1: 
If the keyword template is used, the following 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 the first option (dot) the first expression shall be a glvalue.
For the second option (arrow) the first expression 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 first option (dot).52
Abbreviating postfix-expression.id-expression as E1.E2, E1 is called the object 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 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 is declared to have type “reference to T”, then E1.E2 is an lvalue of type T.
If E2 is 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 is 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.
  • If E2 is 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 the first expression.
    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 E2 is declared to be a mutable member, then the type of E1.E2 is “vq12 T.
    If E2 is not declared to be a mutable member, then the type of E1.E2 is “cq12 vq12 T.
  • If E2 is an overload set, 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.
      The expression can be used only as the left-hand operand of a member function call ([class.mfct]).
      [Note 5: 
      Any redundant set of parentheses surrounding the expression is ignored ([expr.prim.paren]).
      — end note]
  • If E2 is a nested type, the expression E1.E2 is ill-formed.
  • If E2 is 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 is a non-static member, the program is ill-formed if the class of which E2 is directly a member is an ambiguous base ([class.member.lookup]) of the naming class ([class.access.base]) of E2.
[Note 6: 
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 is a non-static member 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 1: 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]
51)51)
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.
52)52)
Note that (*(E1)) is an lvalue.