244 lines
12 KiB
Markdown
244 lines
12 KiB
Markdown
[expr.ref]
|
||
|
||
# 7 Expressions [[expr]](./#expr)
|
||
|
||
## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.ref)
|
||
|
||
### 7.6.1 Postfix expressions [[expr.post]](expr.post#expr.ref)
|
||
|
||
#### 7.6.1.5 Class member access [expr.ref]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4128)
|
||
|
||
A postfix expression followed by a dot . or an arrow ->,
|
||
optionally followed by the keywordtemplate, and then followed by an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]"),
|
||
is a postfix expression[.](#1.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
If the keyword template is used and
|
||
followed by an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"),
|
||
the unqualified name
|
||
is considered to refer to a template ([[temp.names]](temp.names "13.3 Names of template specializations"))[.](#1.sentence-2)
|
||
|
||
If a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") results and is followed by a ::,
|
||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4153)
|
||
|
||
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]](expr.context "7.2.3 Context dependence"));
|
||
if the expression after the dot designates a non-static data member,
|
||
the first expression shall be a glvalue[.](#2.sentence-1)
|
||
|
||
A postfix expression that is followed by an arrow
|
||
shall be a prvalue having pointer type[.](#2.sentence-2)
|
||
|
||
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[.](#2.sentence-3)[49](#footnote-49 "Note that (*(E1)) is an lvalue.")
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4170)
|
||
|
||
The postfix expression before the dot is evaluated;[50](#footnote-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.") the result of that evaluation,
|
||
together with
|
||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]"),
|
||
determines the result of the entire postfix expression[.](#3.sentence-1)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4184)
|
||
|
||
Abbreviating[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]").[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]").[*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") as E1.E2, E1 is called the [*object expression*](expr.mptr.oper#def:object_expression "7.6.4 Pointer-to-member operators [expr.mptr.oper]")[.](#4.sentence-1)
|
||
|
||
If the object expression is of scalar type,E2 shall name the pseudo-destructor
|
||
of that same type (ignoring cv-qualifications) andE1.E2 is a prvalue of type âfunction of () returning voidâ[.](#4.sentence-2)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
This value can only be used
|
||
for a notional function call ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5 Destruction"))[.](#4.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4198)
|
||
|
||
Otherwise, the object expression shall be of class type[.](#5.sentence-1)
|
||
|
||
The class type shall be complete
|
||
unless the class member access appears in the definition of that class[.](#5.sentence-2)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
The program is ill-formed if the result differs from that
|
||
when the class is complete ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))[.](#5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
[[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup") describes how names are looked up after the. and -> operators[.](#5.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4211)
|
||
|
||
If E2 is a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]"),
|
||
then let T1 be the type of E1[.](#6.sentence-1)
|
||
|
||
E2 shall designate either
|
||
a member of T1 or
|
||
a direct base class relationship (T1, B)[.](#6.sentence-2)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4218)
|
||
|
||
If E2 designates a bit-field, E1.E2 is a bit-field[.](#7.sentence-1)
|
||
|
||
The
|
||
type and value category of E1.E2 are determined as follows[.](#7.sentence-2)
|
||
|
||
In the remainder of [expr.ref], *cq* represents eitherconst or the absence of const and *vq* represents
|
||
either volatile or the absence of volatile[.](#7.sentence-3)
|
||
|
||
*cv* represents an arbitrary set of cv-qualifiers, as defined
|
||
in [[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")[.](#7.sentence-4)
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4227)
|
||
|
||
If E2 designates an entity
|
||
that is declared to have type âreference to Tâ, thenE1.E2 is an lvalue of type T[.](#8.sentence-1)
|
||
|
||
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[.](#8.sentence-2)
|
||
|
||
Otherwise, one of the following rules applies[.](#8.sentence-3)
|
||
|
||
- [(8.1)](#8.1)
|
||
|
||
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[.](#8.1.sentence-1)
|
||
The type of E1.E2 is T[.](#8.1.sentence-2)
|
||
|
||
- [(8.2)](#8.2)
|
||
|
||
Otherwise, if E2 designates a non-static data member and the type ofE1 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[.](#8.2.sentence-1)
|
||
If E1 is an lvalue, then E1.E2 is an lvalue;
|
||
otherwise E1.E2 is an xvalue[.](#8.2.sentence-2)
|
||
Let the notation *vq12* stand for the âunionâ of*vq1* and *vq2*; that is, if *vq1* or *vq2* is volatile, then *vq12* is volatile[.](#8.2.sentence-3)
|
||
Similarly,
|
||
let the notation *cq12* stand for the âunionâ of *cq1* and *cq2*; that is, if *cq1* or *cq2* isconst, then *cq12* is const[.](#8.2.sentence-4)
|
||
If the entity designated by E2 is declared to be a mutable member,
|
||
then the type of E1.E2 is â*vq12* Tâ[.](#8.2.sentence-5)
|
||
If the entity designated by E2 is not declared to be a mutable member,
|
||
then the type of E1.E2 is â*cq12* *vq12* Tâ[.](#8.2.sentence-6)
|
||
|
||
- [(8.3)](#8.3)
|
||
|
||
Otherwise, if E2 denotes an overload set,
|
||
the expression shall be the (possibly-parenthesized) left-hand operand of
|
||
a member function call ([[expr.call]](expr.call "7.6.1.3 Function call")), and
|
||
function overload resolution ([[over.match]](over.match "12.2 Overload resolution"))
|
||
is used to select the function to which E2 refers[.](#8.3.sentence-1)
|
||
The type of E1.E2 is the type of E2 and E1.E2 refers to the function referred to by E2[.](#8.3.sentence-2)
|
||
|
||
* [(8.3.1)](#8.3.1)
|
||
|
||
If E2 refers to a static member function,E1.E2 is an lvalue[.](#8.3.1.sentence-1)
|
||
|
||
* [(8.3.2)](#8.3.2)
|
||
|
||
Otherwise (when E2 refers to a non-static member function),E1.E2 is a prvalue[.](#8.3.2.sentence-1)
|
||
[*Note [5](#note-5)*:
|
||
Any redundant set of parentheses surrounding the expression
|
||
is ignored ([[expr.prim.paren]](expr.prim.paren "7.5.4 Parentheses"))[.](#8.3.2.sentence-2)
|
||
â *end note*]
|
||
|
||
- [(8.4)](#8.4)
|
||
|
||
Otherwise, if E2 designates a nested type,
|
||
the expression E1.E2 is ill-formed[.](#8.4.sentence-1)
|
||
|
||
- [(8.5)](#8.5)
|
||
|
||
Otherwise, 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[.](#8.5.sentence-1)
|
||
|
||
- [(8.6)](#8.6)
|
||
|
||
Otherwise, if E2 designates a direct base class relationship (D,B) 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[.](#8.6.sentence-1)
|
||
If E1 is an lvalue,
|
||
then E1.E2 is an lvalue;
|
||
otherwise, E1.E2 is an xvalue[.](#8.6.sentence-2)
|
||
The type of E1.E2 is âcv Bâ[.](#8.6.sentence-3)
|
||
[*Note [6](#note-6)*:
|
||
This can only occur in an expression of the form e1.[:e2:][.](#8.6.sentence-4)
|
||
â *end note*]
|
||
[*Example [1](#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*]
|
||
|
||
- [(8.7)](#8.7)
|
||
|
||
Otherwise, the program is ill-formed[.](#8.7.sentence-1)
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4332)
|
||
|
||
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]](class.member.lookup "6.5.2 Member name lookup")) of
|
||
the designating class ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")) of E2[.](#9.sentence-1)
|
||
|
||
[*Note [7](#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]](class.access.base "11.8.3 Accessibility of base classes and base class members")[.](#9.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4343)
|
||
|
||
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]](conv.qual "7.3.6 Qualification conversions")) to the type of E1,
|
||
the behavior is undefined[.](#10.sentence-1)
|
||
|
||
[*Example [2](#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 dreinterpret_cast<B&>(d).j; // undefined behavior} â *end example*]
|
||
|
||
[49)](#footnote-49)[49)](#footnoteref-49)
|
||
|
||
Note that(*(E1)) is an lvalue[.](#footnote-49.sentence-1)
|
||
|
||
[50)](#footnote-50)[50)](#footnoteref-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*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") denotes a static member[.](#footnote-50.sentence-1)
|