Files
2025-10-25 03:02:53 +03:00

244 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.1General[expr.prim.id.general]") or a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression 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.1General[expr.prim.id.general]"),
the unqualified name
is considered to refer to a template ([[temp.names]](temp.names "13.3Names of template specializations"))[.](#1.sentence-2)
If a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") results and is followed by a ::,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified 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.3Context 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.1General[expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression 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.1General[expr.post.general]").[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]").[*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") as E1.E2, E1 is called the [*object expression*](expr.mptr.oper#def:object_expression "7.6.4Pointer-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.5Destruction"))[.](#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.2Member name lookup"))[.](#5.sentence-3)
— *end note*]
[*Note [4](#note-4)*:
[[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified 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.9Expression 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.5CV-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*€[.](#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.3Function call")), and
function overload resolution ([[over.match]](over.match "12.2Overload 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.4Parentheses"))[.](#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.2Member name lookup")) of
the designating class ([[class.access.base]](class.access.base "11.8.3Accessibility 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.3Accessibility 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.6Qualification 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.1General[expr.prim.id.general]") denotes a static member[.](#footnote-50.sentence-1)