0

重複の可能性:
テンプレートをヘッダー ファイルにしか実装できないのはなぜですか?

私は Matrix クラスに取り組んでおり、標準の C++ 2 次元配列で配列を初期化するために使用するメソッド SetMatrix を持っています。

template <int width, int height>
static void SetMatrix(Matrix& matrix, double array[][width]) {
    if (matrix.height_ != height || matrix.width_ != width) {
        fprintf(stderr, "Incorrect matrix size\n");
        return;
    }
    for (int y = 0; y < height; ++y)
        for (int x = 0; x < width; ++x)
            matrix.matrix_[y][x] = array[y][x];
}

メソッドはうまく機能しますが、ヘッダー ファイルから .cpp 実装ファイルに移動しようとすると、リンカー エラーが発生します。

マトリックス.cpp:

template <int width, int height>
void Matrix::SetMatrix(Matrix& matrix, double array[][width]) {
    if (matrix.height_ != height || matrix.width_ != width) {
        fprintf(stderr, "Incorrect matrix size\n");
        return;
    }
    for (int y = 0; y < height; ++y)
        for (int x = 0; x < width; ++x)
            matrix.matrix_[y][x] = array[y][x];
}

g++ 出力:

g++ -Wall -Wextra main.cpp Matrix.cpp -o matrix
/tmp/ccMkObBs.o: In function `main':
main.cpp:(.text+0x81): undefined reference to `void Matrix::SetMatrix<2, 3>(Matrix&, double (*) [2])'
collect2: error: ld returned 1 exit status

それを .cpp ファイルに移動する方法、または単に運が悪いだけなのか、それとももっとエレガントな方法があるのか​​疑問に思っていましたか? 私が見つけたリソースのほとんどは、非テンプレート クラスの静的テンプレート メソッドではなく、テンプレート クラスの静的メソッドを扱っていました。役立つ場合は、ここに私の呼び出しコードもあります

int main() {
    double input[3][2] = {
        {1, 2},
        {3, 4},
        {5, 6}
    };

    Matrix matrix(2, 3);

    Matrix::SetMatrix<2, 3>(matrix, input);
    matrix.Print();
}
4

1 に答える 1

0

main.cppSetMatrixメンバー関数テンプレートの定義を認識できないため、これが呼び出されたときにインスタンス化できません。コンパイラは、その関数のコードが他の翻訳単位 (つまり、他の.cppファイル) の処理中に生成された、または生成されるという事実にのみ依存できます。

SetMatrixただし、 に関数の定義が存在するだけではmatrix.cpp、関数テンプレートがそこでインスタンス化されることを意味しません(実際には、そのファイルには を呼び出すコード行がないため、インスタンス化されませんSetMatrix)。したがって、その関数のオブジェクト コードは生成されません。

そのため、最終的にインスタンス化された関数テンプレートのコードはどの翻訳単位にも存在せず、リンカ エラーが発生します。

于 2013-01-25T17:51:33.783 に答える