I'm interested in a formal couplig between a point of declaration and a name-lookup concepts. In particular, when a nested-name-specifier denoted a namespace, an unqualified name lookup produce a set of declaration as follows: N4296::3.4.3.2 [namespace.qual]
For a namespace X and name m, the namespace-qualified lookup set
S(X,m) is defined as follows: Let S0(X,m) be the set of all
declarations of m in X and the inline namespace set of X (7.3.1). If
S0(X,m) is not empty, S(X,m) is S0(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 me provide a couple examples:
1.
#include <iostream>
namespace A
{
int b = 42;
}
int a = A::a; //Error
namespace A
{
int a = 24;
}
int main(){ std::cout << a << std::endl; }
DEMO
2.
#include <iostream>
namespace A
{
int b = 42;
}
namespace A
{
int a = 24;
}
int a = A::a; //OK
int main(){ std::cout << a << std::endl; }
DEMO
The rule I provided has nothing to do with the point of declaration concept, but in fact we can see that it does. So the Standard implicitly assumes that the name's m point of declaration should be before the point where the name is used. I think it should be specified explicitly. Maybe I lost the clause where it was specified... if so, couldn't you point me out to that one?
From [basic.scope.namespace] (§3.3.6/1), emphasis mine:
A namespace
member name has namespace scope. Its potential scope includes its namespace from the name’s point of
declaration (3.3.2) onwards
a can only be found in namespace A after it is declared. So example (1) is invalid because a hasn't been declared yet and example (2) is valid because it has been.
Related
[basic.scope.hiding]/4 says:
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; see [namespace.qual].
I've failed the come up with an example, where [basic.scope.hiding]/4 actually in effect, and makes a difference (because other rules, like [namespace.udir]/2 already handles the situtation).
Can you give a simple (easy to understand) example of this rule?
The difference is simply in qualified vs. unqualified lookup:
namespace A {
int x;
int y;
}
namespace B {
using namespace A;
int x;
int test1() {
return x + y; // [namespace.udir]/2
}
}
int test2() {
return B::x + B::y; // [basic.scope.hiding]/4
}
Consider the code:
template<typename T>
class Foo{};
namespace X
{
class X{};
}
using namespace X; // now both class X and namespace X are visible
Foo<X::X> f()
{
return {};
}
int main() {}
gcc5.2 compiles the code with no errors whatsoever. However clang spits the error:
error: 'X' is not a class, namespace, or enumeration
Foo f()
error: reference to 'X' is ambiguous
Is the code syntactically valid, according to the C++ standard? Or is just a gcc bug? Removing the qualified name X::X and using Foo<X> instead makes gcc choke also
error: template argument 1 is invalid
Foo f()
[namespace.udir]/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.
For the first X in X::X, both the namespace and the class are considered. However, the name of the namespace resides in the global namespace while the class resides in namespace X; Hence the above quote applies, Clang is therefore correct. (This also occurs when just writing X, clearly).
::X removes this ambiguity. Lookup does not proceed into the namespace anymore. [namespace.qual]/2:
For a namespace X and name m, the namespace-qualified lookup set
S(X, m) is defined as follows: Let
S0(X, m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X, m) is
not empty, S(X, m) is S0(X, m); otherwise, […]
Here, X is the global namespace and m is "X". Clearly, the declaration of our namespace is found, so lookup is definite here.
Not a complete answer but that is a clear situation that shows even declaring using namespace, for objects with the same name as the namespace you need to declare the namespace.
#include <iostream>
#include <string>
namespace test
{
void function1(void){std::cout << "Function inside the namespace" << std::endl;}
class test
{
public:
static void function1(void){std::cout << "Function inside the class" << std::endl;}
};
};
using namespace test;
int main()
{
function1();
test::function1();
test::test::function1();
}
Output (GCC 4.9.2)
"Function inside the namespace"
"Function inside the namespace"
"Function inside the class"
Consider the following Code Snippet
#include <iostream>
#include <memory>
namespace Foo {
void bar() {
std::cout<<"FOO::BAR"<<std::endl;
}
}
namespace Spam {
void bar() {
std::cout<<"SPAM::BAR"<<std::endl;
}
}
namespace fallbacks {
using Foo::bar;
}
namespace Spam {
using namespace fallbacks;
}
int main() {
Spam::bar();
}
Output
SPAM::BAR
I understand that in this case, if Spam contains the member it will refer to it. However if it doesn't , then the using directive's name will be found and refer to fallbacks::bar.
But I cannot find any authentic source to back the above statement.
Section 3.4.3 of the standard describes qualified name lookup. In particular, section 3.4.3.2 describes the lookup of namespace members.
3.4.3.2.2: 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(N_i,m) for all namespaces
N_i nominated by using-directives in X and its inline namespace set.
(Source: ISO/IEC 14882:2011: C++ Standard)
The following example is given:
int x;
namespace Y {
void f(float);
void h(int);
}
namespace Z {
void h(double);
}
namespace A {
using namespace Y;
void f(int);
void g(int);
int i;
}
namespace B {
using namespace Z;
void f(char);
int i;
}
namespace AB {
using namespace A;
using namespace B;
void g();
}
void h()
{
AB::g(); // g is declared directly in AB,
// therefore S is { AB::g() } and AB::g() is chosen
AB::f(1); // f is not declared directly in AB so the rules are
// applied recursively to A and B;
// namespace Y is not searched and Y::f(float)
// is not considered;
// S is { A::f(int), B::f(char) } and overload
// resolution chooses A::f(int)
AB::f(’c’); // as above but resolution chooses B::f(char)
AB::x++; // x is not declared directly in AB, and
// is not declared in A or B , so the rules are
// applied recursively to Y and Z,
// S is { } so the program is ill-formed
AB::i++; // i is not declared directly in AB so the rules are
// applied recursively to A and B,
// S is { A::i , B::i } so the use is ambiguous
// and the program is ill-formed
AB::h(16.8); // h is not declared directly in AB and
// not declared directly in A or B so the rules are
// applied recursively to Y and Z,
// S is { Y::h(int), Z::h(double) } and overload
// resolution chooses Z::h(double)
}
(Source: ISO/IEC 14882:2011: C++ Standard)
In your example, if Spam contains bar, the set S contains {Spam::bar} and lookup stops. If the namespace Spam does not contain bar, any namespaces or bars declared via using directives inside Spam will be searched, and this logic is applied recursively until either:
A namespace is found that contains bar, or
the possible search paths are exhausted, in which case the program is ill-formed.
The corresponding name look-up of qualified names is described in the following paragraphs of section 3.4.3.2 Namespace members of the C++ Standard
2 For a namespace X and name m, the namespace-qualified lookup set S(X,m) is defined as follows: Let S0(X,m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X,m) is not empty, S(X,m) is S0(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.
3 Given X::m (where X is a user-declared namespace), or given ::m (where X is the global namespace), if S(X,m) is the empty set, the program is ill-formed. Otherwise, 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. Otherwise if the use of m is not one that allows a unique declaration to be chosen from S(X,m), the program is ill-formed.
In your case if to follow the quote "Let S0(X,m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X,m) is not empty, S(X,m) is S0(X,m); " S( Spam, bar ) consists of one declaration of bar in Spam. And this declaration is the only declaration in Spam. so this name will be found.
For practice, I wrote some template functions whose names are the same as the stl algorithms. But my code can not compile
error: Call to < algorithm_name > is ambiguous.
I only included using std::necessary_names; in my code rather than using namespace std;.
Usually when you have using, the "used" name takes precedence:
namespace N { int x = 0; }
int x = 1;
int main() {
using N::x;
cout << x;
}
// Output: 0
However, Argument-Dependent Lookup can mess this up:
namespace N {
struct T {};
void f(T) {}
}
namespace M {
void f(N::T) {}
}
int main() {
using M::f;
N::T o;
f(o); // <--- error: call of overloaded 'f(N::T&)' is ambiguous
}
So, if you are having trouble, qualify your own namespace (in this example, M) explicitly:
namespace N {
struct T {};
void f(T) { cout << "N::f"; }
}
namespace M {
void f(N::T) { cout << "M::f"; }
}
int main() {
using M::f;
N::T o;
M::f(o); // <--- Output: "M::f"
}
In a somewhat bizarre twist, you can also use parentheses to prevent ADL:
namespace N {
struct T {};
void f(T) { cout << "N::f"; }
}
namespace M {
void f(N::T) { cout << "M::f"; }
}
int main() {
using M::f;
N::T o;
(f)(o); // <--- Output: "M::f"
}
Explanation
[n3290: 3.4.1/1]: [re: unqualified name lookup] In all the cases
listed in 3.4.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. If no declaration is
found, the program is ill-formed.
[n3290: 3.4.1/2]: [i.e. first priority] 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.
[n3290: 3.4.2/1]: [re: argument-dependent 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 declarations (11.3) not
otherwise visible may be found. These modifications to the search
depend on the types of the arguments (and for template template
arguments, the namespace of the template argument).
i.e. Normal lookup stops at the name that you brought into scope with using, but when ADL comes into play, other names are also added to the candidate set, causing an ambiguity between two names.
It's better to declare your own version in a namespace; so that such problem would not occur.
namespace MySTL
{
template<typename T, ... > // ... means other template params
class vector;
template<typename T, ... >
class queue;
...
}
now you can do,
using std::vector;
which will not collide with MySTL::vector.
Chances are that you are hitting a problem with Argument Dependent Lookup. When you pass a type that is defined within a namespace to an unqualified function, the namespaces of all the arguments are implicitly added to the lookup set, and that might cause collisions. You can try to qualify your own algorithm calls to inhibit ADL from kicking in.
namespace n {
struct test {};
void foo( test const & ) {}
};
int main() {
n::test t;
foo( t ); // Will find n::foo as the argument belongs to n namespace
}
A point from the ISO C++ draft (n3290): 3.4.3.2/1 Namespace members
If the nested-name-specifier of a qualified-id nominates a namespace,
the name specified after the nested-name-specifier is looked up in
the scope of the namespace. If a qualified-id starts with ::, the
name after the :: is looked up in the global namespace. In either
case, the names in a template-argument of a template-id are looked up
in the context in which the entire postfix-expression occurs.
Here can any one explain about the BOLD part .... and from earlier c++03 draft to c++0x draft he added
If a qualified-id starts with ::, the name after the :: is looked up
in the global namespace.
can any one explain with an example program please
::S is a qualified-id.
In the qualified-id ::S::f, S:: is a nested-name-specifier.
In informal terms, a nested-name-specifier is the part of the id that
begins either at the very beginning of a qualified-id or after the initial scope resolution operator (::) if one appears at the very beginning of the id and
ends with the last scope resolution operator in the qualified-id.
Very informally, an id is either a qualified-id or an unqualified-id. If the id is a qualified-id, it is actually composed of two parts: a nested-name specifier followed by an unqualified-id.
Given:
struct A {
struct B {
void F();
};
};
A is an unqualified-id.
::A is a qualified-id but has no nested-name-specifier.
A::B is a qualified-id and A:: is a nested-name-specifier.
::A::B is a qualified-id and A:: is a nested-name-specifier.
A::B::F is a qualified-id and both B:: and A::B:: are nested-name-specifiers.
::A::B::F is a qualified-id and both B:: and A::B:: are nested-name-specifiers.
Another example:
#include <iostream>
using namespace std;
int count(0); // Used for iteration
class outer {
public:
static int count; // counts the number of outer classes
class inner {
public:
static int count; // counts the number of inner classes
};
};
int outer::count(42); // assume there are 42 outer classes
int outer::inner::count(32768); // assume there are 2^15 inner classes
// getting the hang of it?
int main() {
// how do we access these numbers?
//
// using "count = ?" is quite ambiguous since we don't explicitly know which
// count we are referring to.
//
// Nested name specifiers help us out here
cout << ::count << endl; // The iterator value
cout << outer::count << endl; // the number of outer classes instantiated
cout << outer::inner::count << endl; // the number of inner classes instantiated
return 0;
}
EDIT:
In response to your comment, I believe that statement simply means that the arguments of a template are handled w.r.t the context and line by which they are declared. For example,
in f.~foo();, foo is looked up within f., and within the scope of foo<int>, it is valid to refer to it just with with foo.
It is called as Qualified name lookup.
The leading :: refers the global namespace. Any qualified identifier starting with a :: will always refer to some identifier in the global namespace over the same named identifier in local namespace.
namespace A
{
namespace B
{
void doSomething();
}
}
namespace Z
{
namespace A
{
namespace B
{
void doSomething();
}
}
using namespace A::B // no leading :: refers to local namespace layer
void doSomethingMore()
{
doSomething(); // calls Z::A::B::doSomething();
}
}
namespace Z
{
namespace A
{
namespace B
{
void doSomething();
}
}
using namespace ::A::B // leading :: refers to global namespace A
void doSomethingMore()
{
doSomething(); // calls ::A::B::doSomething();
}
}
The bolded text refers to two different situations. The first part is the distinction of using or not using :: as a prefix. When a qualified name starts with :: the exact namespace is checked starting from the empty namespace, while if it is not present, the search will consider nested namespaces:
namespace A {
void f() { std::cout << "::A::f" << std::endl; }
}
namespace B {
namespace A {
void f() { std::cout << "::B::A::f" << std::endl; }
}
void g() {
A::f(); // ::B::A::f
::A::f(); // ::A::f
}
}
The last sentence in the paragraph refers to the specific of template arguments, and it tells you that the lookup will not start in the namespace that the template was declared, but rather in the namespace where it is being instantiated:
struct A {
static void f() { std::cout << "::A::f()" << std::endl; }
};
template <typename T>
void f() {
T::f();
}
namespace N {
struct A {
static void f() { std::cout << "::N::A::f()" << std::endl; }
};
void g() {
f<A>();
}
}
If lookup started in the template namespace, the call f<A>() would refer to f<::A>, but that clause in the standard states the lookup will start inside namespace N (where the entire postfix-expression occurs), and will thus call ::N::A::f().
int a(1);
class someCls {
private:
int a;
public:
// Assigns this->a with the value of the global variable ::a.
void assignFromGlobal() {
a = ::a;
}
};