2009-07-10 15 views
6

C++では、クラスと関数の定義を匿名の名前空間にラップすることで内部リンケージを指定します。明示的にテンプレートをインスタンス化することもできますが、テンプレートの明示的なインスタンス化に準拠した標準であることは、同じ名前空間内で発生する必要があります。 AFAICTこれはコンパイルする必要がありますが、GCCは、それに失敗:エラーで匿名名前空間はすべての名前空間を囲んでいますか?

namespace foo { 

template<class T> 
class bar {}; 

} 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace 'foo') 

匿名の名前空間だけではない、実際に名前空間として機能し、リンケージを指定する必要があるので面白いです、とグローバル名前空間はすべての名前空間を囲むので、fooを確実に囲みます。しかし、たとえこれが動作しない!:

template<class T> 
class bar {}; 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

だけではなく、グローバルな名前空間を列挙し、同じエラーで失敗する:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace '::') 

:/

+0

どのバージョンのGCC - またはどのコンパイラオプション - またはどのプラットフォームですか?私はMacOS X上のG ++ 4.0.1で最初のサンプルを-Wallの有無にかかわらず試してみました。そして、それは苦情や警告なしにコンパイルされました。 –

+0

Solaris上のGCC 4.2。 –

答えて

10

、匿名またはそれ以外の場合は、そのメンバーのリンケージには影響を与えません。特に、匿名の名前空間のメンバーは、魔法のように内部のリンケージを取得しません。

+1

_TU_specific_unique_generated_nameの内容はファイルの外側で使用できないという明白な点を追加します。 – Valentein

+0

実際には、この標準的な方法で正確に記述されています。 –

6

私はあなたがあなたの答えを持っていると思います - 匿名の名前空間は、固有の固有の名前空間です。ところで、コンパイラは、その名前空間を内部的に表現するために、ランダムな大きな整数を生成します。

0

Stroustrup(セクション8.2.5.1)によれば、グローバル名前空間は匿名(名前のつけられていない)名前空間にアクセスできますが、その逆を明示的には言いません。私はあなたが使用してステートメントを使用して名前空間を指定するか、完全に無名の名前空間内で他の名前空間への参照を修飾する必要があるだろう期待し

...

7

まず:あなたは明示的にクラステンプレートをインスタンス化している、あなたが定義されていません新しいクラステンプレート。何

template class bar<int>; 

は、 "ここにint型のクラステンプレートバーをインスタンス化してください"と言います。別の名前空間でクラステンプレートを部分的に特化できないのと同じように、別の名前空間ではできません。具体的には、明示的にインスタンス化されるテンプレートが定義されている必要があります。例では、(匿名の名前空間):: bar <>、foo :: bar <>のみです。

2番目:匿名の名前空間は実際の名前空間です(ただし、すべての翻訳単位では異なります)。それはまた魔法のようにリンケージを変えません。名前空間{}内で宣言されたものは、他の名前空間のスコープと同じように、引き続きデフォルトのリンケージを持ちます。 IIRCでは、翻訳単位 - プライベートではあるが外部リンケージオブジェクトも可能にするために追加されました。匿名の名前空間が

namespace _TU_specific_unique_generated_name 
{ 
    // ... 
} 
using namespace _TU_specific_unique_generated_name; 

名前空間と論理的に等価である