using namespace does not work for definitions? - c++

I am having trouble understanding c++ namespaces. Consider the following example:
//distr.h
namespace bogus{
extern const int x;
extern const int y;
double made_up_distr(unsigned param);
}
Now if I define my variables like the cpp below everything compiles fine
//distr.cpp
#include "distr.h"
#include <cmath>
const int bogus::x = 10;
const int bogus::y = 100;
double bogus::made_up_distr(unsigned param){
auto pdf = (exp(param) / bogus::x) + bogus::y;
return pdf;
}
But if I try to simply bring in the bogus namespace and use instead
//broken distr.cpp
#include "distr.h"
#include <cmath>
using namespace bogus;
const int x = 10;
const int y = 100;
double made_up_distr(unsigned param){
auto pdf = (exp(param) / x) + y;
return pdf;
}
My compiler tells me that the reference to x and y is ambiguous.
Why is that?

There's a simple reason why this can't plausibly work the way you expected:
namespace bogus {
const int x;
}
namespace heinous {
const int x;
}
using namespace bogus;
using namespace heinous;
const int x = 10;
now, should x above refer to bogus::x, heinous::x or a new global ::x?
It would be the third without the using statements, which means here that adding a using statement would change the meaning of existing code in a particularly subtle way.
The using statement is used to introduce the contents of a scope (usually but not necessarily a namespace) for lookup. The statement
const int x = 10;
wouldn't normally require a lookup in the first place, except to detect an ODR violation.

Name lookup for the identifier in declarations/definitions doesn't work the same way as name lookup in usage. In particular, it doesn't care about using statements. There is a very simple reason for this: if it were different, it would lead to all sorts of nasty surprises. Consider this:
// sneakattack.h
namespace sneakattack { void foo(); }
using namespace sneakattack;
// somefile.cpp
#include "sneakattack.h"
void foo() { std::cout << "Hello\n"; }
// otherfile.cpp
void foo();
int main() { foo(); }
This program currently works: the declaration sneakattack::foo is ignored, and the definition ::foo is correctly linked to the use in otherfile. But if name lookup worked differently, somefile would suddenly define sneakattack::foo, not ::foo, and the program would fail to link.

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

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;
}

How to refer to user defined literal operator inside a namespace?

Consider the following:
#include <iostream>
namespace X
{
void operator ""_test(unsigned long long x)
{
std::cout << x;
}
}
int main()
{
using namespace X;
10_test;
// 10_X::test; /* doesn't work */
}
I can refer to the user defined literal operator inside the namespace X by an explicit using namespace X;. Is there any way of referring to the literal operator without explicitly including the namespace? I tried the
10_X::test;
but of course doesn't work as the parser believes X refers to the name of the operator.
X::operator ""_test(10)
works but it's clumsy.
#include <iostream>
namespace X {
inline namespace literals {
void operator ""_test(unsigned long long x) {
std::cout << x;
}
}
}
int main() {
{
using namespace X::literals;
10_test;
}
{
using X::operator""_test;
10_test;
}
}
_test is both in X and X::literals. This permits people to using namespace X::literals; without pulling in everything from X, yet within X _test is also available.
Importing an individual literal is a bit annoying.
std does this with both std::chrono and std::literals and std::chrono::literals. inline namespaces let you define subsections of your namespace that you think people would want to import as a block without getting the rest of it.

Does declaring variables and functions in same namespace get an error? [C++]

If I create a namespace Maths and use another library with a namespace named Maths, will I get an error for re-declaring a variable like PI or re-defining a function like add?
I ask because if I choose to not use namespaces, I should get an error for doing those things, right?
If I don't get an error using namespaces but I do when not using namespaces, isn't safer to just not use namespaces?
Thanks for your time.
First thing, namespace must be global and In different namespace you can have same function or variable, but in same namespace you can't have same variable declaration twice.
namespace A {
int i=10;
char i ='a';/** is not valid **/
void print() {
...
}
}
namespace B {
float i = 1.5; /** valid **/
void print() { /** valid **/
...
}
}
In above example in namespace A and B you have i of int type and i of float type respectively which is valid but In namespace A itself you can't have variable i of different types (considered as re-declaration)
Decided to test it myself:
//in file testnamespace.h
namespace test
{
int t = 1;
void fooo(){};
}
//in file testnamespace2.h
namespace test
{
int t=10000;
void fooo(){int x = -2;}
}
//in file test.cpp
#include "testnamespace.h"
#include "testnamespace2.h"
int main()
{
int ayyyeee = test::t;
foo();
return 0;
}
This gives an error for redefinition,multiple initialization.
All I was looking for.

Invalid use of qualified name

I'm trying the following:
#include <iostream>
namespace A
{
extern int j;
}
int main()
{
int A::j=5;
std::cout << A::j;
}
But I've error: invalid use of qualified-name ‘A::j’. Please explain why this error occurred?
Please explain why this error occurred?
The language simply doesn't allow you to define namespace-scope variables inside functions. The definition has to be either in namespace A:
namespace A {
int j = 5;
}
or in the surrounding (global) namespace:
int A::j = 5;
You can, of course, assign a value to the variable inside the function:
int main() {
A::j = 5;
// ...
}
but you'll also need a definition somewhere, since your program doesn't have one.
#include <iostream>
namespace A
{
int j;
}
int main()
{
A::j=5;
std::cout << A::j;
return 0;
}
Since you declare j in namespace A as extern in the global area, you also need its definition. But in main, you try to assign to it, which also need the symbol definition when linking. So you can remove the extern in namespace A, and remove the 'int' keyword when assigning.