名前空間は他のほとんどのもののように宣言および定義されていませんが、前方宣言に相当する名前空間は次のようになります。
namespace X {} // empty body
通常、名前空間を定義するには、その中に他の宣言を配置します。しかし、この「名前空間前方宣言」が最も簡単な解決策である問題はありますか?空の名前空間はどのような用途に使用されますか?
名前空間は他のほとんどのもののように宣言および定義されていませんが、前方宣言に相当する名前空間は次のようになります。
namespace X {} // empty body
通常、名前空間を定義するには、その中に他の宣言を配置します。しかし、この「名前空間前方宣言」が最も簡単な解決策である問題はありますか?空の名前空間はどのような用途に使用されますか?
これは、標準にも表示されるものです: 名前空間を示すために using ディレクティブを宣言する
namespace unique { }
using namespace unique;
その後、別の機会に名前空間を開いて追加することができます。 using ディレクティブは、外側の名前空間から見えるようにします。
空の名前空間定義を使用して、再帰関数の宣言を簡素化します。ここで、一方の「側」は演算子のオーバーロードです。演算子は、ヘッダーがどこかに含まれている場合に使用を強制するのではなく、必要に応じてスコープ内で選択的に使用できるように独自の名前空間に配置されます (したがって、解決があいまいになった場合にエラーを強制します)。
例:
namespace container_inserters {}
template<class Stream, class Iter, class Ch>
void write_sequence(Stream& s, Iter begin, Iter end,
Ch const *initial, Ch const *sep, Ch const *final)
{
using namespace container_inserters;
if (initial) s << initial;
if (begin != end) {
s << *begin;
++begin;
for (; begin != end; ++begin) {
if (sep) s << sep;
s << *begin;
}
}
if (final) s << final;
}
namespace container_inserters {
#define G(N) \
template<class Ch, class Tr, class T, class A> \
std::basic_ostream<Ch,Tr>& operator<<(std::basic_ostream<Ch,Tr> &s, \
N<T,A> const &value) \
{ \
write_sequence(s, value.begin(), value.end(), "[", ", ", "]"); \
return s; \
}
G(std::deque)
G(std::list)
G(std::vector)
#undef G
} // container_inserters::
の解決はs << *begin
、write_sequence がインスタンス化されるまで (テンプレート パラメーターが含まれているため) 遅れます。その時点までに、オペレーターは宣言され、using ディレクティブを介して見つけることができます。ネストされたコンテナーの呼び出しは再帰的になります。
int main() {
using namespace std;
vector<deque<list<int> > > v (3, deque<list<int> >(2, list<int>(1, 42)));
using namespace container_inserters;
cout << v << '\n';
return 0;
}
// output:
// [[[42], [42]], [[42], [42]], [[42], [42]]]
Boost にも同様の出力書式設定ライブラリがありますが、同じ実装手法を使用しているかどうかはわかりません。