What is the meaning of Note 1 in the C++ class member name lookup rules?
Asked Answered
D

2

7

From http://eel.is/c++draft/class.member.lookup#1 :

A search in a scope X for a name N from a program point P is a single search in X for N 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.

[Note 1: The result differs only if N is a conversion-function-id or if the single search would find nothing. — end note]

I'm having a hard time making a sense of the Note. It seems that a "single search" from a class scope will find preceding declarations at namespace scope, since the namespace scope contains the class scope. But, as we know, if the name has also been declared as a member of a non-dependent base class, then the base class member takes precedence over the namespace member. Note 1 seems to contradict this, since it's basically saying "if N is not a conversion-function-id, then you can just do a normal single search, and only if you fail to find anything, then use the procedure in this section". But the single search will succeed by finding the namespace scope declaration, and the class member lookup will yield a different result.

Where is the error in my understanding?

Descartes answered 31/5, 2021 at 19:59 Comment(15)
Not sure whether I'm missing some context, but I can't even make sense of the non-note part. I thought "A search" is a single search by definition? Is that not the reason that it says "A search" and not "Multiple searches"? So is the "unless..." not contradictory?Kliber
Ok, this is WG21 playing games with the english language. "Single search" has its own definition, and "single search" does not denote a quantity of searches, as one might suspect!Kliber
@JohannesSchaub-litb: Perhaps you would be happier with “simple search”? We could always file an editorial issue if it’s deemed broadly confusing.Francisco
@Davis yes IMO that would be far better!Kliber
@DavisHerring I think "single search" is not that confusing, but I was confused by the term "bound in" ([basic.scope.scope]/2.5). One normally thinks of "N is bound to D" to be a relationship between two entities, and this definition then defines where this relationship holds - namely, in the target scope (including any child scopes). But it seems that you intended "bound in" to be a relationship between three entities, where the word "in" is part of the term and doesn't have its usual meaning. This could probably be made less confusing, but I'm not sure how.Descartes
Though I still agree that "simple search" is better than "single search".Descartes
@Davis I now understand the confusion comes from confusing the meaning of "single" as appertaining to "search", but it actually appertains to "scope" (i.e. without searching base-class scopes). Maybe "single scope search" would have been clearer. Or even "direct search" (without parents or base classes/others). Or "scoped search". I'm now unsure whether "simple search" would actually be better than "single search". "Simple" doesn't give any hint as to what may happen. Maybe it's best to leave it on "single search".Kliber
@Brian I think the "N bound to D in S" just means that there's a name findable by name lookup in that scope. I.e a name that was introduced by a declaration possibly into a different scope, the declaration's "target scope", is "bound" to that declaration in a scope where name lookup can resolve it to that declaration.Kliber
For example, "class x{ };"s target scope is the global scope, but the name is bound to that declaration in both the global scope and x's own class scope (injected class name)Kliber
@Davis the term "direct search" would nicely match the term "direct member", which is distinct to "member" in that a member can also be an inherited member.Kliber
Opened an issue report github.com/cplusplus/draft/issues/4629Kliber
@Davis in the spec I see "If a declarator-id is a name, the init-declarator and (hence) the declaration introduce that name.". Is this even true for "friend void f();"? I suspect that the declaration "introduces"/"declares" the name into its target scope (as a hidden/internal entry marking the entity or typedef-name belonging there)? But I can't find a rule that says so!Kliber
@JohannesSchaub-litb: Yes, friend declarations introduce names (as necessary for them to declare the same entity as any other declaration based on that name ([basic.scope.scope]/3)); [dcl.meaning.general]/2.3 specifies their target scope, and /2.1 suppresses the binding there.Francisco
@David I see! So if I understand it correctly: name introductions do not happen "in" a scope anymore (it's bindings that do this job now). But they are just introduced into a translation unit, into a large "bin of names". What determines identity is the target scope of the declaration. But why is it important that a name is "introduced" into the TU at all? Why is it not sufficient that the entity has a name and its declaration has a target scope? I guess I will figure it out on subsequent reads of your paper!Kliber
Though I suspect the act of introducing a name just means that there's a declaration that provides a name and interpretation for it. Guess I'm trying to find a deeper meaning while there is none!Kliber
F
5

Answer

A single search considers only one scope—not an enclosing namespace or even a base class. It’s an unqualified search that considers all enclosing scopes. Single searches and (plain) searches are subroutines of these higher-level procedures.

Context

It should be said, since there have been a lot of these questions lately, that these terms exist to reduce ambiguity and imprecision (e.g., CWG issue 191) in the definitions of “programmer-level” constructs like (un)qualified name lookup. I didn’t invent them to increase the number of vocabulary words that the typical programmer should be expected to have memorized. (Put differently, the standard is not a tutorial.)

Of course, there’s nothing special about this particular question in this regard, but I must hope that this will thereby tend to find the people that need to see it.

Francisco answered 31/5, 2021 at 21:21 Comment(3)
Thanks for the authoritative answer. This would have made more sense to me if I hadn't overlooked the sentence at the end of [basic.lookup.unqual]/2. Yet I still think the wording needs some improvement. I'll add another comment on the question about this, since there's already a thread there.Descartes
@LanguageLawyer: Perhaps not: /4 changes the point of the lookup when in a complete-class context.Francisco
This is what I was thinking about. But decided to triple-check and deleted the comment. Single search may find some overloads, which isn't nothing, and this still be different from lookup result in the complete class context which will find all overloads.Cajolery
L
0

The purpose of a "single search" is used to state how the lookup should perform for the member. In simple, if a single search is used to find the member in the namespace's scope, its enclosing scope will not be continue found due to the single search here, if there is no declaration yet found.

As the rule you quoted here, the scope of the class or class template is an exception here to the "single search", which means the single search should continue to be performed in its base classes if nothing yet found.

The declaration set is the result of a single search in the scope of C for N from immediately after the class-specifier of C if P is in a complete-class context of C or from P otherwise.

This is a recursive procedure. Hence, the note says "The result differs only if the single search would find nothing."

Whereas for "The result differs only if N is a conversion-function-id" because of the following rule:

In each case where conversion functions of a class S are considered for initializing an object or reference of type T, the candidate functions include the result of a search for the conversion-function-id operator T in S.

It does not mean the name "operator T" is the unique name to be lookup for the conversion function, the "permissible types" are also candidates to be found according to the relevant rule.

Each such case also defines sets of permissible types for explicit and non-explicit conversion functions;

Anyway, the note is used to say the exception for a "single search" which shouldn't have found any declaration by the single search but the other candidate ways would find them.

Levant answered 9/6, 2021 at 2:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.