[解決済み] インライン名前空間は何のためにあるのですか?
質問
C++11では
inline namespace
のすべてのメンバは、自動的に周囲の
namespace
. これの有用な応用が思いつかないのですが、どなたか簡単で簡潔な例を挙げてください。
inline namespace
が必要であり、それが最も慣用的な解決策である場合はどうでしょうか?
(また、(1)のような場合、どうなるのかがよくわかりません。
namespace
が宣言されている場合
inline
を、異なるファイルに存在するすべての宣言ではなく、1つの宣言に含めることができます。これはトラブルの元ではないでしょうか?)
解決方法は?
インライン名前空間は、ライブラリのバージョン管理機能で、次のようなものです。 シンボルバージョニング しかし、特定のバイナリ実行形式の機能(つまり、プラットフォーム固有)ではなく、純粋に C++11 レベル(つまり、クロスプラットフォーム)で実装されています。
これは、ライブラリの作者が、ネストされた名前空間を、その宣言がすべて周囲の名前空間にあるかのように見せ、動作させることができるメカニズムです(インライン名前空間はネストすることができるので、" more-nested" 名前は最初の非インライン名前空間まで浸透し、その宣言もその間のいずれかの名前空間にあるかのように見せ、動作させることができます)。
例として、STLの実装である
vector
. もし C++ の最初からインライン名前空間があったとしたら、C++98 ではヘッダの
<vector>
は、こんな感じになっていたかもしれません。
namespace std {
#if __cplusplus < 1997L // pre-standard C++
inline
#endif
namespace pre_cxx_1997 {
template <class T> __vector_impl; // implementation class
template <class T> // e.g. w/o allocator argument
class vector : __vector_impl<T> { // private inheritance
// ...
};
}
#if __cplusplus >= 1997L // C++98/03 or later
// (ifdef'ed out b/c it probably uses new language
// features that a pre-C++98 compiler would choke on)
# if __cplusplus == 1997L // C++98/03
inline
# endif
namespace cxx_1997 {
// std::vector now has an allocator argument
template <class T, class Alloc=std::allocator<T> >
class vector : pre_cxx_1997::__vector_impl<T> { // the old impl is still good
// ...
};
// and vector<bool> is special:
template <class Alloc=std::allocator<bool> >
class vector<bool> {
// ...
};
};
#endif // C++98/03 or later
} // namespace std
の値に応じて
__cplusplus
は、どちらか一方が
vector
の実装が選択されます。もし、あなたのコードベースがC++98以前の時代に書かれたもので、C++98バージョンの
vector
への参照を見つけるだけでよいのです。
std::vector
に置き換えてください。
std::pre_cxx_1997::vector
.
次の標準になると、STL ベンダーはまたこの手順を繰り返し、新しい名前空間を導入して
std::vector
で
emplace_back
をサポートし(これは C++11 が必要です)、もし
__cplusplus == 201103L
.
OK、では、なぜこのために新しい言語機能が必要なのでしょうか?すでに次のような方法で同じ効果を得ることができますよね?
namespace std {
namespace pre_cxx_1997 {
// ...
}
#if __cplusplus < 1997L // pre-standard C++
using namespace pre_cxx_1997;
#endif
#if __cplusplus >= 1997L // C++98/03 or later
// (ifdef'ed out b/c it probably uses new language
// features that a pre-C++98 compiler would choke on)
namespace cxx_1997 {
// ...
};
# if __cplusplus == 1997L // C++98/03
using namespace cxx_1997;
# endif
#endif // C++98/03 or later
} // namespace std
の値に応じて
__cplusplus
のどちらか一方の実装を取得します。
そして、ほぼ正解でしょう。
次のようなC++98の有効なユーザーコードを考えてみましょう(名前空間に存在するテンプレートを完全に特殊化することが許されていました)。
std
をC++98で既に使用しています)。
// I don't trust my STL vendor to do this optimisation, so force these
// specializations myself:
namespace std {
template <>
class vector<MyType> : my_special_vector<MyType> {
// ...
};
template <>
class vector<MyOtherType> : my_special_vector<MyOtherType> {
// ...
};
// ...etc...
} // namespace std
これは完全に妥当なコードで、ユーザはSTLにあるものより効率的な実装を知っているような、型の集合に対するベクターの独自の実装を提供します。
しかし
: テンプレートを特殊化する場合は、そのテンプレートが宣言された名前空間で行う必要があります。スタンダードでは
vector
は名前空間
std
そのため、ユーザは当然そこで型を特化することを期待します。
このコードはバージョン管理されていない名前空間で動作します。
std
や、C++11 のインライン名前空間機能を使用したバージョン管理トリックでは使用できません。
using namespace <nested>
という実装の詳細が公開されるからです。
vector
が定義されていたのは
std
を直接表示します。
ネストした名前空間を検出するための穴は他にもありますが(以下のコメント参照)、インライン名前空間はそれらをすべて塞いでくれます。そして、それがすべてなのです。将来的には非常に有用だが、AFAIKでは標準ライブラリのインライン名前空間を規定していないため(これについては間違いが証明されると嬉しいが)、標準自体ではなくサードパーティのライブラリにしか使えない(コンパイラベンダが命名方式に合意しない限り)。
関連
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] ムーブセマンティクスとは何ですか?
-
[解決済み] std::promiseとは何ですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】if __name__ == "__main__": は何をするのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み] 関数/メソッドのキーワード 'inline' はいつ書けばよいのですか?
-
[解決済み] 特定のglibcのバージョンにリンクするにはどうしたらいいですか?