Why does unqualified name lookup find all overloaded declarations - c++

Here is an example which I'm trying to understand how does unqualified name look up work for overloaded declarations:
int foo(char a){ return 0; }
namespace A
{
int foo(int a){ return a; }
int foo(){ return 2; }
extern int j;
extern int i;
}
int A::j=foo('a'); //97
int A::i=foo(); //2
It means that int foo(char); does not found by unqualified name look up but int foo(int); and int foo() can be found. So I assume that unqualified name look up for overloaded declaration ends as soon as all overloaded declarations is found for the name. I can't find this into the standard, I can find only the following (sec. 3.4.1):
name look up ends as soon as a declaration is found for the name.
This quote doesn't say anything about overloaded declaration look up.

You're mixing up name lookup with overload resolution. There is no such thing as "unqualified name look up for overloaded declaration". Name lookup and overload resolution are separate.
Name lookup means determining which scope the name is found in. Once that is completed, overload resolution determines which of the declarations visible in that scope should be used.
In your code, name lookup determines that foo means A::foo. Then overload resolution selects between A::foo() and A::foo(int). The ::foo is not considered for overload resolution because it is not a definition of A::foo.
Another example:
namespace C { void f(); }
namespace B { void f(); void f(float); }
namespace C { void f(long); }
using namespace C;
int main()
{
f(1.0);
}
When processing the line f(1.0), name lookup sees void f(); and stops. The result is that f means C::f.
Then overload resolution kicks in, and all declarations of C::f are considered for overload resolution. void f(long) is chosen.

In a declaration in which the declarator-id is a qualified-id, names used before the qualified-id being declared
are looked up in the defining namespace scope; names following the qualified-id are looked up in the scope
of the member’s class or namespace.
(C++11 §3.4.3/3)
So in both of
int A::j=foo('a');
int A::i=foo();
the name foo is looked up in the scope of A just because you have A::j and A::i to the left, in the declarator.
Note that if you do
int k = foo();
only the global foo will be found, and you'll get an error.

You said
It means that int foo(char); does not found by unqualified name look up but int foo(int); and int foo() can be found. So I assume that unqualified name look up for overloaded declaration ends as soon as all overloaded declarations is found for the name.
A similar question was asked in another SO post
There is from 3.4.1/14:
If a variable member of a namespace is defined outside of the scope of its namespace then any name that appears in the definition of the member (after the declarator-id) is looked up as if the definition of the member occurred in its namespace.
Your posted code is equivalent to:
int foo(char a){ return 0; }
namespace A
{
int foo(int a){ return a; }
int foo(){ return 2; }
extern int j;
extern int i;
}
namespace A
{
int j=foo('a');
int i=foo();
}
When the definitions and initializations are put under the namespace, it becomes clear why functions used to initialize the variables are looked up in namespace A first. If an unambiguous match can be found for a function in namespace A, the search for it stops. That means, when compiling the line,
int A::j=foo('a');
The lookup for foo starts in namespace A, is resolved to int A::foo(int); and the search for foo stops.
Hope this clears the confusion.

In the standard (§3.4/1)
Name lookup shall
find an unambiguous declaration for the name (see 10.2). 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 (13.1). Overload resolution (13.3) takes place after name lookup has succeeded.
The access rules (Clause 11) are considered only once name lookup and function overload resolution (if
applicable) have succeeded.
Which means the steps are as follows for methods:
First collect all the matching names
Do overload resolution
Check for accessibility
For method, name lookup does not return after finding first match, rather it searches for all matching names. It is clear from the statement Name lookup may associate more than one declaration with a name if it finds the name to be a function name.

Related

Interpretation of [basic.scope.hiding]p2 when unqualified name lookup involves using-directives

