Usual unqualified lookup and Argument-dependent name lookup(ADL) - c++

For unqualified name lookup, 'Usual unqualified lookup' and 'Argument-dependent name lookup'(ADL), I cannot find in standard which one happens first ?
Again as both trying to add something to the overload candidate set, the order doesn't seems to be matter though. But would still be nice to know which one happens first.
Thanks

It doesn't matter which comes first, does it? Name lookup generates a set of possible names.
3.4 Name lookup
Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions.
The standard specifically says "set". As a mathematical construct, the set {1,2,3} is the same as {2,3,1} and {3,2,1}. Order doesn't matter. What does matter is when overload resolution and the application access rules occurs. Here the standard is very clear. Quoting once again from the intro paragraph to 3.4:
Overload resolution takes place after name lookup has succeeded. The access rules are considered only once name lookup and function overload resolution have succeeded.

Related

A confusion about function name lookup

I'm confused by some rules in the standard. I'll cite them here:
[basic.lookup.argdep]:
Let X be the lookup set produced by unqualified lookup and let Y be the lookup set produced by argument dependent lookup (defined as follows).
So the sentence above means that the set X is created by unqualified lookup. Then we look at the rules of unqualified lookup:
[basic.lookup.unqual]:
In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name.
The emphasized part "name lookup ends as soon as a declaration is found for the name" means that once a name is found, the lookup stops.
So my question is:
void func(int){}
void func(double){}
int main(){
func(0);
}
Consider the above code. The name of fun is used in an unqualified way. So the unqualified lookup rules are performed. Hence, once either func(double) or func(int) is found, the lookup is stopped. So, why can func be overloaded, i.e. the set of candidate function contains both func(int) and func(double)? Doesn't it contradict the unqualified lookup rules? If I miss something, please correct me.
Reasonable question. The relevant part is "the scopes are searched for a declaration in the order listed".
In pseudo-code
for (auto scope: scopes)
{
if (scope.contains(name))
return scope;
}
throw ill_formed(name);
As soon as one scope is found that contains name, that scope is selected. Further scopes on the list are not searched. Even if name occurs in that scope, it will not participate in overload resolution.
In your example however, the selected scope contains not one but two declarations of func so overload resolution still happens.

Overload resolution of a qualified name

Consider this function call:
foo::bar();
11.3.1.1.1, paragraph 3 [over.call.func] (N4778) covers this case:
In unqualified function calls, the name is not qualified by an -> or . operator and has the more general form of a primary-expression. The name is looked up in the context of the function call following the normal rules for name lookup in function calls...
Here, foo::bar is an unqualified name, in the sense that it's not qualified by -> or .. So this paragraph applies. Now, the meaning of the phrase "looked up in the context of" is explained in 6.4, paragraph 2 [basic.lookup]:
A name “looked up in the context of an expression” is looked up as an unqualified name in the scope where the expression is found.
However, foo::bar is a qualified name in the realm of name lookup. In other words, this combination of paragraphs basically say that, the qualified name foo::bar is looked up by the rule of unqualified name lookup. However, I don't think that unqualified name lookup is capable of recursively entering into a narrower scope, i.e., foo to bar. Is this a defect?
No, I don't think this is a defect. It says
The name is looked up in the context of the function call following the normal rules for name lookup in function calls [...]
As you can see from the part that I highlighted, the standard specifies how the name is supposed to be looked up: By name lookup.
Name lookup involves unqualified, qualified and argument-dependent lookup, so your name is indeed resolved by the qualified name lookup rules.
The "looked up in the context of expr" rule doesn't apply here, as it is specified what rule is used. That paragraph only comes into play when it's not. For example, in [class.qual]p1:
the names in a template-argument of a template-id are looked up in the context in which the entire postfix-expression occurs.

Does Argument-Dependent Lookup go before normal scope lookup?

This is the code in question that appears in §13.3 of "C++ Primer", 5ed:
void swap(Foo &lhs, Foo &rhs)
{
using std::swap;
swap(lhs.h, rhs.h); // uses the HasPtr version of swap
// swap other members of type Foo
}
The book mentions the phenomenon of the class-specific swap not being hidden by the using declaration, and refers reader to §18.2.3:
I read that section and realized that this may be related to Argument-Dependent Lookup (ADL). The following is the excerption:
But I still have some vagueness in the understanding. My question is: does the ADL go before the normal scope lookup, or after the normal scope lookup? My current understanding is that ADL goes before the normal scope lookup, because otherwise it should be the std::swap that is used. I need confirmation if you think I am right, or please point out what mistake I've made if you think I am wrong. Thank you.
ADL doesn't go before, it's not preferred specially; the names found by ADL will be considered in addition to the names found by the usual name lookup.
These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.
That means all the named found by ADL and usual name lookup will be considered in overload resolution; then the best match will be selected.
In order to compile a function call, the compiler must first perform name lookup, which, for functions, may involve argument-dependent lookup, and for function templates may be followed by template argument deduction. If these steps produce more than one candidate function, then overload resolution is performed to select the function that will actually be called.

