クラス内でクラスを宣言することは有効です。 (ネストされたクラス)
クラス内で名前空間を宣言することは無効です。
問題は、クラス内の名前空間の宣言を禁止する正当な理由(c ++文法/構文の問題以外)がありますか?
なぜ私がそれをしたいのか、ここに例があります:
二分木コンテナの基本的な宣言をしましょう
template<typename Data>
class binary_tree
{
public:
... stuff ....
private:
... iterators class declaration ...
public:
typedef left_depth_iterator_impl left_depth_iterator;
typedef right_depth_iterator_impl right_depth_iterator;
typedef left_breadth_iterator_impl left_breadth_iterator;
typedef right_breadth_iterator_impl right_breadth_iterator;
... stuff ....
private:
Data data;
binary_tree* left;
binary_tree* right;
};
クラスにイテレータがたくさんあることに気づいたので、次のように同じ名前空間内でイテレータを再グループ化します。
template<typename Data>
class binary_tree
{
public:
... stuff ....
private:
... iterators class declaration ...
public:
namespace iterator
{
typedef left_depth_iterator_impl left_depth;
typedef right_depth_iterator_impl right_depth;
typedef left_breadth_iterator_impl left_breadth;
typedef right_breadth_iterator_impl right_breadth;
}
... stuff ....
private:
Data data;
binary_tree* left;
binary_tree* right;
};
これにより、簡単な使用が可能になります。
void function()
{
binary_tree::iterator::left_depth it;
...stuff...
}
これは、名前空間の代わりにクラスを使用する場合に機能しますが、インスタンス化されないクラスを宣言することを強制されますが、これは非常に名前空間です。
ネストされたクラスを許可し、クラス内のネストされた名前空間を禁止する理由それはレガシーの負担ですか?
標準の一部(特に構文部分)を引用するだけでなく、セマンティックな理由による回答は評価されます:)
そのような機能を言語に追加しても、実際の利点はありません。通常、機能は需要がない限り追加されません。
クラス内の名前空間は何を買うでしょうか?単にbinary_tree::iterator::left_depth
の代わりにbinary_tree::left_depth
と言うのが本当ですか?おそらく、内部に複数の名前空間がある場合、それらを使用して、たとえばbinary_tree::depth_iterator::left
とbinary_tree::breadth_iterator::right
を区別します。
いずれにせよ、内部クラスを貧しいプログラマーの名前空間として使用することで、目的の結果を達成できます。これは、クラス内に真の名前空間を要求しないさらに大きな理由です。
標準のマンデート名前空間の場所のどの部分を尋ねたので、最初にそれを見つけました:
C++ 11 7.3-p4:すべての名前空間定義は、グローバルスコープまたは名前空間スコープ(3.3.6)に表示されます。
クラス定義と名前空間内の宣言の提案に関して、私はあなたを...
C++ 11 9.2-p2:クラスは、クラス指定子の終了}で完全に定義されたオブジェクトタイプ(3.9)(または完全なタイプ)と見なされます。クラスメンバ仕様内では、クラスは関数本体、デフォルト引数、例外仕様、および非静的データメンバのブレースまたはイコール初期化子内で完全と見なされます(ネストされたクラスのようなものを含む)。それ以外の場合は、独自のクラスメンバー仕様内で不完全と見なされます。
エルゴ、閉じているカーリーに到達すると、クラス定義は有限になります。開いて拡張することはできません(派生は別のものですが、定義したクラスを拡張しません)。
しかし、名前空間の標準定義の最初に潜んでいるのは、名前空間を拡張する機能です。より良い用語がないためにそれを拡張するには:
C++ 7.3-p1:名前空間は、オプションで名前が付けられた宣言領域です。名前空間の名前を使用して、その名前空間で宣言されたエンティティにアクセスできます。つまり、名前空間のメンバー。 他の宣言領域とは異なり、名前空間の定義は1つ以上の翻訳単位の複数の部分に分割できます。(強調が追加されました)。
したがって、クラス内の名前空間は7.3-p4の定義に違反します。それが存在しないと仮定すると、possibleはクラス内を含むどこでも名前空間を宣言しますが、クラスの定義は一度それが形式化されるためが閉じている場合、7.3-p1への準拠を維持した場合、次の操作のみを行うことができます。
class Foo
{
namespace bar
{
..stuff..
}
.. more stuff ..
namespace bar
{
..still more stuff..
}
};
このfeatureの有用性は、それを解決するために7.3-p4が確立される前に、約3フル秒間議論される可能性がありました。
私はここで他の人に反対するつもりです。本当の利点はないとは言いません。時々、余分な影響なしにコードを分離したいだけです。例として、私はマルチスレッドリングバッファモジュールで作業しており、状態メンバー(一部はアトミックおよび/またはメモリアラインメント)をプロデューサーとコンシューマーのネームスペースに分割したいと考えていました。
すべてにproducer
またはconsumer
プレフィックス(これは現在の迷惑な実装です)を付けるだけで、コードを読みにくくする汚染を追加しています。例えば。プロデューサーが所有するすべてのものがproducer
で始まる場合、誤ってproducerProducerTimer
(プロデューサータイマーのプロデューサーコピー)をproducerConsumerTimer
(プロデューサーシャドウコンシューマータイマーの)またはconsumerProducerTimer
(プロデューサータイマーのコンシューマーシャドウ)。コードがスキム可能でないため、必要以上に時間がかかるデバッグ。
ネストされたクラス/構造を作成することにより:
= delete
これらの事。理想的には、次のようなものを変更できるようにしたいと思います。
rbptr producerPosition;
rbptr consumerPosition;
これに:
namespace producer
{
rbptr position;
}
namespace consumer
{
rbptr position;
}
次に、コンシューマメンバにのみ接触する関数はコンシューマネームスペースを使用でき、プロデューサメンバにのみ接触する関数はプロデューサネームスペースを使用でき、両方に触れる必要がある関数は両方とも明示的に修飾する必要があります。プロデューサー名前空間のみを使用している関数のコンシューマー変数に誤って触れる方法はありません。
この場合、純粋に物のプロデューサーとコンシューマーのコピーの間の名前の衝突を減らし、名前の衝突を減らすことがネームスペースの目的です。そのため、クラス内で名前空間を宣言できるという提案を支持します。
これは名前空間のポイントではありません。名前空間は、2つの異なる企業(またはコードベース)が互いにコードを混在させることができるように、コードのトップレベルの近くに存在することを意図しています。さらにマイクロレベルでは、電子メールアクセス用のIMAPと電子メール送信用のSMTPの両方を使用してコーディングし、Email
と呼ばれるいずれかのモジュールにまったく異なるクラスがありますが、同じクラスの両方を使用したいアプリケーション、例えばメールクライアント、おそらく、あるアカウントから別のアカウントにメールを転送します。名前空間/パッケージ名/などはこれを許可します。
あなたが提案したのは、名前空間の目的ではありません-1つのファイル内で、作成者はファイルのグローバルな知識を持っているため、別の名前を付けることができますが、2つの会社がコードまたは2つのアプリケーションを共有したい場合はそうではありません彼らはどの時点でも衝突することを知らなかった。
私が言及した価値があると感じたほんの小さな考え。クラス内での名前空間の使用の1つは、テンプレート化された名前空間と機能的に同等です。
template<class...types>
struct Namespace {
namespace Implementation {
...
}
};
// somewhere else
using namespace Namespace<types...>::Implementation;
// use templated stuff.
個人的には、この機能をお楽しみいただけますが、実装するには需要が十分に高くないようです。