class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
I want to know the motivation behind it.
class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
I want to know the motivation behind it.
I don't know exactly, but my guess is that allowing this at class scope could cause confusion:
namespace Hello
{
typedef int World;
}
class Blah
{
using namespace Hello;
public:
World DoSomething();
}
//Should this be just World or Hello::World ?
World Blah::DoSomething()
{
//Is the using namespace valid in here?
}
Since there is no obvious way of doing this, the standard just says you can't.
Now, the reason this is less confusing when we're talking namespace scopes:
namespace Hello
{
typedef int World;
}
namespace Other
{
using namespace Hello;
World DoSomething();
}
//We are outside of any namespace, so we have to fully qualify everything. Therefore either of these are correct:
//Hello was imported into Other, so everything that was in Hello is also in Other. Therefore this is okay:
Other::World Other::DoSomething()
{
//We're outside of a namespace; obviously the using namespace doesn't apply here.
//EDIT: Apparently I was wrong about that... see comments.
}
//The original type was Hello::World, so this is okay too.
Hello::World Other::DoSomething()
{
//Ditto
}
namespace Other
{
//namespace Hello has been imported into Other, and we are inside Other, so therefore we never need to qualify anything from Hello.
//Therefore this is unambiguiously right
World DoSomething()
{
//We're inside the namespace, obviously the using namespace does apply here.
}
}
using namespace Hello;
inside other namespace
also (and declaring extern
function inside it). –
Decaliter Hello::World Blah::DoSomething()
or Blah::World Blah::DoSomething()
(if it was allowed), the return type of a member function definition is not considered to be in the scope of the class in the language, so it has to be qualified. Consider the valid example of replacing the using
with a typedef Hello::World World;
at class scope. So there should be no surprises there. –
Strobotron typedef int World;
) –
Impartible Because the C++ standard explicitly forbids it. From C++03 §7.3.4 [namespace.udir]:
using-directive: using namespace ::opt nested-name-specifieropt namespace-name ;
A using-directive shall not appear in class scope, but may appear in namespace scope or in block scope. [Note: when looking up a namespace-name in a using-directive, only namespace names are considered, see 3.4.6. ]
Why does the C++ standard forbid it? I don't know, ask a member of the ISO committee that approved the language standard.
I believe that the rationale is that it would probably be confusing. Currently, while processing a class level identifier, lookup will first search in the class scope and then in the enclosing namespace. Allowing the using namespace
at class level would have quite some side effects on how the lookup is now performed. In particular, it would have to be performed sometime between checking that particular class scope and checking the enclosing namespace. That is: 1) merge the class level and used namespace level lookups, 2) lookup the used namespace after the class scope but before any other class scope, 3) lookup the used namespace right before the enclosing namespace. 4) lookup merged with the enclosing namespace.
.
namespace A {
void foo() {}
struct B {
struct foo {};
void f() {
foo(); // value initialize a A::B::foo object (current behavior)
}
};
}
struct C {
using namespace A;
struct foo {};
void f() {
foo(); // call A::foo
}
};
.
namespace A {
void foo() {}
}
void bar() {}
struct base {
void foo();
void bar();
};
struct test : base {
using namespace A;
void f() {
foo(); // A::foo()
bar(); // base::bar()
}
};
.
namespace A {
void foo( int ) { std::cout << "int"; }
}
void foo( double ) { std::cout << "double"; }
struct test {
using namespace A;
void f() {
foo( 5.0 ); // would print "int" if A is checked *before* the
// enclosing namespace
}
};
using
declaration at the namespace level. It would not add any new value to that, but will on the other hand complicate lookup for compiler implementors. Namespace identifier lookup is now independent from where in the code the lookup is triggered. When inside a class, if lookup does not find the identifier at class scope it will fall back to namespace lookup, but that is exactly the same namespace lookup that is used in a function definition, there is no need to maintain new state. When the using
declaration is found at namespace level, the contents of the used namespace are brought into that namespace for all lookups involving the namespace. If using namespace
was allowed at class level, there would be different outcomes for namespace lookup of the exact same namespace depending on where the lookup was triggered from, and that would make the implementation of the lookup much more complex for no additional value.Anyway, my recommendation is not to employ the using namespace
declaration at all. It makes code simpler to reason with without having to keep all namespaces' contents in mind.
using
exists. By purposedly declaring things in deep nested long namespaces. E.g. glm
does that, and uses multiple tricks to activate / present features when the client use using
. –
Palocz using namespace std::placeholders
. c.f en.cppreference.com/w/cpp/utility/functional/bind –
Palocz namespace ph = std::placeholders;
–
Strobotron using namespace A
at top level, into any other namespace or into any function. i think, the main issue is, that namespace imported global variables and functions would look like fake static members of the class. –
Produce This is probably disallowed because of openness vs closedness.
Importing namespaces into classes would lead to funny cases like this:
namespace Foo {}
struct Bar { using namespace Foo; };
namespace Foo {
using Baz = int; // I've just extended `Bar` with a type alias!
void baz(); // I've just extended `Bar` with what looks like a static function!
// etc.
}
namespace Foo
to the search order for all code inside the type definition of struct Bar
, much like putting that line in every inline member function body, except that it would also be active for brace-or-equal initializers, etc. But it would still expire at the closing brace, the same as using namespace
inside a member function body. Now there unfortunately doesn't seem to be any way to use Koenig-with-fallback lookup in a brace-or-equal initializer without polluting the enclosing namespace. –
Tardigrade using namepace Foo;
inside a struct (assuming re-export of names) would be ill-defined in the first place. I don't really see the point of bike-shedding the specifics of such a hypothetical feature. The whole point of my answer was that such a feature would be confusing at best, and potentially ill defined at worst. Your comments are supporting this. –
Darling I think it's a defect of the language. You may use workaround below. Keeping in mind this workaround, it is easy to suggest rules of names conflicts resolution for the case when the language will be changed.
namespace Hello
{
typedef int World;
}
// surround the class (where we want to use namespace Hello)
// by auxiliary namespace (but don't use anonymous namespaces in h-files)
namespace Blah_namesp {
using namespace Hello;
class Blah
{
public:
World DoSomething1();
World DoSomething2();
World DoSomething3();
};
World Blah::DoSomething1()
{
}
} // namespace Blah_namesp
// "extract" class from auxiliary namespace
using Blah_namesp::Blah;
Hello::World Blah::DoSomething2()
{
}
auto Blah::DoSomething3() -> World
{
}
You can't use using namespace
inside of a class, but what you can do is simply use #define
and then #undef
inside of the structure. It will act the exact same way as namespace a = b;
struct foo
{
#define new_namespace old_namespace
void foo2()
{
new_namespace::do_something();
}
#undef new_namespace
};
© 2022 - 2024 — McMap. All rights reserved.
using namespace
. C# allows something similar, but at file scope only. C++'susing namespace
allows you to incorporate one namespace into another. – Desiraeusing string = std::string;
at class scope. All the resolution confusions thatusing namespace std;
creates is is already an issue, if the class author is willing to be explicit about it. – Collado