2

次の例を考えてみましょう:

#include <iostream>
#include <typeinfo>

template< int N, typename T >
struct B
{
    struct C;
};

template< typename T >
struct B< 0, T >::C
{
    typedef T type;
};

template< int N, typename T >
struct B< N, T >::C
{
    typedef T type[N];
};

int main()
{
    std::cout<<"n=0   type = " << typeid( B< 0, float >::C::type ).name() << std::endl;
    std::cout<<"n=5   type = " << typeid( B< 5, float >::C::type ).name() << std::endl;
}

g++ (バージョン 4.3.0) を使用してコンパイルした場合

g++ dfg.cpp  -ansi -pedantic -Wall

コンパイルエラーは次のとおりです。

dfg.cpp:13: error: qualified name does not name a class before ‘{’ token
dfg.cpp: In instantiation of ‘B<0, float>::C’:
dfg.cpp:25:   instantiated from here
dfg.cpp:20: error: ISO C++ forbids zero-size array

私が実際にアーカイブしようとしているのは、列挙値に応じて異なる Imp 実装を持つことです (この例では、列挙型の代わりに int を使用しましたが、問題にはなりません)。

これが許可されていない理由を誰かが説明できますか? 最初のエラーが発生するのはなぜですか? (これ: 修飾名は '{' トークンの前にクラスを指定しません)


テンプレートパラメータに依存するpimplの実装に関して、私は新しい質問を作成しました(より良い例で)here

4

2 に答える 2

3

これは無効です:

template< typename T >
struct B< 0, T >::C
{
    typedef T type;
};

クラス テンプレートのメンバーを特殊化できますが、それらのクラス テンプレートの暗黙的なインスタンス化に対してのみです。これは平易な英語を意味します: 囲んでいるクラス テンプレート (そのメンバーを特殊化する必要がある) のすべてのテンプレート引数に値を指定した場合のみです。

template< >
struct B< 0, int >::C
{
    typedef T type;
};

あなたが書いたのは、B<0, T>::Cのクラステンプレート部分特殊化のメンバーであるの定義ですB<N, T>。このような部分的な特殊化は存在しないため、コンパイラでエラーが発生しました。


これを解決するには、いくつかのオプションがあります。一つは

template< int N, typename T >
struct B
{
    template<typename N1, typename T1>
    struct CMember { typedef T1 type[N1]; };

    template<typename T1>
    struct CMember<0, T1> { typedef T1 type; };

    struct C { 
      typedef typename CMember<N, T>::type type;
    };
};

明示的な特殊化 (非部分的) をクラス テンプレートに直接配置することはできないことに注意してください (そのため、template<> struct CMember<0, int> { ... }の本体内に書き込む場合は形式が正しくありませんB)。Bその場合、「セレクター」テンプレートを外部で(おそらくdetail名前空間で)定義する必要があります。

CMember他の選択肢には、その typedefからの派生と継承が含まれます。

于 2011-03-24T13:27:15.840 に答える
2

この方法C以外で定義することはできません-作成している特殊化には存在しません。B::C を特化したい場合は、B を特化する必要があります。BCB

template< int N, typename T >
struct B
{
    struct C {
        typedef T type[N];
    };
};

template< typename T >
struct B< 0, T >
{
    struct C {
        typedef T type;
    };
};

または、次のようなこともできます。

template< int N, typename T >
struct B
{
    struct C;
};

template< typename T >
struct B< 0, T > {
    struct C;
};

template< typename T >
struct B< 0, T >::C
{
    typedef T type;
};

template< int N, typename T >
struct B< N, T >::C
{
    typedef T type[N];
};

これは B を 0 に部分的に特殊化し、前方宣言 C をB<0, T>::C定義できるようにします。

于 2011-03-24T13:17:52.723 に答える