2011-11-03 23 views
6

ISO 98/03標準(セクション14.3.1)は、内部パラメータを持つ型をテンプレートパラメータとして使用することを禁止しているようです。 (下記の例を参照してください)。C++ 11標準はそうではありません。 G ++ - 古い標準を使用しています - 許可しています。 03標準を誤読していますか、またはこのスライドをただ単にgにしていますか?テンプレート引数としての内部型

namespace 
{ 
    struct hidden { }; 
} 

template<typename T> 
struct S 
{ 
    T t; 
}; 

int main() 
{ 
    S<hidden> s; 
    return 0; 
} 
+0

g ++バージョン?拡張子かもしれない –

答えて

7

あなたはC++ 03はC++ 11が行う一方で、テンプレート型パラメータとして内部リンケージで型を使用して許可しないことが正しいです。

ただし、匿名名前空間内の定義にはまだ外部リンクがあります。


うんは、セクション3.5 [basic.link]

言う名称有する名前空間の範囲(3.3.5)は、

  • オブジェクト、参照、関数の名前である場合、内部結合を有します静的に宣言された関数テンプレート、または
  • 明示的にconstと宣言され、明示的に宣言されていないオブジェクトまたは参照externも、以前は外部リンケージがあると宣言されていませんでした。または
  • 匿名組合のデータメンバー。それは内部結合を持っていない限り、それは、オブジェクトまたは参照

    • の名前である場合、名前空間の範囲を有する

    名は、外部結合を有します。または

  • 内部リンケージがない限り、関数です。または
  • 名前付きクラス(9節)、または結合目的の型定義名を持つtypedef宣言で定義された名前のないクラス(7.1.3)。または
  • 名前付き列挙型(7.2)、または列挙型がリンケージ用のtypedef名を持つtypedef宣言で定義された名前のない列挙型(7.1.3)。または
  • 外部リンケージを伴う列挙に属する列挙子。または内部リンクを持つ関数テンプレートでない場合(第14節)、テンプレートは
  • です。名前が付けられていない名前空間内で宣言されている場合を除き、
  • 名前空間(7.3)。

名前空間スコープに名前付きクラスがありますが、これには外部リンケージがあります。

とページ115の下部に脚注ISO/IECの14882:2003明確化は:無名の名前空間内のエンティティは、外部リンケージを持っているかもしれませんが

、それらが効果的に翻訳に固有の名前で修飾されていますしたがって、他の翻訳単位から決して見ることはできません。

別のバージョンをお持ちの場合は、7.3.1項を参照してください。1 [namespace.unnamed]

4

これはルールの有効な例ではありません。あなたの例のhiddenクラスは、外部リンケージを持っています。 (これは、現在の翻訳単位外の何が実際にそれにリンクすることはできませんが、それはまだ外部のだと、このようなコンパイラで生成されたユニークな名前を持っています。)

標準は、地元のタイプの例示します:

template <class T> class X { /* ... */ }; 
void f() 
{ 
    struct S { /* ... */ }; 

    X<S> x3; // error: local type used as template-argument 
    X<S*> x4; // error: pointer to local type used as template-argument 
} 
関連する問題