User-declared namespace member - c++

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.
If that name treated as the definition of the member name then what is it point of declaration?
And why the following example will works:
namespace N
{
extern int j;
}
int i = 2;
int N::j = i; //N::j=2
int N::j=i actual appears into the namespace scope. Hence the declarationint i=2 is not visible for unqualified name lookup. Why does this declaration found?

Your question:
int N::j=i actual appears into the namespace scope. Hence the declaration int i=2 is not visible for unqualified name lookup. Why does this declaration found?
Answer:
Since i is not found in the N namespace, it is looked up in the global namespace. Had an i been there in the N namespace, that would have been used to initialize N::j.
Hope the following program clarifies your doubt.
#include <iostream>
namespace N
{
extern int j;
extern int k;
int x = 3;
}
int x = 2;
int y = 10;
int N::j = x; // N::x is used to initialize N::j
int N::k = y; // ::y is used to initialize N::k
int main()
{
std::cout << N::j << std::endl;
std::cout << N::k << std::endl;
}
Output:
3
10
Update, in response to comment by OP
What the standard is saying is that:
namespace N
{
extern int j;
}
int x = 2;
int N::j = x;
is equivalent to:
namespace N
{
extern int j;
}
int x = 2;
namespace N
{
int j = x;
}
The logic for lookup ofx is same. If it is found within the same namespace N, it is used. If x is not found in namespace N, it is searched for outward in the enclosing namespaces.

You seem to be confused about how name lookup works on a basic level. Maybe a simple example helps:
#include <iostream>
void print(std::string const & s) { std::cout << "Boo: " << s << "\n"; }
namespace Foo
{
std::string message = "Foo";
void action() { print(message); }
}
int main() { Foo::action(); }
Clearly the name print is visible in the definition of Foo::action. Names from containing namespaces are visible in contained namespaces. There's nothing unusual about that.
The point of the rule you are quoting, and which R Sahu already demonstrated nicely, is that you can put the definition of a variable elsewhere from its declaration, and in that case any name appearing in the initializer is looked up in the namespace in which the variable is declared. Here's another example:
namespace Foo
{
namespace Bar { int a = 10; }
int b = 20;
extern int c;
}
namespace Bar { int a = -20; }
int b = 5;
int Foo::c = Bar::a + b; // uses Foo::Bar::a and Foo::b, NOT ::Bar::a or ::b
int main() { return Foo::c; } // returns 30

Related

How do namespace's with same name but different scope (e.g. foo, bar::foo) work?

If there are two namespaces named Foo and Bar and there is a namespace named Foo inside Bar. If I refer to a variable Foo::i from inside Bar will it search for i in both Foo and Bar::Foo. If not, is it possible to make the compiler search in both namespaces when i doesn't exist in Bar::Foo?
More concrentely in the below example, I am trying to refer variable i from namespace a in b without puting extra ::. I know putting :: works, I am trying to see if there is any other way to resolve this.
#include <iostream>
#include <string>
namespace a {
int i = 1;
}
namespace b {
namespace a {
}
namespace c {
int j = a::i; // Doesn't work, need to use ::a::i;
}
}
int main()
{
std::cout << b::c::j << "\n";
}
If you can change b::a, then you can indeed make certain declarations available in b::a from ::a as fallbacks:
namespace a {
int i = 1;
int j = 2;
}
namespace b {
namespace a {
namespace detail {
using ::a::i; // Selectively bring declarations from ::a here
}
using namespace detail; // Make the names in detail available for lookup (but not as declarations).
//int i = 2;
}
namespace c {
int j = a::i; // Uses ::a::i
// int k = a::j; // ERROR! We didn't bring ::a::j into b::a at all
}
}
Here it is live.
Un-commenting the declaration of b::a::i will change the output. Since a proper declaration takes precedence over names brought in by a namespace using directive.
You could explicitly have a using declaration in the inner namespace for variables that it wants to use from the outer one.
i.e. for your example,
namespace a {
int i = 1;
}
namespace b {
namespace a {
using ::a::i; //inner one does not define its own
int i2 = 2; //inner one creates its own variable
}
namespace c {
int j = a::i; // Doesn't work, need to use ::a::i;
}
}
See:
https://en.cppreference.com/w/cpp/language/namespace#Using-declarations

C++ does not recognize string as keyword

