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.
For the first option (dot),
if the id-expression names a static member or an enumerator,
the first expression is a discarded-value expression ([expr.context]);
if the id-expression names a non-static data member,
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).50
The postfix expression before the dot is evaluated;51
the result of that evaluation,
together with the id-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”.
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.
If E2 is a non-static data member and the type of
E1 is “cq1 vq1X”, and the type of E2
is “cq2 vq2T”, 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 “vq12T”.
If E2 is not declared to be a
mutable member, then the type of E1.E2 is
“cq12vq12T”.
If E2 is 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 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.
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 dreinterpret_cast<B&>(d).j; // undefined behavior} — end example]
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.