What is the meaning of the last sentence in [basic.lookup]/1?

[basic.lookup]/1:
The name lookup rules apply uniformly to all names (including typedef-names (10.1.3), namespace-names
(10.3), and class-names (12.1)) wherever the grammar allows such names in the context discussed by a
particular rule. Name lookup associates the use of a name with a set of declarations (6.1) of that name. The
declarations found by name lookup shall either all declare the same entity or shall all declare functions; in the
latter case, the declarations are said to form a set of overloaded functions (16.1). Overload resolution (16.3)
takes place after name lookup has succeeded. The access rules (Clause 14) are considered only once name
lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the
name’s declaration used further in expression processing (Clause 8).
What are those attributes introduced by the names´s declaration?
This sentence is visible in the N1638 - C++ Working Draft from April 2004, so it doesn't refer specifically to attributes of the form [[...]], which were introduced to the standard by N2761 - Towards support for attributes in C++
(Revision 6) in 2008.
[basic.lookup]/1
Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the name’s declaration used further in expression processing (clause 5).
Also [basic.def]/1
A declaration (clause 7) introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.
From the above, and looking at the five other occurrences of 'attribute' in that paper, it appears to me that 'attribute' just means "information about the name". So in this case, things like extern, friend, the body of a function definition, and anything else you can say about a name in a declaration, that wasn't part of determining the interpretation of a name.
Since C++11 this would also include "generalised attributes" in the form [[..]]. There's a hint here, N2761 didn't introduce 'attributes', it just gave us a generalised syntax for them.
Function parameters, conversely, would not be 'attributes' in this sense, as the interpretation of the function name involves the parameters as part of overload resolution. The return type would be an attribute, since we don't look at it until we know what the name means, and which overload we've chosen.
In a slightly-more-standardese sense, I think you can say that the 'specifiers' are attributes, while the 'declarators' specify the interpretation of a name.
Pratically, I would say (without checking for a more-specific rule) that this is the rule that requires that deleted functions survive all the way through the lookup and name resolution process, and then fail the compilation.
Otherwise, a crafty compiler author might want to save their users some grief by eliminating deleted functions earlier, on the grounds that you can't call a deleted function, so why bother including it in the overload set?

List of C++ name resolution (and overloading) rules

Where I can find a list of the rules that a C++ compliant compiler must apply in order to perform names resolution (including overloading)?
I'd like something like a natural-language algorithm or flow chart.
C++ standard of course has this set of rules but it is build up as new language statements are introduced and the result it's pretty hard to remember.
To make a long story short, I'd like to know the complete and detailed answer to the question "What compiler do when it see the name 'A'?"
I know C++ is all "We do this when X but not Y if Z holds" so, I'm asking whether it is possible to make it more linear.
EDIT: I'm working on a draft of this topic, something that may be improved collectively once posted. However i'm very busy this days and it may take time to have something publicable. If someone interested i'll promote the "personal note on a raw txt file" to something better and post it.
Well, in broad strokes:
If the name is preceded by ::, as in ::A or X::A, then use qualified name lookup. First look up X, if it exists (if not use the global namespace) then look inside it for A. If X is a class, and A is not a direct member, then look in all the direct bases of X. If A is found in more than one base, fail.
Otherwise, if the name is used as a function call such as A( X ), use argument-dependent lookup. This is the hard part. Look for A in the namespace the type of X was declared in, in the friends of X, and if X is a template instantiation, likewise for all the arguments involved. Scopes associated only by typedef do not apply. Do this in addition to unqualified lookup.
Start with unqualified lookup if argument-dependent lookup doesn't apply. This is the usual way variables are found. Start at the current scope and work outwards until the name is found. Note that this respects using namespace directives, which the other two cases do not.
Simply glancing at the Standard will reveal many exceptions and gotchas. For example, unqualified lookup is used to determine whether the name is used as a function call, as opposed to a cast-expression, before ADL is used to generate a list of potential overloads. Unqualified lookup doesn't look for objects in enclosing scopes of nested of local classes, because such objects might not exist at the time of reference.
Apply common sense, and ask more specific questions when (as often it does) intuition fails.