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 ]
Related
Can someone explain why I can't define variable that was declared in anonymous namespace as global variable in another place?
#include <iostream>
namespace {
extern int number;
}
int number = 123;
void g() {
std::cout << number;
}
Compiler says that "Reference to 'number' is ambiguous" but I can't understand why it recognises declaration and definition as different things? Thank you in advance.
In general, the name being declared by a declaration is not looked up—after all, you can’t rely on finding a previous declaration when a name is first introduced. Of course, there is a similar process that traps things like
int x;
float x;
However, since it isn’t lookup it is not affected by using at all (including for an unnamed namespace). Another way of describing this distinction is that a declaration puts entities into namespaces and thus need not consider any other namespace in order to decide where to put an entity.
There are also cases where lookup does occur for (what might be) a declarator-id:
namespace N {using X=int;}
// using namespace N;
struct A {
A(X()); // ?
};
A has a member function with no parameters returning an A named X (with meaningless parentheses around its declarator); however, with the using-directive it instead has a constructor that takes a pointer to a function of no parameters returning an int. Similarly, in a declaration beginning
template<>
struct X<…
X must be fully looked up, even though a declaration of an explicit specialization must inhabit the same scope as the primary template (with leeway for inline namespaces), because it might continue
template<>
struct X<int>::Y<char> {…};
and not be a specialization of X at all.
For the unqualified name-lookup the compiler considers also nested unnamed namespaces in the global namespace,
You declared two different objects with the same name in the global namespace and in the nested unnamed namespace.
The using directive for unnamed namespace is implicitly inserted in the enclosing namespace.
Consider the following demonstration program
#include <iostream>
namespace N
{
extern int number;
}
using namespace N;
int number = 123;
int main()
{
std::cout << number << '\n';
}
The compiler will issue an error due to the ambiguity for the unqualified reference to the name number in this statement
std::cout << number << '\n';
The similar situation takes place with an unnamed namespace because the using directive is implicitly inserted in the enclosing namespace.
From the C++ 20 Standard (9.8.2 Namespace definition)
7 Members of an inline namespace can be used in most respects as
though 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 (6.5.3)
whenever one of them is, and a using directive (9.8.4) that names
the inline namespace is implicitly inserted into the enclosing
namespace as for an unnamed namespace (9.8.2.2).
3.4.1/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.
[ 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
}
I believe 3.4.1/6 ignores the lookup of a name used in a function-body that is found in the function's parameter-declaration-clause, as shown below:
void f(int i) { std::cout << i << '\n'; }
That paragraph is not relevant to your example, because in your example i is not "A name [...] that is a member of namespace N"
The start of the sentence should be parsed like this:
Let F be a function.
Let N be a namespace.
Let X be a name.
If X is used in the definition of F after F’s declarator-id and X is a member of namespace N ...
Edit: I've been persuaded by the comments that my interpretation above is wrong. I've created https://github.com/cplusplus/draft/issues/451 to request that paragraph be rephrased.
However this is wrong too:
I believe 3.4.1/6 ignores the lookup of a name used in a function-body that is found in the function's parameter-declaration-clause,
Firstly, obviously i is found by name lookup, otherwise function parameters would be unusable!
Secondly, 3.3.3 [basic.scope.block]/2 says that i has "block scope" beginning at its point of declaration and ending at the closing brace of the function definition. 3.4.6/6 says "shall be declared before its use in the block in which it is used" and that is true in this case. i is declared before it is used (its point of declaration is before it is used) and is declared in the block in which it is used (the outermost block scope of the function).
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
}
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.
I was looking over section 7.3.1.1 in the C++03 standard expecting to find some description of the access rules for items defined in an unnamed namespace.
The rules seem to be a little different for unnamed namespaces, since you cannot fully qualify access to items in one. I know that at least within the same translation unit, one can access items in an unnamed namespace as if they were not in a namespace. For example:
namespace {
int foo;
}
void something()
{
foo = 4;
}
If the namespace had a name, you could not do this. So, where are the rules defined in the standard for these exceptional rules that apply to unnamed namespaces?
An anonymous namespace is basically treated as:
namespace unique_per_TU
{
// Stuff
}
using namespace unique_per_TU;
I'll try to find the reference here in a minute.
EDIT:
It appears you already found it in 7.3.1.1/1
An unnamed namespace definition behaves as if it were replaced by
namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespacebody }
where 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.
The "fake" using already brings the namespace members into the global namespace as you discovered.
Apart from the standard quote which defines Unnamed Namespaces in 7.3.1.1/1,
This is explicitly stated in one of the examples in
3.3.5/1 Namespace Scope:
The declarative region of a namespace-definition is its namespace-body. The potential scope denoted by an original-namespace-name is the concatenation of the declarative regions established by each of the namespace-definitions in the same declarative region with that original-namespace-name. Entities declared in a namespace-body are said to be members of the namespace, and names introduced by these declarations into the declarative region of the namespace are said to be member names of the namespace. A namespace member name has namespace scope. Its potential scope includes its namespace from the name’s point of declaration (3.3.1) onwards; and for each using-directive (7.3.4) that nominates the member’s namespace,
the member’s potential scope includes that portion of the potential scope of the using-directive that follows the member’s point of declaration.
>[Example:
namespace N {
int i;
int g(int a) { return a; }
int j();
void q();
}
namespace { int l=1; }
// the potential scope of l is from its point of declaration
// to the end of the translation unit
namespace N {
int g(char a) // overloadsN::g(int)
{
return l+a; // l is from unnamed namespace
}
int i; // error: duplicate definition
int j(); // OK: duplicate function declaration
int j() // OK: definition ofN::j()
{
return g(i); // callsN::g(int)
}
int q(); // error: different return type
}
—end example]
Note the wordings:
the potential scope of l is from its point of declaration to the end of the translation unit