C++の「名前空間エイリアス」とは何ですか?どのように使用されますか?
名前空間エイリアスは、別の短い名前で長い名前空間名を参照する便利な方法です。
例として、using namespace
ディレクティブなしでBoostのuBLASの数値ベクトルを使用したいとします。毎回完全な名前空間を記述するのは面倒です:
boost::numeric::ublas::vector<double> v;
代わりに、boost::numeric::ublas
のエイリアスを定義できます。これを単にublas
に短縮したい場合:
namespace ublas = boost::numeric::ublas;
ublas::vector<double> v;
簡単に言えば、#defineは機能しません。
namespace Mine { class MyClass { public: int i; }; }
namespace His = Mine;
namespace Yours { class Mine: public His::MyClass { void f() { i = 1; } }; }
うまくコンパイルします。名前空間/クラス名の衝突を回避できます。
namespace Nope { class Oops { public: int j; }; }
#define Hmm Nope
namespace Drat { class Nope: public Hmm::Oops { void f () { j = 1; } }; }
最後の行の「Hmm:Oops」はコンパイルエラーです。プリプロセッサはそれをNope :: Oopsに変更しますが、Nopeはすでにクラス名です。
また、名前空間のエイリアスとusingディレクティブは、実行時ではなくコンパイル時に解決されることに注意してください。 (より具体的には、現在のスコープまたはその親スコープのいずれかで特定のシンボルが見つからない場合、名前を解決するときに他の場所をコンパイラに指示するために使用される両方のツールです。)たとえば、これらのどちらもコンパイル:
namespace A {
int foo;
namespace AA {
int bar;
} // namespace AA
namespace AB {
int bar;
} // namespace AB
} // namespace A
namespace B {
int foo;
namespace BA {
int bar;
} // namespace BA
namespace BB {
int bar;
} // namespace BB
} // namespace B
bool nsChooser1, nsChooser2;
// ...
// This doesn't work.
namespace C = (nsChooser1 ? A : B);
C::foo = 3;
// Neither does this.
// (Nor would it be advisable even if it does work, as compound if-else blocks without braces are easy to inadvertently break.)
if (nsChooser1)
if (nsChooser2)
using namespace A::AA;
else
using namespace A::AB;
else
if (nsChooser2)
using namespace B::BA;
else
using namespace B::BB;
好奇心の強い人は、constexpr
変数もコンパイル時に使用されることに気づき、エイリアスまたはディレクティブのいずれかと組み合わせて使用できるかどうか疑問に思っているかもしれません。私の知る限り、私はこれについて間違っているかもしれませんが、彼らはできません。異なる名前空間で同じ名前の変数を操作し、それらを動的に選択する必要がある場合は、参照またはポインターを使用する必要があります。
// Using the above namespaces...
int& foo = (nsChooser1 ? A::foo : B::foo);
int* bar;
if (nsChooser1) {
if (nsChooser2) {
bar = &A::AA::bar;
} else {
bar = &A::AB::bar;
}
} else {
if (nsChooser2) {
bar = &B::BA::bar;
} else {
bar = &B::BB::bar;
}
}
上記の有用性は制限される場合がありますが、目的にかなうはずです。
(上記で見逃したかもしれないタイプミスに対する謝罪。)
次のような名前空間名のエイリアスを選択することがすべてです。
namespace SHORT = NamespaceFirst::NameSpaceNested::Meow
その後、typedefすることができます
typedef SHORT::mytype
の代わりに
typedef NamespaceFirst::NameSpaceNested::Meow::mytype
この構文は名前空間でのみ機能し、クラス、namespace NAME =
の後の型を含めることはできません
名前空間は、名前の競合を防ぐために使用されます。
例えば:
namespace foo {
class bar {
//define it
};
}
namespace baz {
class bar {
// define it
};
}
これで、ネームスペースのおかげで、まったく異なる2つのクラスの名前バーができました。
表示する「名前空間の使用」は、その名前空間内のクラスを使用するために名前空間を指定する必要がないようにするためです。つまり、std :: stringはstringになります。