I tried the following code:
#include <iostream>
using namespace std;
int main()
{
char string[4]='xyz';
return 0;
}
Since string is a keyword the compiler should give error but it runs fine. Can anyone explain why it compiles successfully.
string is not a keyword.
It's the name of a type declared in the standard library.
When you give it a name, you're doing something called shadowing. This is more clear in the following example:
{
int x = 0;
{
int x = 5;
std::cout << x << std::endl;
}
std::cout << x << std::endl;
}
What gets printed?
Well, 5 first then 0.
This is because the x in the second scope overrides the x from the first. It "shadows" the first declaration.
This works with typenames as well:
struct MyStruct {
int x;
};
...
{
...
int MyStruct = 10;
...
}
Here, MyStruct gets overridden within that scope.
That same thing happens in your example with std::string

Variable declaration in C++ within namespaces

In a library I am working with some variables are declared like that:
char &ns::x = y;
However, if I do it that way I get the following error:
error: no member named 'x' in namespace 'ns'
If I rewrite it, it works:
namespace ns {
char &x = y;
}
What exactly is the difference? And why is it working within the library?
If you’re right and the code from the library is exactly as written, then this implies that elsewhere in this library, you’ll find the following declaration:
namespace ns {
extern char& x;
}
In other words, x must have already been declared (and not defined!) inside ns.
The first declaration
char &ns::x = y;
assumes that the name x is already declared in the namespace ns. However this assumption is wrong (in the provided code snippet there is no previous declaration of the variable. Possibly the code snippet is not complete.).
The code snippet can works provided that the variable x is already declared (without its definition) in the namespace ns.
For example
#include <iostream>
namespace ns
{
extern char &x;
}
char y;
char & ns::x = y;
int main() {
return 0;
}
In this code snippet
namespace ns {
char &x = y;
}
there is defined a reference that is initialized by the object y.
The Variable declaration using namespace:
#include <iostream>
using namespace std;
// Variable created inside namespace
namespace first
{
int val = 500;
}
// Global variable
int val = 100;
int main()
{
// Local variable
int val = 200;
// These variables can be accessed from
// outside the namespace using the scope
// operator ::
cout << first::val << '\n';
return 0;
}

Accessing member of an unnamed namespace when the outer namespace has a member with the same name

Here is the test code
extern "C" {int printf(const char *, ...);}
namespace PS
{
int x = 10; // A
// some more code
namespace {
int x = 20; // B
}
// more code
}
int main()
{
printf("%d", PS::x); // prints 10
}
Is there any way to access inner(unnamed) namespace's x inside main?
I dont want to change code inside PS. Apologies if the code looks highly impractical.
P.S: I tend to use the name x quite often.
No. The only way to specify a namespace is by name, and the inner namespace has no name.
Assuming you can't rename either variable, you could reopen the inner namespace and add a differently-named accessor function or reference:
namespace PS {
namespace {
int & inner_x = x;
}
}
printf("%d", PS::inner_x);
One way is to add this code:
namespace PS
{
namespace
{
namespace access
{
int &xref = x;
}
}
}
and then you can access what you want:
std::cout << PS::access::xref << std::endl; //prints 20!
Demo : http://ideone.com/peqEs

Is there any other possiblitly to prove this point other than using 'extern' keyword :n3290 draft

A point from ISO draft N3290 :
Unqualified Name Lookup :section 3.4.1, para 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.
ex:
namespace N {
int i = 4;
extern int j;
}
int i = 2;
int N::j = i; // N::j == 4
Is there any other possiblitly to prove this point other than using 'extern' keyword
can u give some other examples ... other than extern
Another example which doesn't use extern keyword:
//demo.cpp
int i = 100;
namespace N
{
int i = 200;
struct A
{
static int m;
};
}
int N::A::m = i; //i is 100 or 200?
int main()
{
cout << N::A::m << endl; //what will it print?
}
Output:
200
Online demo : http://www.ideone.com/pRVAb
This code doesn't use extern yet it more or less proves the point. Note that it doesn't define variable outside the namespace, it instead defines function outside the namespace.
//demo.cpp
int i = 100;
namespace N
{
int i = 200;
struct X{};
void f(const X&);
}
void N::f(const X&)
{
cout << i << endl; //what will it print?
}
int main()
{
N::X x;
f(x); //use argument-dependent lookup (ADL) to find the function!
}
Output:
200
Online demo : http://www.ideone.com/KCqUV
I added ADL to make it more interesting!
Another example is regarding the definition of a static member in class.
// header
namespace N {
const int i = 4;
class A
{
public:
static int m_i;
};
}
// source file
int i = 2;
int N::A::m_i = i; // N::A::m_i == 4
int main(int argc, char* argv[])
{
cout << N::A::m_i << endl;
return 0;
}
// header.h
struct X { void bar () {} };
namespace N {
struct X { void bar () {} };
void foo(X *p = new X);
}
// implementation.cpp
#include"header.h"
N::foo(X* p) { p->bar(); } // N::X::bar() called
This example is without using extern. (though it's implied).