This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
[class.member.lookup]
# 6 Basics [[basic]](./#basic)
## 6.5 Name lookup [[basic.lookup]](basic.lookup#class.member.lookup)
### 6.5.2 Member name lookup [class.member.lookup]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1735)
A [*search*](#def:search "6.5.2Member name lookup[class.member.lookup]") in a scope X for a name M from a program point P is a single search in X for M from P unless X is the scope of a class or class template T, in which case the
following steps define the result of the search[.](#1.sentence-1)
[*Note [1](#note-1)*:
The result differs only
if M is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") or
if the single search would find nothing[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1747)
The [*lookup set*](#def:lookup_set "6.5.2Member name lookup[class.member.lookup]") for a name N in a class or class template C, called S(N,C),
consists of two component sets:
the [*declaration set*](#def:declaration_set), a set of members named N; and
the [*subobject set*](#def:subobject_set),
a set of subobjects where declarations of these members were found
(possibly via [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")*s*)[.](#2.sentence-1)
In the declaration set, type declarations (including injected-class-names)
are replaced by the types they designate[.](#2.sentence-2)
S(N,C) is calculated as follows:
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1757)
The declaration set is the result of
a single search in the scope of C for N from immediately after the [*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]") of C if P is in a complete-class context of C or
from P otherwise[.](#3.sentence-1)
If the resulting declaration set is not empty, the subobject set
contains C itself, and calculation is complete[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1766)
Otherwise (i.e., C does not contain a declaration of N or the resulting declaration set is empty), S(N,C) is initially empty[.](#4.sentence-1)
Calculate the lookup set for N in each direct non-dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types")) base class subobject Bi, and
merge each such lookup set S(N,Bi) in turn into S(N,C)[.](#4.sentence-2)
[*Note [2](#note-2)*:
If C is incomplete,
only base classes whose [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]") appears before P are considered[.](#4.sentence-3)
If C is an instantiated class, its base classes are not dependent[.](#4.sentence-4)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1779)
The following steps define the result of merging lookup set S(N,Bi) into the intermediate S(N,C):
- [(5.1)](#5.1)
If each of the subobject members of S(N,Bi) is a base class
subobject of at least one of the subobject members of S(N,C), or ifS(N,Bi) is empty, S(N,C) is unchanged and the merge is complete[.](#5.1.sentence-1)
Conversely, if each of the subobject members of S(N,C) is a base class
subobject of at least one of the subobject members of S(N,Bi), or ifS(N,C) is empty, the new S(N,C) is a copy of S(N,Bi)[.](#5.1.sentence-2)
- [(5.2)](#5.2)
Otherwise, if the declaration sets of S(N,Bi) and S(N,C) differ, the merge is ambiguous: the new S(N,C) is a lookup set with an
invalid declaration set and the union of the subobject sets[.](#5.2.sentence-1)
In
subsequent merges, an invalid declaration set is considered different
from any other[.](#5.2.sentence-2)
- [(5.3)](#5.3)
Otherwise, the new S(N,C) is a lookup set with the shared set of
declarations and the union of the subobject sets[.](#5.3.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1801)
The result of the search is the declaration set of S(M,T)[.](#6.sentence-1)
If it is an invalid set, the program is ill-formed[.](#6.sentence-2)
If it differs from the result of a search in T for M in a complete-class context ([[class.mem]](class.mem "11.4Class members")) of T,
the program is ill-formed, no diagnostic required[.](#6.sentence-3)
[*Example [1](#example-1)*: struct A { int x; }; // S(x,A) = { { A::x }, { A } }struct B { float x; }; // S(x,B) = { { B::x }, { B } }struct C: public A, public B { }; // S(x,C) = { invalid, { A in C, B in C } }struct D: public virtual C { }; // S(x,D) = S(x,C)struct E: public virtual C { char x; }; // S(x,E) = { { E::x }, { E } }struct F: public D, public E { }; // S(x,F) = S(x,E)int main() { F f;
f.x = 0; // OK, lookup finds E::x}
S(x,F) is unambiguous because the A and B base
class subobjects of D are also base class subobjects of E, soS(x,D) is discarded in the first merge step[.](#6.sentence-4)
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1826)
If M is a non-dependent [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]"),
conversion function templates that are members of T are considered[.](#7.sentence-1)
For each such template F, the lookup set S(t,T) is constructed,
considering a function template declaration to have the name t only if it corresponds to a declaration of F ([[basic.scope.scope]](basic.scope.scope "6.4.1General"))[.](#7.sentence-2)
The members of the declaration set of each such lookup set,
which shall not be an invalid set, are included in the result[.](#7.sentence-3)
[*Note [3](#note-3)*:
Overload resolution will discard those
that cannot convert to the type specified by M ([[temp.over]](temp.over "13.10.4Overload resolution"))[.](#7.sentence-4)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1839)
[*Note [4](#note-4)*:
A static member, a nested type or an enumerator defined in a base classT can unambiguously be found even if an object has more than one
base class subobject of type T[.](#8.sentence-1)
Two base class subobjects share
the non-static member subobjects of their common virtual base classes[.](#8.sentence-2)
— *end note*]
[*Example [2](#example-2)*: struct V {int v;};struct A {int a; static int s; enum { e };};struct B : A, virtual V { };struct C : A, virtual V { };struct D : B, C { };
void f(D* pd) { pd->v++; // OK, only one v (virtual) pd->s++; // OK, only one s (static)int i = pd->e; // OK, only one e (enumerator) pd->a++; // error: ambiguous: two as in D} — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1869)
[*Note [5](#note-5)*:
When virtual base classes are used, a hidden declaration can be reached
along a path through the subobject lattice that does not pass through
the hiding declaration[.](#9.sentence-1)
This is not an ambiguity[.](#9.sentence-2)
The identical use with
non-virtual base classes is an ambiguity; in that case there is no
unique instance of the name that hides all the others[.](#9.sentence-3)
— *end note*]
[*Example [3](#example-3)*: struct V { int f(); int x; };struct W { int g(); int y; };struct B : virtual V, W {int f(); int x; int g(); int y;};struct C : virtual V, W { };
struct D : B, C { void glorp(); };
![SVG Image](data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMzg2LjAwIDE0MC4wMCIgd2lkdGg9IjM4NnB0IiBoZWlnaHQ9IjE0MHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydAoKPGcgY2xhc3M9Im5vZGUiPgpXMQpXCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KVgpWCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KVzIKVwo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkIKQgo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkItJmd0O1cxCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik05NC4yNiwtNzYuMTZDODEuODUsLTg0LjQzIDYzLjM3LC05Ni43NSA0OC45MiwtMTA2LjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpCLSZndDtWCjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0xMjEuNzQsLTc2LjE2QzEzNC4xNSwtODQuNDMgMTUyLjYzLC05Ni43NSAxNjcuMDgsLTEwNi4zOCIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7Vgo8cGF0aCBmaWxsPSJub25lIiBkPSJNMjU2LjI2LC03Ni4xNkMyNDMuODUsLTg0LjQzIDIyNS4zNywtOTYuNzUgMjEwLjkyLC0xMDYuMzgiIHN0cm9rZT0iYmxhY2siIC8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiAvPgo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkMtJmd0O1cyCjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0yODMuNzQsLTc2LjE2QzI5Ni4xNSwtODQuNDMgMzE0LjYzLC05Ni43NSAzMjkuMDgsLTEwNi4zOCIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KRApECjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KRC0mZ3Q7Qgo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNMTc1LjI2LC0yMC4xNkMxNjIuODUsLTI4LjQzIDE0NC4zNywtNDAuNzUgMTI5LjkyLC01MC4zOCIgZmlsbD0ibm9uZSIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KRC0mZ3Q7Qwo8cGF0aCBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBkPSJNMjAyLjc0LC0yMC4xNkMyMTUuMTUsLTI4LjQzIDIzMy42MywtNDAuNzUgMjQ4LjA4LC01MC4zOCIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KPC9nPgo8L3N2Zz4=)
Figure [1](#fig:class.lookup) — Name lookup [[fig:class.lookup]](./fig:class.lookup)
As illustrated in Figure [1](#fig:class.lookup),
the names declared in V and the left-hand instance of W are hidden by those in B, but the names declared in the
right-hand instance of W are not hidden at all[.](#9.sentence-4)
void D::glorp() { x++; // OK, B::x hides V::x f(); // OK, B::f() hides V::f() y++; // error: B::y and C's W::y g(); // error: B::g() and C's W::g()} — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1912)
An explicit or implicit conversion from a pointer to or
an expression designating an object
of a
derived class to a pointer or reference to one of its base classes shall
unambiguously refer to a unique object representing the base class[.](#10.sentence-1)
[*Example [4](#example-4)*: struct V { };struct A { };struct B : A, virtual V { };struct C : A, virtual V { };struct D : B, C { };
void g() { D d;
B* pb = &d;
A* pa = &d; // error: ambiguous: C's A or B's A? V* pv = &d; // OK, only one V subobject} — *end example*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1935)
[*Note [6](#note-6)*:
Even if the result of name lookup is unambiguous, use of a name found in
multiple subobjects might still be
ambiguous ([[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions"), [[expr.ref]](expr.ref "7.6.1.5Class member access"), [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members"))[.](#11.sentence-1)
— *end note*]
[*Example [5](#example-5)*: struct B1 {void f(); static void f(int); int i;};struct B2 {void f(double);};struct I1: B1 { };struct I2: B1 { };
struct D: I1, I2, B2 {using B1::f; using B2::f; void g() { f(); // Ambiguous conversion of this f(0); // Unambiguous (static) f(0.0); // Unambiguous (only one B2)int B1::* mpB1 = &D::i; // Unambiguousint D::* mpD = &D::i; // Ambiguous conversion}}; — *end example*]