3

テンプレート関数内で逆呼び出しを行うことはできませんが、渡されたパラメーターは問題ないようです。最初はヘッダーファイルです:

#ifndef TestTemplate_TestTemplate_h
#define TestTemplate_TestTemplate_h

template<int size>
void printArray(int (*iarr)[size]);

#include "TestTemplate.cpp"
#endif

2番目は.cppファイルです。

#include <iostream>

using std::cout;
using std::endl;
template<int size>
void printArray(int (*iarr)[size]){
    if(size == 1){
        return;
    }
    else{
        const int s = size - 1;
        cout << size << endl;
        int arr[s][s] = {};
        printArray<s>(arr);
    }
}

最後はメインファイルです:

#include <iostream>
#include "TestTemplate.h"
int main(int argc, const char * argv[])
{
    const int size = 4;
    int iarr[size][size]= {{1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}};
    printArray<size>(iarr);
}

今、私はそれを言っているコンパイルエラーを受け取りました

no matching function for call to 'printArray'

ソースファイル内。テンプレートプログラミングには、ここではわからない文法があるかもしれません。誰かが私に教えてくれたらいいのにと思います。どうもありがとうございました。

4

1 に答える 1

4

if. _ コンパイラは、分岐の 1 つが実行されないことを「認識」している場合でも、常にifinsideの両方の分岐をインスタンス化する必要があります。printArrayこれは、コンパイル時の再帰が実際には終了していないことを意味します。それは潜在的に無限です。arrコンパイラが sizeの配列を宣言しようとすると、コンパイル エラーが発生しますが0、これは違法です。これがエラーの原因です。

ここでも、コンパイラは を生成するときにprintArray<1>、内部の両方のブランチのコードをインスタンス化しますif。つまり、宣言しようとします。

int arr[0][0] = {};

これは違法です。

コンパイラから得られるエラー メッセージは誤解を招くものです。おそらく、コンパイラがサイズ 0 の配列を受け入れることを許可する非標準の拡張機能を実装しているためです。実際には、サイズがゼロの配列宣言によってエラーが発生するはずです。

コンパイル時のテンプレート再帰を実装しようとしている場合は、(実行時の分岐とは対照的に) コンパイル時の手法を使用して底をつく必要があります。あなたの場合、明示的な特殊化を使用して、つまり、明示的に特殊化された非再帰バージョンのprintArrayfor arrays を個別に追加することで実行できます1

template<>
void printArray<1>(int (*iarr)[1]) {
}

( size の配列に対して何もしていない理由がわかりません1。意図した機能を忠実に再現しました。)

または、明示的なテンプレートの特殊化の代わりに、通常の関数のオーバーロードを使用して同じ効果を得ることができます。このオーバーロードされたバージョンを宣言する

void printArray(int (*iarr)[1]) {
}

そしてそれは問題も解決します。(この場合、再帰テンプレートの前に宣言する必要があることに注意してください)。printArray

もちろん、再帰バージョン内で分岐する必要はもうありません

template<int size>
void printArray(int (*iarr)[size]) {
    const int s = size - 1;
    cout << size << endl;
    int arr[s][s] = {};
    printArray<s>(arr);
}

PS またprintArray、コード サンプルでテンプレート引数を明示的に指定する必要はありません。関数を として呼び出すことができますprintArray(arr)。コンパイラはsize.

于 2012-12-24T08:17:27.673 に答える