There are two types of name hiding in c++:
1) Normal name hiding: [basic.scope.hiding]p1 (http://eel.is/c++draft/basic.scope.hiding#1):
A name can be hidden by an explicit declaration of that same name in a
nested declarative region or derived class ([class.member.lookup]).
2) The special type of name hiding in [basic.scope.hiding]p2 (http://eel.is/c++draft/basic.scope.hiding#2):
A class name ([class.name]) or enumeration name ([dcl.enum]) can be
hidden by the name of a variable, data member, function, or enumerator
declared in the same scope. If a class or enumeration name and a
variable, data member, function, or enumerator are declared in the
same scope (in any order) with the same name, the class or enumeration
name is hidden wherever the variable, data member, function, or
enumerator name is visible.
I'm interested to know about how name hiding interacts with using-directives when unqualified name lookup is performed.
For the first type of name hiding the behaviour is quite clear. This is because [basic.scope.hiding]p1 has been reformulated in terms of the rules in the section [basic.lookup.unqual] (http://eel.is/c++draft/basic.lookup.unqual)
The same has not been done for the second type of name hiding. So the following question now arises:
*) How should this second type of name hiding interact with unqualified name lookup that involves using-directives?
Looking elsewhere in the standard I find [namespace.udir]p2 (http://eel.is/c++draft/namespace.udir#2) and I think this is key to answering this question:
A using-directive specifies that the names in the nominated namespace
can be used in the scope in which the using-directive appears after
the using-directive. During unqualified name lookup
([basic.lookup.unqual]), the names appear as if they were declared in
the nearest enclosing namespace which contains both the
using-directive and the nominated namespace. [ Note: In this context,
“contains” means “contains directly or indirectly”. — end note ]
Applying the as if part of this rule to [basic.scope.hiding]p1 gives consistency with the rules in the section [basic.lookup.unqual]. This application is also consistent with [basic.scope.hiding]p4 (http://eel.is/c++draft/basic.scope.hiding#4) So this looks promising.
Because of this I think we can answer the question *) by similarly applying the as if part of [namespace.udir]p2 to [basic.scope.hiding]p2. This application is also consistent with [basic.scope.hiding]p4. I think this is also the most natural and least complex interpretation of the c++ standard.
The problem however is that Clang and GCC does not make the same interpretation as me. For example:
namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;
int main() { sizeof(i); }
According to my interpretation this program should be well-formed and i should be looked up as the integer variable. Both Clang and GCC disagree with this by giving a name lookup ambiguity.
In the case of Clang this more complex interpretation leads to the following bug:
namespace N { static int i = 1; }
namespace M { struct i {}; }
namespace P {
using N::i;
using M::i;
}
namespace Q { using M::i; }
using namespace P;
using namespace Q;
int main() { sizeof (i); }
Gives no errors, but change
using namespace P;
using namespace Q;
into
using namespace Q;
using namespace P;
and we get name-lookup ambiguity error. GCC is at least consistent here.
Did I interpret the c++ standard correctly?
The key phrases here I believe are:
A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived
class (10.2).
A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member,
function, or enumerator declared in the same scope.
In this example:
namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;
int main() { sizeof(i); }
Both is are declared in different, non-nested scopes, so there is no hiding. Name lookup finds them as if they were declared in ::, but that's not what the rule for hiding stipulates.
Otherwise, we have, from [basic.lookup]:
Name lookup shall
find an unambiguous declaration for the name (see 10.2). Name lookup may associate more than one declaration
with a name if it finds the name to be a function name;
There is no unambiguous declaration in ::, so this code is ill-formed and the error is correct. The same is true for the other example, so the fact that there is some using-declaration ordering for which clang compiles it is a bug.
While this is non-normative, there is an example in [namespace.udir] that makes this interpretation clear:
[ Note: In particular,
the name of a variable, function or enumerator does not hide the name of a class or enumeration declared
in a different namespace. For example,
namespace A {
class X { };
extern "C" int g();
extern "C++" int h();
}
namespace B {
void X(int);
extern "C" int g();
extern "C++" int h(int);
}
using namespace A;
using namespace B;
void f() {
X(1); // error: name X found in two namespaces
g(); // OK: name g refers to the same entity
h(); // OK: overload resolution selects A::h
}
—end note ]
namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;
int main() { sizeof(i); }
This is ill-formed. §7.3.4/6:
If name lookup finds a declaration for a name in two different
namespaces, and the declarations do not declare the same entity and do
not declare functions, the use of the name is ill-formed.
The same applies to your second example. Note that the name hiding rule that applies in e.g.
struct A {} A;
…doesn't apply in your case, as the two is are declared in distinct scopes. Also,
During unqualified name lookup ([basic.lookup.unqual]), the names
appear as if they were declared in the nearest enclosing namespace
which contains both the using-directive and the nominated namespace.
Is irrelevant as well since any ambiguity that name lookup produces, as in your examples with i, is dealt with after lookup - here in e.g. the aforementioned §7.3.4/6.

Unnamed and Named Namespace Resolution

Should a reference to a name that exists in both an unnamed namespace and the local named namespace result in a error for ambiguity or is the resolution well-defined? I'm seeing the following work fine on G++ and Clang, less well on MSVC.
namespace Foo
{
class Bar
{
public:
int x;
};
}
namespace
{
class Bar
{
public:
int y;
};
}
namespace Foo
{
void tester()
{
Bar b;
}
}
int main()
{
Foo::tester();
return 0;
}
GCC and Clang are right. Within Foo::tester, an unqualified use of Bar unambiguously refers to Foo::Bar.
Unqualified lookup is specified by C++11 3.4.1/1:
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 scopes searched for the use of a name in a function are listed in 3.4.1/6:
A name used in the definition of a function [...] that is a member of namespace N [...] shall be declared before its use in the block [...] or, shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N’s enclosing namespaces.
In this case, the function is a member of Foo, so Foo is searched before the enclosing (global) namespace, which includes the unnamed namespace. Foo::Bar is found there, and lookup ends.

Interesting behavior of compiler with namespaces

Assume the following code:
#include <iostream>
using namespace std;
namespace X
{
class A{};
void f(A a){}
void g(int a){}
}
int main()
{
X::A a;
f(a);
g(5);
}
When I compile the code, the following compile error occurs:
main.cpp: In function 'int main()':
main.cpp: error: 'g' was not declared in this scope
So the function f is compiled perfectly, but g isn't. How? Both of them belong to the same namespace. Does the compiler deduce that function f belongs to the X namespace from the argument of type X::A? How does compiler behave in such cases?
X::A a;
f(a);
works because of Argument-Dependent Lookup (Also known as Koenig Lookup). a is an object of class A inside namespace X, when compiler searches a match-able function f, it will look into namespace X in this case. See Argument Dependent Lookup for more information.
This works for the function call expression:
f(a);
because the namespace that X::A belongs to is included in the lookup for the function f due to argument dependent lookup(ADL), cppreference explains ADL as follows:
Argument-dependent lookup, also known as ADL, or Koenig lookup, is the
set of rules for looking up the unqualified function names in
function-call expressions, including implicit function calls to
overloaded operators. 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.
Argument-dependent lookup makes it possible to use operators defined
in a different namespace
This is covered in the draft C++ standard section 3.4.2 Argument-dependent name lookup:
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered
during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope
friend function or function template declarations (11.3) not otherwise visible may be found
and goes on to say:
For each argument type T in the function call, there is a set of zero or more associated namespaces and a
set of zero or more associated classes to be considered. The sets of namespaces and classes is determined
entirely by the types of the function arguments (and the namespace of any template template argument).
and includes the following bullet:
If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a
member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces
of which its associated classes are members.[...]
and further down provides a similar example to your problem:
namespace NS {
class T { };
void f(T);
void g(T, int);
}
NS::T parm;
void g(NS::T, float);
int main() {
f(parm); // OK: calls NS::f
extern void g(NS::T, float);
g(parm, 1); // OK: calls g(NS::T, float)
}
The function call expression:
g(5);
does not work because ADL does not add any namespaces for arguments that are fundamental types.
Herb Sutter covers ADL in Gotw #30 and in What's In a Class? - The Interface Principle.
When the code f(a), the compiler finds the function void f(A a){} in the namespace X because of the ADL (argument dependent lookup, also known as Koenig lookup).
A is declared in the namespace X, hence when the compiler needs to look up the definition of f, it includes possibilities from that namespace because the object a of type A is in that namespace (as declared X::A a;).
On the other hand, int is not declared in the namespace X, so the namespace X is not included in the lookup. Since no corresponding function for f is found, it fails to compile.

Is usual unqualified lookup for the function name differs from lookup for variable name?

Consider the following code:
#include <iostream>
int a=5;//1
extern int a;//2
int main(){ cout << a; }
During unqualified name lookup declaration#1 will be found and unqualified name lookup ends just after #1 is found.
But consider another example:
#include <iostream>
void foo() { cout << "zero arg"; }
void foo(int a) { cout << "one arg"; }
int main(){ foo(4); }
In that case void foo();'s definition will be found first. But unqualified name lookup doesn't end. Why? Where is it specified in the standard? In general, I'm interested in:
When does unqualified name lookup ends for the postfix-expression for the function call?
Note: I know what does ADL mean. The set of declarations produced by ADL is empty in that case.
UPD:
But if we write the following:
int foo(int a) { return 0; }
namespace A
{
int foo() { return 1; }
int a= foo(5); //Error: to many arguments
}
This implies that enclosing namespace does not considering. I would like to know where is it specified too.
In that case void foo();'s definition will be found first. But unqualified name lookup doesn't end. Why?
Because standard says:
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 (13.1). Overload resolution (13.3) takes place after name lookup has succeeded.
So in case of function, name lookup does not end after finding first match, it collects all the names, and then overload resolution occurs.
Update
For the updated question, you are back to your previous question
name lookup ends as soon as a declaration is found for the name.
So as soon as foo is found in inner scope, no further search is conducted.
But if you use namespace qualified name, then the specified namespace will be searched:
int a = ::foo(5); // finds foo in global namespace.
So in general, for unqualified search, first search is conducted in the current scope, if not found then next enclosing scope and so forth. However, as soon as a name is found, search ends, it does not matter if the name is usable or not. It means, for function, it may not be the correct one, may be there is an overloaded one in enclosing scope which is correct, but search does not continue to that.

Unqualified name lookup applied instead of argument-dependent name lookup

Consider an example from the standard sec 3.4.1/3:
typedef int f;
namespace N
{
struct A
{
friend void f(A &);
operator int();
void g(A a)
{
int i = f(a);// f is the typedef, not the friend
// function: equivalent to int(a)
}
};
}
f(a) is postfix expression. How does compiler determine that f(a) is not a function call? I'm wondering when we have no error like f previously declared of typedef int f; as in the following example:
#include <stdio.h>
typedef int foo; //error: previous declaration of ‘typedef int foo’
class B
{
public:
friend void foo(B b){ printf("3"); } //error: ‘void foo(B)’ redeclared as different kind of symbol
static const int c=42;
};
int main(){ }
(In my version of the C++11 document the example is presented in 3.4.1/3).
The 3.4.1/3 clearly states that for the purposes of parsing, in order to perform the initial determination of whether this is a postfix expression or function call, a usual name lookup is performed. "Usual" means that the lookup is performed as described in the rest of 3.4.1 and no ADL is used at that initial stage. 3.4.1/3 explicitly says that "The rules in 3.4.2 have no effect on the syntactic interpretation of an expression." (3.4.2 is ADL).
In this example, while parsing f(a) the usual lookup is used to look for name f. It finds the global typedef-name ::f and nothing else. This means that f(a) is treated as a postfix expression (a cast), not as a function call. Note, that friend declaration of function f inside A refers to function N::f, but it does not introduce a declaration of N::f into N. Since N::f function is not explicitly declared in N (it is not visible in N), the usual lookup does not see it. It only sees the global ::f, which is a typedef-name.
If you want the usual name lookup to find the function in the first example, you have to declare that function in N explicitly
typedef int f;
namespace N
{
struct A; // <- added
void f(A &); // <- added
struct A
{
friend void f(A &);
...
Now the declaration of N::f is visible in N. Now the usual name lookup will find N::f and treat that f(a) as a function call from the very beginning.
Your second example is seriously different from the first. You have no extra namespace there. Because of that the friend function declaration in B refers to the global ::foo and claims that foo is a function. But the global ::foo is already declared as a typedef-name. This contradiction is exactly what causes the error.
(Amusingly, C++03 version of the standard contained an example in 3.4.1/3, which was essentially equivalent to your second example. I.e. the example in the standard was ill-formed. This is reported as Defect #139 of the standard.)