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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With