I want to understand the namespace qualified name lookup rule. I'm trying to do that on the example:
namespace A
{
int a=::b; //error: ‘::b’ has not been declared
}
int b=6;
There is a quote which I rely in my reasoning (3.4.3.2/2 N3797):
For a namespace X and name m, the namespace-qualified lookup set S(X,
m) is defined as follows: Let S (X, m) be the set of all declarations
of m in X and the inline namespace set of X (7.3.1). If S (X, m) is
not empty, S(X, m) is S (X, m); otherwise, S(X, m) is the union of
S(Ni , m) for all namespaces Ni nominated by using-directives in X and
its inline namespace set.
Let X be a global scope. We have that S(X,b)={int b=6}. This implies that name lookup must be success. But in fact, the program is ill-formed. Might I don't understood this rule correctly?
b is in global scope but it must be declare before where you are using it.
like
int b=6;
namespace A
{
int a=::b;
}
(N 3690 Draft)
3.4.1 Unqualified name 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.
Related
I just went through a case where i don't need to prefix the namespace within a function that is itself declared within the namespace
Consider this:
namespace fs
{
void ftest();
typedef int uint;
}
void fs::ftest()
{
uint p = 2; // no prefix fs:: needed
}
This actually doesn't really shock me, but i'd like to have some insights : why does in actually work? Obviously this isn't koenig lookup here.
I'm using VS 2013
This is basic unqualified lookup. The relevant rule is in [basic.lookup.unqual]:
A name used in the definition of a function following the function’s declarator-id 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. [ Example:
namespace A {
namespace N {
void f();
}
}
void A::N::f() {
i = 5;
// The following scopes are searched for a declaration of i:
// 1) outermost block scope of A::N::f, before the use of i
// 2) scope of namespace N
// 3) scope of namespace A
// 4) global scope, before the definition of A::N::f
}
—end example ]
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.
Is the following program well-formed or ill-formed according to the c++ standard?
namespace N { int i; }
using namespace N;
using ::i;
int main() {}
I get different results with different compilers:
Clang (http://melpon.org/wandbox/permlink/c8vl7XbumyyS6vsw): No errors.
GCC (http://melpon.org/wandbox/permlink/immhNeWFCMcCA800): Error: 'i' not declared.
Is this program well-formed or ill-formed according to the c++ standard? References to the c++ standard needed.
I'm trying to figure out for which compiler I should file a bug.
Well-formed.
The using-directive doesn't introduce the name i in the global namespace, but it is used during lookup. The using-declaration uses qualified lookup to find i; qualified lookup in the presence of using-directives is specified in [3.4.3.2 p1, p2] (quotes from N4527, the current working draft):
If the nested-name-specifier of a qualified-id nominates a namespace
(including the case where the nested-name-specifier is ::, i.e.,
nominating the global namespace), the name specified after the
nested-name-specifier is looked up in the scope of the namespace. [...]
For a namespace X and name m, the namespace-qualified lookup set
S(X,m) is defined as follows: Let S'(X,m) be the set of all
declarations of m in X and the inline namespace set of X (7.3.1). If
S'(X,m) is not empty, S(X,m) is S'(X,m); otherwise, S(X,m) is the
union of S(Ni,m) for all namespaces Ni nominated
by using-directives in X and its inline namespace set.
So, for qualified lookup, the first step is to look for declarations of i made directly in the namespace indicated by the nested-name-specifier (:: in this case). There are no such declarations, so lookup then proceeds to the second step, which is to form the set of all declarations of i found by qualified lookup in all namespaces nominated by using-directives in the global namespace. That set is comprised of N::i, which is the result of name lookup, and is introduced as a name in global namespace by the using declaration.
I find it worth noting (although pretty obvious) that this definition of qualified lookup is recursive: using the notation in the quote, qualified lookup in each namespace Ni will first look for declarations made directly in Ni, then, if none is found, will in turn proceed to look in the namespaces nominated by using-directives in Ni, and so on.
For what it's worth, MSVC accepts the code as well.
GCC is wrong. Qualified name lookup does consider N::i; §3.4.3.2/2 & /3:
For a namespace X and name m, the namespace-qualified lookup set
S(X, m) is defined as follows: Let S'(X, m) be the set of all
declarations of m in X and the inline namespace set of X
(7.3.1). If S'(X, m) is not empty, S(X, m) is S'(X, m);
otherwise, S(X, m) is the union of S(Ni, m) for all namespaces Ni nominated by using-directives in X
and its inline namespace set.
Given X::m (where X is a user-declared namespace), or given ::m (where
X is the global namespace), […] if S(X, m) has exactly one member, or if the
context of the reference is a using-declaration (7.3.3), S(X, m) is
the required set of declarations of m.
There is only one namespace nominated by a using-directive in your program: N. It's therefore included in the union and ::i is resolved to N::i.
Note that GCC is inconsistent with its lookup: Using ::i in another context is fine.
namespace N { int i; }
using namespace N;
int main() {
::i = 5;
}
This compiles. The only difference that a using-declaration makes as a context is shown in the above quote and does not affect the established conclusion.
Consider the following two code snippets:
Snippet A
#include <iostream>
namespace
{
bool foo = false;
}
bool foo = true;
int main()
{
std::cout << foo << std::endl;
}
Snippet B
#include <iostream>
namespace A
{
namespace
{
bool foo = false;
}
bool foo = true;
}
int main()
{
std::cout << A::foo << std::endl;
}
In Snippet A, foo's usage inside int main() is ambiguous, whilst in Snippet B it is not. Why is this the case?
Related: Anonymous Namespace Ambiguity
The behavior of unnamed namespaces is specified in §7.3.1.1 [namespace.unnamed]/p1:
An unnamed-namespace-definition behaves as if it were replaced by
inline_opt namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
where inline appears if and only if it appears in the
unnamed-namespace-definition, all occurrences of unique in a translation unit are replaced by the same identifier, and this
identifier differs from all other identifiers in the entire program.
In particular, note that the declarations inside the unnamed namespace is made visible in the surrounding scope via a using-directive using namespace unique;.
In Snippet A, foo is unqualified, so the compiler performs unqualified name lookup (§3.4.1 [basic.lookup.unqual]). Relevant here is paragraph 2 of the subclause:
2 The declarations from the namespace nominated by a using-directive
become visible in a namespace enclosing the using-directive; see
7.3.4. For the purpose of the unqualified name lookup rules described in 3.4.1, the declarations from the namespace nominated by the
using-directive are considered members of that enclosing namespace.
Hence, unqualified name lookup finds both declarations of foo, and the name is ambiguous.
In Snippet B, A::foo is qualified, so qualified name lookup rules apply. Since A is a namespace, the applicable subclause is §3.4.3.2 [namespace.qual]. As relevant here, the rule is specified in paragraph 2 of that subclause:
For a namespace X and name m, the namespace-qualified lookup set
S(X,m) is defined as follows: Let S'(X,m) be the set of all
declarations of m in X and the inline namespace set of X
(7.3.1). If S'(X,m) is not empty, S(X,m) is S'(X,m); otherwise,
S(X,m) is the union of S(Ni,m) for all namespaces Ni nominated
by using-directives in X and its inline namespace set.
In other words, qualified name lookup considers namespaces nominated by using-directives only if the name is not found in the specified namespace and its inline namespace set. Here, the name foo is found in namespace A, so the unnamed namespace nominated by the using-directive is not considered, and there's no ambiguity.
If you write ::foo instead of foo in Snippet A, then qualified lookup rules would apply instead, and there would once again be no ambiguity.
I've written the following code:
#include <iostream>
inline namespace M
{
int j=42;
}
int main(){ std::cout << j << "\n"; } //j is unqualified name here.
//Hence, unqualified name lookup rules will be applied.
//This implies that member of inline namespace shall not be considered.
//But it is not true
And it works fine. But I'm expected that the that program is ill-formed. It is because the Standard said (N3797, sec. 7.3.1/7):
Finally, looking up a name in the enclosing namespace via explicit
qualification (3.4.3.2) will include members of the inline namespace
brought in by the using-directive even if there are declarations of
that name in the enclosing namespace.
Also the section 3.4.1/6 does not said anything about involving of inline namespace in the unqualified name lookup:
A name used in the definition of a function following the function’s
declarator-id 28 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.
It is a g++ bug or I understood that rules incorrectly?
There's no bug..
No, it's not a bug in neither g++ (or clang++) which has the behavior described, the compiler is supposed to find j.
inline namespace N {
int j;
}
int main () {
int a = j; // legal, `j` == `N::j`
}
What does the Standard say?
You are missing a very important section of the standard, namely 7.3.1§8, where it states that the enclosing namespace of an inline namespace implicitly has a using directive that refers to the inline namespace.
[7.3.1]p8 namespace definition [namespace.def]
Members of an inline namespace can be used in most respects as thought they were members of the enclosing namespace. Specifically, the inline namespace and its enclosing namespace are both added to the set of associated namespaces used in argument-dependent lookup (3.4.2) whenever one of them is, and a using-directive (7.3.4) that names the inline namespace is implicitly inserted into the enclosing namespace as for an unnamed namespace (7.3.1.1).
Elaboration
This means that our previous example is semantically equivalent to the below, where we have introduced a using-directive to bring the names from our nested namespace into the global namespace:
inline namespace N {
int j;
}
using namespace N; // the implicit using-directive
int main () {
int a = j; // legal
}