1

コードを見てください:

template <class x> struct Foo
{
    int getX(x *p) { return(0); }
    enum E12 { a };
};

template <> int Foo<int>::getX(int*)
{
    return(-15);
}

template <> enum Foo<int>::E12
{
    a, b, c
}

Cannot overload functionで説明したように、最初の特殊化は合法であり、MSVC でも機能します。の 2 番目の特殊enum化は、「エラー C2988: 認識できないテンプレート宣言/定義」と言って、コンパイルしたくありません。

C++ がメソッドに対して比較的非論理的な例外を作成しているように思えます。列挙型は単なる例です。メンバー クラス、typedef などにも同じことが適用できます。

誰かがこれについてコメントしてくれると嬉しいです。

4

1 に答える 1

1

これは、C++11 の非常に目立たない新機能です。Microsoft にバグ レポートを提出してください。ただし、これが許可されていることをほとんど誰も認識していないため、優先される可能性は低いと思われます。正しい構文は次のようになります。

template <class x> struct Foo
{
    int getX(x *p) { return(0); }
    enum E12 { a };
};
 
template <> int Foo<int>::getX(int*)
{
    return(-15);
}
 
template <> enum Foo<int>::E12
{
    a, b, c
};

GCC にバグを報告しました誰かが最近の Clang でテストできますか?


C++03 では、明示的に特殊化できるのはクラスと関数だけです。標準、C++03 14.7.3/1 から:

次のいずれかの明示的な特殊化:

  • 関数テンプレート
  • クラス テンプレート
  • クラス テンプレートのメンバ関数
  • クラス テンプレートの静的データ メンバー
  • クラス テンプレートのメンバ クラス
  • クラスまたはクラス テンプレートのメンバ クラス テンプレート
  • クラスまたはクラス テンプレートのメンバ関数テンプレート

によって導入された宣言によって宣言できますtemplate<>

メンバー列挙型はそのような場合ではありません。(一般的に言えば、enum型は常に最初の宣言で一度だけ定義されます。)

enumテンプレート化されたまたはを取得するtypedefには、それをクラス テンプレートでラップできます。あなたの場合、それはのメンバークラステンプレートになりFooます。このような構造はメタ関数と呼ばれます。

C++11 には、テンプレート化された typedef に似たエイリアス テンプレートもありますが、明示的に特殊化することはできません。


クラスと関数のみを特殊化することを許可し、そのようなテンプレートに や などの他のものをカプセル化することを許可するというポリシーは、 の直接の特殊化を許可するよりも一貫しているように思えenumます。しかし、おそらく言語はあなたの好みの方向に進んでいます。typedefenum

于 2012-06-30T05:15:52.537 に答える