Following code results in an error as it is not considering ::x in global scope.
#include<iostream>
namespace nspace
{
int x = 2;
}
int main()
{
using namespace nspace;
std::cout << ::x; //error: ‘::x’ has not been declared
return 0;
}
Following code results in output 2 without any compilation error.
#include<iostream>
namespace nspace
{
int x = 2;
}
using namespace nspace;
int main()
{
std::cout << ::x; // Outputs 2
return 0;
}
I was under the impression that if we have using directive within main function vs using directive in global scope, it is same as far as main function is concerned. For main function both should introduce nspace::x in global scope. And both should result in same behaviour. But above code contradicts my understanding.
So if you can point me to some text from standard that clarifies above behaviour then it would be helpful.
[namespace.qual]/1:
Qualified name lookup in a namespace N additionally searches every element of the inline namespace set of N ([namespace.def]). If nothing is found, the results of the lookup are the results of qualified name lookup in each namespace nominated by a using-directive that precedes the point of the lookup and inhabits N or an element of N's inline namespace set.
In the first case, using namespace nspace; inhabits the block scope inside the main function, so it is not considered.
In the second case, using namespace nspace; inhabits the global namespace scope, so it is considered by lookup in the global scope.
Related
on C++ primer ch 18. namespaces:
"As with any name, a namespace name must be unique within the scope in which the namespace is defined. Namespaces may be defined at global scope or inside
another namespace. They may not be defined inside a function or a class."
But as I guess if not wrong; defining a namespace more than once in the same scope wouldn't break ODR but instead reopens that namespace and may add to it.
Here is my example:
namespace fooNS{
int x = 5;
}
namespace fooNS{
int y = 10;
}
int main(){
std::cout << fooNS::x << '\t' << fooNS::y << '\n';
}
My code works fine so what is meant with "As with any name, a namespace name must be unique within the scope in which the namespace is defined."?
So are there some situations where redefining the same namespace will break the ODR rule? Thanks!
If name in C++ is not fully qualified, e.g. std::cout, it can lead to an unintentional error, such as mentioned at https://en.cppreference.com/w/cpp/language/qualified_lookup. But using a fully qualified name for ::std namespace, e.q. ::std::cout, is very rare, as I have noticed.
Is there any reason why a fully qualified name for ::std namespace is not used?
And what about using fully qualified name for own created namespaces? Is it good idea?
You are completely right, in the sense that yyyy::xxx can be ambiguous if there is a namespace yyyy and also a class yyyy which are both visible in the same scope. In this case only the full qualification ::yyyy::xxx can solve the ambiguity. The example of your link makes it very clear:
// from cppreference.com
#include <iostream>
int main() {
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
But in practice, it's difficult to create a conflicting std at top level, since most of the includes from the standard library will make it fail:
#include <iostream>
struct std { // OUCH: error: ‘struct std’ redeclared as different kind of symbol
int hello;
};
This means that to create a conflict, you'd need to define local classes or introduce a using clause in another namespace. In addition, nobody will (dare to) call a class std.
Finally, in practice, ::yyyy::xxx is less convenient to read. All this explains why you won't find it very often.
Additional remark
The problem is not so much for std which is well known, but rather for your own namespaces and third party libraries. In this case, the namespace alias would be a better alternative to :::yyyy to disambiguate:
namespace foo {
void printf() { }
}
int main() {
foo::printf(); // ok, namespace is chose because no ambiguity
struct foo {/*...*/ }; // creates ambiguity
//foo::printf(); // error because struct foo is chosen by name lookup
::foo::printf(); // ok, but not if you decide to move the code to be nested in another namespace
namespace mylib = foo ; // or ::foo (see discussion below)
mylib::printf(); // full flexibility :-)
}
Its advantage is a higher flexibility. Suppose for example that you'd move your code to nest it in an enclosing namespace. With the namespace alias, your code could continue to work as is (in the worst case with a minor adjustment in the alias definition). With the global scope resolution, you'd have to change all the statements where the global namespace ::foo would be used.
To maintain big code or better readability or clashes in names, C++ has provided namespace " a declarative region".
A namespace definition can appear only at global scope, or nested within another namespace.
#Sample Code
#include <iostream>
int main()
{
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
In the above code compiler is looking for cout in struct std , but in next line when you use ::std::cout it looks for cout in globally defined std class.
Solution:
#include <iostream>
//using namespace std; // using keyword allows you to import an entire namespace at once.
namespace test
{
void cout(std::string str)
{
::std::cout<<str;
}
}
int main()
{
cout("Hello");//'cout' was not declared in this scope
::test::cout("Helloo ") ;
::std::cout<<"it is also ok\n";
}
Or use the in this way , it is just for better readability
##
using namespace test;
int main()
{
cout("Hello");//'cout' was not declared in this scope
cout("Helloo ") ;
::std::cout<<"it is also ok\n";
}
I have a simple question for namespace in C++. There are errors when I compiling the following little piece of code. I don't understand why. Thanks for any help in advance!
#include <iostream>
using namespace std;
int x=100;
namespace first
{
int x=1;
}
namespace second
{
int x=2;
}
int main(){
{
using namespace first;
cout<<x<<endl;
}
{
using namespace second;
cout<<x<<endl;
}
cout<<x<<endl;
}
If I comment out the x declared in the global scope and the last statement. It works fine. But in my mind, the first x is declared in the std namespace and using namespace first and second in the main will be invalid after the the code block they are declared(so the namespace will be std again). So the above code should work. Where am I wrong?
But in my mind, the first x is declared in the std namespace
Your mind is wrong. The using namespace std makes names from std available in the global namespace, it doesn't mean names declared in the global namespace are in std.
x is declared in the global namespace.
so the namespace will be std again
No, nothing in your file is in namespace std, only the contents of <iostream> are in namespace std.
The error is that when you try to use x there are two different variables in scope, ::x and first::x that you could be referring to, so it is ambiguous. You can disambiguate with a using declaration instead of a using directive:
{
using first::x;
cout<<x<<endl;
}
This says that in that scope x refers to first::x
in this case x variable is ambiguous. The compiler can't find which x you are going to use. You can write like this.
#include <iostream>
using namespace std;
int x=100;
namespace first
{
int x=1;
}
namespace second
{
int x=2;
}
int main(){
{
cout<<first::x<<endl;
}
{
cout<<second::x<<endl;
}
cout<<x<<endl;
}
now your code will compile.
The first x is not in the std namespace. It would only be in the std namespace if defined like this:
namespace std
{
int x;
}
Because it's not in that namespace, it's matched by references to x later in the program, and such references become ambiguous when another namespace declaring x is also being used (as in using namespace first / second).
When using a using namespace statement inside an anonymous namespace bring the namespace used in to the file scope? Eg:
namespace foo
{
int f() { return 1; }
}
namespace
{
using namespace foo;
}
int a()
{
return f(); // Will this compile?
}
According to 7.3.4 [namespace.udir] paragraph 4 a namespace directive is transitive:
For unqualified lookup nominates a second namespace that itself contains using-directives, the effect is as if the using-directives from the second namespace also appeared in the first.
... and according to 7.3.1.1 [namespace.unnamed] paragraph 1 there is kind of an implicit using directive for the unnamed namespace:
An unnamed-namespace-definition behaves as if it were replaced by
inline 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.
Thus, the answer is "yes, this is supposed to compile" (and it does with all C++ compilers I tried it with).
Yes.
This is because an anonymous namespace is automatically brought into the containing scope.
Yes, because, as Dietmar Kühl quoted, an anonymous namespace is replaced by its content.
However, you should pay attention that it is replaced exactly where it is declared (edit), so there is no "magic" in this. For example, this won't work:
namespace foo
{
int f() { return 1; }
}
int a()
{
return f(); // Will this compile?
}
namespace
{
using namespace foo;
}
Anyone can help me to understand this statement found in chapter 3 (Library Types) by Stanley Lipmann?
"Using an unqualified version of a namespace name without a using declaration is an error, although some compilers may fail to detect this error"
I'm having such hard time understanding the semantics of his sentence (english).
Is he trying to say something like the below scenario?
int main() {
xx::yy
}
where xx is a namespace not defined using the "using" statement and yy is a member?
Example:
cout is a name of the std namespace. The unqualified name is cout. The qualified name is std::cout. It is an error to use the unqualified name(cout) without a using declaration beforehand. You can use either one of the two following declarations:
// This brings in the entire std namespace
using namespace std;
OR
// This only brings in cout. You would still need to qualify other names,
// such as cin, endl, etc...
using std::cout;
What he's saying is that the following code should not compile:
#include <iostream>
void foo() {
cout << "This is an error!" << endl;
}
The cout and endl names are not defined right now. They're declared as std::cout and std::endl, and in order to use them, you can do one of a few things:
#include <iostream>
void foo() {
std::cout << "This, I think, is the best way to do it." << std::endl;
}
Using the fully qualified name prevents collisions later on: you'll never have something else called std::cout.
#include <iostream>
void foo() {
using std::cout;
using std::endl;
cout << "This is pretty good." << endl;
}
Having the using statements specify the exact names you're using, and having the using statements in the function, can save some typing and makes collisions pretty unlikely.
#include <iostream>
using namespace std;
void foo() {
cout << "This works, but isn't good." << endl;
}
Importing the entire std namespace makes it pretty likely that you'll end up having a function named the same as an std function.. You might discover that as soon as you write it, or you might write your function and then later include the header file with the std version of the function, at which point your application will mysteriously break.
A namespace name is the name of a namespace.
namespace A {
}
namespace B = A;
The statement says that using a namespace name without a using declaration is an error. But that's not true: The above code is fine, still using the namespace-name A as an unqualified name.
Probably it should say the following, to convey its meaning
"Using an unqualified version of a namespace member name without a using declaration
outside the scope of the namespace is an error, although some compilers may fail to
detect this error"
Mentioning the scope is important. The following, for example, is fine too, even though it uses the unqualified version of a namespace member name
namespace A {
int x;
int &y = x; // x is an unqualified name
}
Books should be careful to try and not use slippery language. And even outside the scope of the namespace, the above sentence is not entirely correct because you can also extend the scope of x by a using directive. Using declarations aren't the only way to name a namespace member outside the namespace using an unqualified name.