グローバルな観点からのメリットはほとんどありません。他の翻訳単位の観点から見ると、どちらのアプローチも同じ結果になります。匿名の名前空間は見えません (または参照できません)。
同じ翻訳単位の観点から、違いがあります。トップレベルの名前空間を定義しているという事実は、他の場所で宣言された名前空間の競合をインポートする可能性を減らすことを意味し、最も一般的なものはグローバル名前空間 (名前空間なし) に対するものです。 stdio.h などの ISO C から継承されたものを考えてください)。
たとえば、その翻訳単位でインポートするグローバル ヘッダーに「名前空間のない」abort() があり、翻訳単位で名前空間 { abort() { ...} } を宣言すると、あいまいさ、たとえば gcc が発生します。コンパイルエラーをスローします:
error: call of overloaded ‘abort()’ is ambiguous
ここで、名前付き名前空間内で匿名名前空間に名前を付けると、次の効果があります。
a) 優先順位があるため、名前空間内で宣言された関数にあいまいさはありません。
namespace a { namespace { abort() {...} } }
a::whatever() のような関数があり、abort() を参照する場合、それが優先されるため、独自の名前空間で解決されます。
b) 名前空間 { abort(); と同じように、翻訳単位の外に存在しないため、 a::abort() のグローバルリンケージはありません。} はトップレベルにありますが、上記の潜在的な競合はありません。
そして、「b」に違いがあります。これは単なる名前空間 a { abort(); と同じではありません。グローバルリンケージがないため、競合することなく別の翻訳単位で再定義できます。名前空間 a { abort() { ... } } ... を定義する 2 つの翻訳単位をリンクしようとして頑張ってください。
したがって、あなたが意味するとおりになります:
namespace a { // you have a named space, so you don't have conflicts with the nameless one
namespace { // but you have local visibility and linkage
whatever(); // for this
}
}
要するに、どちらの方法にも類似点がありますが、違いがあります。それはあまり役に立たないと主張する人もいるかもしれませんが、スタイルとして、グローバル名前空間との衝突を予防的に回避します。これらはコンパイル時に (願わくば、少なくとも署名が完全に一致する場合に) キャッチされるため、なぜ気にする必要があるのか 、という議論ができます。ただし、プロジェクトが移植可能なライブラリであり、環境ヘッダー自体がインポートするものに応じてヘッダーが汚染される可能性がある場合、これは便利な概念です。そうしないと、ユーザーはシステム用にライブラリにパッチを適用するか、#ifdefs が必要になります。あちこち。
私は ISO/ANSI C 99 で多くのプログラミングを行っており、時々次のようなことをしなければなりません:
#include <headerA.h>
#define symbol symbolB
#include <headerB.h>
// or some crap alike. And I have linker problems with above.
...両方のヘッダー(たとえば、異なるライブラリから)が名前空間を汚染し、他の誰かのライブラリに単純にパッチを当てることができないためです。
C++ 名前空間は、他の誰かがそれを使用しない場合を除いて、それを解決するため、防止する (レガシー コードのオプションではない) またはそれを打ち消すための措置を講じる必要があります。