18

テンプレートの特殊化で遊んでいますが、解決できないと思われる問題を見つけました。これは私のコードです:

template<int length, typename T>
void test(T* array)
{
    ...
    test<length-1>(array);
}

template<typename T>
void test<0>(T* array)
{
    return;
}

だから私がやろうとしているのは、テンプレートで処理されるものの長さを渡すことです。

問題は、これをコンパイルすると、永久に出力されることです。

a.cpp:83:43: error: template-id 'test<0>' in declaration of primary template
a.cpp: In function 'void test(T*) [with int length= -0x000000081, T = int]':
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000080, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x00000007f, T = int]'
a.cpp:77:9:   [ skipping 151 instantiation contexts ]
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= 28, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= 29, T = int]'
...
a.cpp: In function 'void test(T*) [with int length= -0x000000082, T = int]':
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000081, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000080, T = int]'

最後の2行は、最初の行とほとんど同じです。

私には、専門分野を捉えていないように思われるので、次のようになります。

a.cpp:83:43: error: template-id 'test<0>' in declaration of primary template

私は正しいですか?

そして、私が正しければ、部分的なテンプレートの特殊化が関数テンプレートに許可されていないという問題だと思います。それでは、構造体を作成し、それに特殊化を使用することで、どのような解決策がありますか?

4

4 に答える 4

22

関数テンプレートの部分的な特殊化は許可されていません。ハーブサッターは、彼の記事「関数テンプレートを専門にしないのはなぜですか?」でその理由を説明しています。

この制限を回避するには、代わりにクラステンプレートを使用する必要があります。次に、そのクラステンプレートを使用する通常の関数テンプレートを作成できます。

発生している特定のエラーは、スペシャライゼーションの2番目のパラメーターを忘れたためです。代わりにこれを行う場合:

template<int length, typename T>
void test(T* array)
{
    //...
    test<length-1,T>(array);
}


template<typename T>
void test<0,T>(T* array)
{
    return;
}

GCCは次のように文句を言います。

エラー:関数テンプレートの部分的な特殊化'test <0、T>'は許可されていません

于 2011-07-08T10:47:59.887 に答える
8

機能を部分的に特殊化することはできません。これを回避するには、テンプレート関数でクラス内の関数を呼び出させます。

template<int length, typename T>
struct helper
{
    static void go(T* array)
    {
        ...
        helper<length-1, T>::go(array);
    }
};

template<typename T>
struct helper<0, T>
{
    static void go(T* array)
    {
        ...
    }
};

template<int length, typename T>
void test(T* array)
{
    ...
    helper<length, T>::go(array);
}
于 2011-07-08T10:49:58.560 に答える
3

関数テンプレートの部分的な特殊化は許可されていません

これを回避するにtestは、クラステンプレートの静的メンバーを作成し、クラスを部分的に特殊化することができます。

于 2011-07-08T10:49:58.020 に答える
2

ヘルパークラスで回避できます。説明のために:

template<typename T, typename U> struct helper_t {
    static int foo () { return 0; }
};

template<typename T> struct helper_t<T,T> {
    static int foo () { return 1; }
};

template <typename T, typename U>
int frob () {
    return helper_t<T,U>::foo();
}
于 2011-07-08T10:50:59.380 に答える