Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using namespace does not work for definitions?

Tags:

c++

namespaces

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?

like image 699
dudu Avatar asked Mar 23 '23 02:03

dudu


2 Answers

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.

like image 169
Useless Avatar answered Apr 02 '23 10:04

Useless


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.

like image 39
Sebastian Redl Avatar answered Apr 02 '23 11:04

Sebastian Redl