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.
Related
Consider the following program:
namespace foo {
namespace sub {
int f();
} // namespace sub
} // namespace foo
namespace bar {
namespace sub {
int g() {
using namespace foo;
return sub::f() + 1;
}
} // namespace sub
} // namespace bar
I expect this to compile, but - it doesn't:
$ g++-6 -c a.cpp
a.cpp: In function ‘int bar::sub::g()’:
a.cpp:12:9: error: ‘f’ is not a member of ‘bar::sub’
return sub::f() + 1;
^~~
a.cpp:12:9: note: suggested alternative:
a.cpp:3:5: note: ‘foo::sub::f’
int f();
^
no luck with clang either:
$ clang++-6.0 -c a.cpp
a.cpp:12:9: error: no member named 'f' in namespace 'bar::sub'; did you mean 'foo::sub::f'?
return sub::f() + 1;
^~~~~~
foo::sub::f
a.cpp:3:5: note: 'foo::sub::f' declared here
int f();
^
1 error generated.
and it knows which function I want, too!
Now, I understand that things could be ambiguous if I had both a foo::sub::f and a bar::sub::f here. But - why is bar::sub "hiding" foo::sub even when I explicitly ask to use foo::sub functions?
To be clear about what an answer might:
An explanation why this is the (most) reasonable behavior and my expectation is unreasonable.
The rationale for it being this way in the C++ standard.
A quotation from standard saying this needs to be the case; maybe the context will help me understand why this was decided.
Motivation: I've written my code so that the last namespace before the function is part of the method name, in the sense that you wouldn't understand what the function does without prepending the namespace. So instead of saying sub_f() like I would in C, I want to be able to say sub::f(). It's proving difficult to do so without prepending a much longer path of namespaces.
[namespace.udir] says (emphasis mine):
-2- 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 (6.4.1), 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]
In your example "the names in the nominated namespace" is just foo::sub because that's the only name declared in namespace foo, and the "nearest enclosing namespace which contains both the using-directive and the nominated namespace" is the global namespace. So foo::sub appears (for the purposes of name lookup) as though it were in the global namespace, like this:
namespace sub {
int f();
} // namespace sub
namespace bar {
namespace sub {
int g() {
return sub::f() + 1;
}
} // namespace sub
} // namespace bar
Now it should be more obvious that sub::f won't find anything. Name lookup for sub::f starts by looking for sub. It doesn't find it in the enclosing namespace (which is bar::sub) so it looks in the next innermost enclosing scope (which is bar) and there it finds sub. At that point name lookup for sub stops, it doesn't look in the global namespace where it would find foo::sub made visible by the using-directive.
The next step of name lookup tries to find f in the scope it found for sub, but there's no f in the namespace it found, so name lookup fails.
Using-directives do not work like adding a using-declaration for every member of the namespace, they are "weaker" than using-declarations. The reason for that is so that names really declared in a namespace take priority over names simply made visible by a using-directive. rodrigo's answer to a related question explains that in more detail.
I think the relevant part of the standard that prevents what you are trying to do is this:
6.3.10 Name hiding [basic.scope.hiding]
...
4 During the lookup of a name qualified by a namespace name, declarations that would otherwise be made visible by a using-directive can be hidden by declarations with the same name in the namespace containing the using-directive;
You have sub in both foo and bar namespaces. And the sub in bar is hiding the sub in foo in spite of the using directive. And that is the reason why the f() in foo::sub is also not visible.
An answer to your first point:
What happens when you add to your program a:
namespace sub
{
int f();
}
What should now the compiler choose:
::sub::f() or (using ::foo::)sub::f() ?
According to this question it is valid to define class methods after a using directive, instead of enclosing them within a namespace block.
However, that seems not to be the case for ordinary functions. Consider:
Greeting.hh
#pragma once
namespace NS
{
class Greeting
{
public:
void hello();
};
void otherHello();
}
Greeting.cc
#include "Greeting.hh"
#include <iostream>
using namespace NS;
void Greeting::hello()
{
std::cout << "Greeting::hello" << std::endl;
}
void otherHello()
{
std::cout << "otherHello" << std::endl;
}
main.cc
#include "Greeting.hh"
int main()
{
NS::Greeting o;
o.hello();
NS::otherHello();
}
This won't compile, yielding the following error message:
undefined reference to `NS::otherHello()'
Further inspection indicates that otherHello's symbol is not preceded by the namespace, while Greeting::hello's is:
g++ -std=c++14 -pedantic -Wall -c Greeting.cc
nm -C Greeting.o | grep T
000000000000002a T otherHello()
0000000000000000 T NS::Greeting::hello()
Does this contradict with the Standard reference from the accepted answer?
"During unqualified name lookup (3.4.1), the names appear as if they
were declared in the nearest enclosing namespace which contains both
the using-directive and the nominated namespace."
What's important to remember is that
Function declarations in different namespaces don't interfere with each other.
A definition of a function is also a declaration.
[namespace.def/4]
The enclosing namespaces of a declaration are those namespaces in
which the declaration lexically appears, except for a redeclaration of
a namespace member outside its original namespace (e.g., a definition
as specified in [namespace.memdef]). Such a redeclaration has the same
enclosing namespaces as the original declaration.
So let's look at the otherHello definition. Where does it lexically appear? In the global namespace of course. That's also the point of declaration for it. Which means the enclosing namespace is the global one, and you end up with a declaration of ::otherHello.
So no, this doesn't contradict the standard quote from the accepted answer to the other question. Member functions can be defined outside of the class, so long as they are qualified by their class name ([class.mfct/4]):
If the definition of a member function is lexically outside its class
definition, the member function name shall be qualified by its class
name using the :: operator.
So we need only ask, does Greeting name the same class as NS::Greeting? Why, yes it does. The using directive is responsible for that.
I'll add this segment in the hope of clarifying. Consider this code snippet:
namespace NS1 {
namespace NS2 {
void hello();
}
}
using namespace NS1;
void NS2::hello() {
}
int main() {
NS1::NS2::hello();
return 0;
}
When the compiler encounters NS2::hello being defined it preforms name lookup for that declarator id. According to [basic.lookup.qual/3]:
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.
So NS2 is looked up in the defining scope (the global one), and according to the unqualified name lookup rule you quoted, it is found and resolved as NS1::NS2. That's how NS2::hello is associated with NS1::NS2::hello and resolved as defining it.
In the global namespace of the OP, otherHello isn't preceded by anything. Therefore name lookup doesn't occur. It immediately defines that function in the enclosing namespace, as I previously quoted.
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.
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.
Why the following code is compiled successfully:
#include <stdio.h>
namespace B
{
void foo();
int i=3;
}
void B::foo()
{
i=65;
}
int main(){ }
and the following is not compiled succefully:
#include <stdio.h>
namespace B
{
void foo()
{
i=65;//error: ‘i’ was not declared in this scope
}
int i=3;
}
int main(){ }
I would like to find a reference from the standard clarified this moment.
Since you want quotes 3.4.1 [basic.unqual.lookup]:
/4 A name used in global scope, outside of any function, class or user-declared namespace, shall be declared before its use in global scope.
/6 A name used in the definition of a function following the function’s declarator-id28 that is a member of namespace N (where, only for the purpose of exposition, N could represent the global scope) shall be declared before its use in the block in which it is used or in one of its enclosing blocks (6.3) 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 the first example, foo is declared in namespace B, so will search for an i inside its namespace first (and finds such an i, because the implementation of foo is AFTER the namespace declaration of i). In the second example you are declaring i after the definition of foo, so f does not "see" i.