class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
編集:その背後にある動機を知りたい。
正確にはわかりませんが、クラススコープでこれを許可すると混乱が生じる可能性があります。
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?
}
これを行う明白な方法はないので、規格は単にできないとだけ言っています。
さて、これが名前空間のスコープについて話しているときの混乱が少なくなる理由:
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.
}
}
C++標準では明示的に禁止されているためです。 C++ 03§7.3.4[namespace.udir]から:
使用ディレクティブ: 名前空間の使用::optネストされた名前指定子opt名前空間名 ;
sing-directiveはクラススコープには表示されませんが、ネームスペーススコープまたはブロックスコープに表示される場合があります。 [注:usingディレクティブで名前空間名を検索する場合、名前空間名のみが考慮されます。3.4.6を参照してください。 ]
C++標準で禁止されているのはなぜですか?私は知りません、言語標準を承認したISO委員会のメンバーに尋ねてください。
その理由は、おそらく混乱を招くことだと思います。現在、クラスレベルの識別子の処理中に、ルックアップは最初にクラススコープで検索し、次にそれを囲む名前空間で検索します。 using namespace
クラスレベルでは、検索の実行方法にかなりの副作用があります。特に、特定のクラススコープをチェックしてから、それを囲む名前空間をチェックするまでの間に実行する必要があります。つまり、1)クラスレベルと使用されたネームスペースレベルのルックアップをマージする、2)使用されたネームスペースをルックアップするafterクラススコープであるが他のクラススコープの前3)囲んでいる名前空間の直前で使用されている名前空間を検索します。 4)囲んでいる名前空間とマージされたルックアップ。
。
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
宣言を適用するのとまったく同じ効果があります。それは新しい値を追加しませんが、一方でコンパイラ実装者の検索を複雑にします。ネームスペース識別子のルックアップは、コード内のルックアップがトリガーされる場所から独立しています。クラス内で、ルックアップがクラススコープで識別子を見つけられない場合、ネームスペースルックアップにフォールバックしますが、それは関数定義で使用されるネームスペースルックアップとまったく同じであるため、新しい状態を維持する必要はありません。 using
宣言が名前空間レベルで見つかった場合、used名前空間の内容はbrought 名前空間を含むallルックアップのためにその名前空間に。 using namespace
はクラスレベルで許可され、ルックアップのトリガー元に応じてまったく同じネームスペースのネームスペースルックアップの結果が異なるため、値の追加なしでルックアップの実装がより複雑になります。とにかく、私の推奨事項はnotを使用するusing namespace
宣言。すべての名前空間の内容を考慮する必要なく、コードを推論するのが簡単になります。