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.
Related
template<typename T>
void fun(T t){
foo(t); //#1 foo is a dependent name
}
void foo(int){
}
int main(){
fun(0); // #2 ill-formed
}
Since the unqualified-id foo is a dependent name as per temp.dep#2, So, the lookup name rule for this name should obey the following rule, which is mentioned in the note of [temp.dep#2]
[ Note: Such names are unbound and are looked up at the point of the template instantiation ([temp.point]) in both the context of the template definition and the context of the point of instantiation ([temp.dep.candidate]). — end note ]
The lookup rule for a dependent name is clearly written in c++17 standard, that is:
temp.dep.res#1
In resolving dependent names, names from the following sources are considered:
Declarations that are visible at the point of definition of the template.
Declarations from namespaces associated with the types of the function arguments both from the instantiation context ([temp.point]) and from the definition context.
And temp.dep.candidate#1
For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:
For the part of the lookup using unqualified name lookup, only function declarations from the template definition context are found.
For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.
In other words, these rules mean that only ADL is used to perform in phase two lookup.
However, I cannot find the relevant rule in the current standard(i.e, c++20). [temp.dep.res#1] has been removed from the current standard. [temp.dep.candidate#1] has been modified as:
temp.dep.candidate#1
For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules from the template definition context ([basic.lookup.unqual], [basic.lookup.argdep]). [ Note: For the part of the lookup using associated namespaces ([basic.lookup.argdep]), function declarations found in the template instantiation context are found by this lookup, as described in [basic.lookup.argdep]. — end note ] If the call would be ill-formed or would find a better match had the lookup within the associated namespaces considered all the function declarations with external linkage introduced in those namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts, then the program has undefined behavior.
It's just to be a note in the current standard. It appears to me that the current standard does not clearly describe how the lookup rule performs for an unqualified dependent name in a function call. In the current standard, where's the relevant rule states that only ADL will perform in the second phase? It's unclear. If the usual unqualified look rule will be performed in the second phase, #2 would be well-formed due to void foo(int) can be found in the instantiation context by unqualified lookup. If I miss anything, where's the relevant rule?
In other words, these rules mean that only ADL is used to perform in phase two lookup.
This is the wrong conclusion to draw from the given specification quotes. You seem to be confusing two different concepts.
The first concept is what is commonly called "two-phase lookup": the fact that when a template gets parsed, names which are dependent on template parameters cannot be looked up at parse time. They can only be lookup up at instantiation time. There are two phases of lookup: one for non-dependent names, and one for dependent names.
The second concept is just name lookup, which has two scopes of names to search: regular unqualified lookup (defined in [basic.lookup.unqual]) and argument-dependent lookup (defined in [basic.lookup.argdep]). Unqualified lookup searches in the scope of the code itself, while ADL searches in the scope of the namespace of a function's arguments.
Both phases of template name lookup use both of these scopes. To be clear, dependent name lookup also does unqualified lookup. This is why one of the bullet points you quoted said "for the part of the lookup using unqualified name lookup... ". If dependent name lookup didn't use the rules for unqualified name lookup, it wouldn't have mentioned them.
Now, dependent name lookup does restrict what the candidate names are compared to the regular rules. But it doesn't restrict it to just ADL; it does both scopes of lookup.
These restrictions used to be specified in [temp.dep.candidate]/1, as you pointed out. But they got moved around a bit.
For the unqualified lookup part, the new [temp.dep.candidate]/1 covers that as you quoted it, because it says "usual lookup rules from the template definition context". This specifies the context of the unqualified lookup as being the template's definition only.
Note that the second bullet point also says to look in that scope, so it covers part of that.
The rest of the second bullet point is covered by [basic.lookup.argdep]/4.5:
If the lookup is for a dependent name ([temp.dep], [temp.dep.candidate]), any declaration D in N is visible if D would be visible to qualified name lookup ([namespace.qual]) at any point in the instantiation context ([module.context]) of the lookup, unless D is declared in another translation unit, attached to the global module, and is either discarded ([module.global.frag]) or has internal linkage.
This expands the lookup to include the "instantiation context", which largely matches the C++17 text (though with module-based modifications).
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.
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.
If a function cannot be found in the scope where it is called, looking up in the namespaces of its arguments will follow. I have a few questions.
If there are several arguments in different namespaces, which namespace will be first looked up? Is it the namespace of the first argument?
f(A::T t, B:U u); // Is namespace A looked up first?
More complex for template classes, like
f(A::T<B::U> t); // Namespace A or B is looked up first?
Actually, there is no order among the namespaces for ADL. All relevant namespaces are searched, and all functions thus found form the set of candidates for overload resolution.
Also note that unlike what you say in the question, ADL is performed even when a function is found by unqualified lookup in the calling scope. The union of unqualified lookup and ADL is then used to find the best overload.
ADL is only suppressed if unqualified lookup at calling scope finds a class member, a non-function, or a block-scope non-using declaration.
The relevant rules are in C++14 3.4.2 [basic.lookup.argdep]. Quoting N4140, bold emphasis mine:
3 Let X be the lookup set produced by unqualified lookup (3.4.1) and let Y be the lookup set produced by
argument dependent lookup (defined as follows). If X contains
a declaration of a class member, or
a block-scope function declaration that is not a using-declaration, or
a declaration that is neither a function or a function template
then Y is empty. Otherwise Y is the set of declarations found in the namespaces associated with the
argument types as described below. The set of declarations found by the lookup of the name is the union of
X and Y.
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.