似乎没有任何参数时参数不匹配

Argument mismatch when there doesn't seem to be any

提问人:eccentricOrange 提问时间:3/12/2023 最后编辑:eccentricOrange 更新时间:3/12/2023 访问量:96

问:

我正在尝试编写一个程序来查找 NxN 矩阵的行列式,并在这样做的过程中首次了解并首次了解。std::arraytemplates

我根据辅助因子和次要因子的方法提出了这个实现。

#include <array>
#include <iostream>

template <int N>
using Matrix = std::array<std::array<double, N>, N>;

template <int N>
Matrix<N - 1> subMatrix(Matrix<N> matrix, size_t focusRow, size_t focusColumn) {
    Matrix<N - 1> returnMatrix;

    int subMatrixRow = 0, subMatrixColumn = 0;
    static const int matrixSize = matrix.size();

    for (size_t matrixRow = 0; matrixRow < matrixSize; matrixRow++) {
        for (size_t matrixColumn = 0; matrixColumn < matrixSize; matrixColumn++) {
            if (matrixRow != focusRow && matrixColumn != focusColumn) {
                returnMatrix[subMatrixRow][subMatrixColumn++] = matrix[matrixRow][matrixColumn];

                if (subMatrixColumn == matrixSize - 1) {
                    subMatrixColumn = 0;
                    subMatrixRow++;
                }
            }
        }
    }

    return returnMatrix;
}

template <int N>
double getDeterminant(Matrix<N> matrix) {
    static const int matrixSize = matrix.size();
    double determinant = 0;

    if (matrixSize == 1) {
        determinant = matrix[0][0];
    }

    else if (matrixSize == 2) {
        determinant = (matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]);
    }

    else if (matrixSize > 0) {
        int sign = 1;

        for (size_t dimension = 0; dimension < N; dimension++) {
            determinant += sign * matrix[0][dimension] * getDeterminant(subMatrix(matrix, 0, dimension));
            sign = -sign;
        }
    }

    else {
        throw std::invalid_argument("expected square matrix");
    }

    return determinant;
}

int main(int argc, char const* argv[]) {
    static const int length = 3;

    Matrix<length> matrix = {{{1, 2, 3},
                              {4, 5, 6},
                              {7, 8, 9}}};

    printf("determinant = %.2f\n", getDeterminant(matrix));
}

但是,当我运行时,我遇到了一个我无法完全解决的错误。如何进行?make

vscode ➜ /workspaces/c-cpp-mirror/11032023-arrays $ make determinant
g++     determinant.cpp   -o determinant
determinant.cpp: In function ‘int main(int, const char**)’:
determinant.cpp:68:57: error: no matching function for call to ‘getDeterminant(Matrix<3>&)’
   68 |     printf("determinant = %.2f\n", getDeterminant(matrix));
      |                                                         ^
determinant.cpp:31:8: note: candidate: ‘template<int N> double getDeterminant(Matrix<N>)’
   31 | double getDeterminant(Matrix<N> matrix) {
      |        ^~~~~~~~~~~~~~
determinant.cpp:31:8: note:   template argument deduction/substitution failed:
determinant.cpp:68:57: note:   mismatched types ‘int’ and ‘long unsigned int’
   68 |     printf("determinant = %.2f\n", getDeterminant(matrix));
      |                                                         ^
make: *** [<builtin>: determinant] Error 1

下面是一个较小的程序,它仍然表现出相同的行为:

#include <array>
#include <iostream>

template <int N>
using Matrix = std::array<std::array<double, N>, N>;

template <int N>
void printMatrix(Matrix<N> matrix) {}

int main(int argc, char const* argv[]) {
    static const int length = 4;

    Matrix<length> matrix = {{{7, -2, 2, 1},
                              {3, 1, -5, 2},
                              {2, 2, -5, 3},
                              {3, 2, 5, 1}}};

    printMatrix(matrix);
}
C++ 数组 函数 模板

评论

0赞 eccentricOrange 3/12/2023
@FrançoisAndrieux是的,我也是在发布后才意识到这一点的。已编辑,谢谢!
1赞 François Andrieux 3/12/2023
std::array的 size 参数类型是 和 not 。将两者混合在一起可能会扰乱模板参数推导,并且由于没有显式提供参数,编译器找不到可以调用的函数。std::size_tint
0赞 Passer By 3/12/2023
这不是最小的,请参阅最小可重复示例
0赞 Passer By 3/12/2023
Clang 有一个更好的诊断:“候选模板被忽略:替换失败:推导的非类型模板参数与相应的模板参数没有相同的类型('unsigned long' vs 'int')”
0赞 eccentricOrange 3/12/2023
@PasserBy这是公正的批评。请允许几分钟,我将尽量减少示例。

答:

4赞 Sam Varshavchik 3/12/2023 #1

显示的代码存在多个基本问题。

第一个是第二个模板参数不是 .这是一个 .std::arrayintstd::size_t

把这个事实放在一个搅拌器中,连同一个别名,旋转它,你最终会要求一个受苦的C++编译器从 .这是一个苹果与橙子的问题。usingintsize_t

要解决第一个问题,必须将所有模板声明更改为 。template<int N>template<size_t n>

但是当这种情况发生时,你的编译器会脾气暴躁,因为你将指示你受苦的C++编译器创建一个比我们共享宇宙中的原子更多的值的矩阵:

    else if (matrixSize > 0) {
        Matrix<N - 1> temp;

什么时候是 0,这最终会成为一个相当大的矩阵,你不是说吗?即使这个分支不会被采用,它仍然必须编译,并且作为一个模板,你受苦的C++编译器基本上需要评估它。这种可能性不大。Matrix

因此,您需要修复此问题,并将所有这些更改为 .if constexpr

然后,代码将编译。

#include <array>
#include <iostream>

template <std::size_t N>
using Matrix = std::array<std::array<double, N>, N>;

template <std::size_t N>
Matrix<N - 1> subMatrix(Matrix<N> matrix, size_t focusRow, size_t focusColumn) {
    Matrix<N - 1> returnMatrix;

    int subMatrixRow = 0, subMatrixColumn = 0;
    static const int matrixSize = matrix.size();

    for (size_t matrixRow = 0; matrixRow < matrixSize; matrixRow++) {
        for (size_t matrixColumn = 0; matrixColumn < matrixSize; matrixColumn++) {
            if (matrixRow != focusRow && matrixColumn != focusColumn) {
                returnMatrix[subMatrixRow][subMatrixColumn++] = matrix[matrixRow][matrixColumn];

                if (subMatrixColumn == matrixSize - 1) {
                    subMatrixColumn = 0;
                    subMatrixRow++;
                }
            }
        }
    }

    return returnMatrix;
}

template <std::size_t N>
double getDeterminant(Matrix<N> matrix) {
    static const int matrixSize = matrix.size();
    double determinant;

    if constexpr (matrixSize == 1) {
        determinant = matrix[0][0];
    }

    else if constexpr (matrixSize == 2) {
        determinant = (matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]);
    }

    else if constexpr (matrixSize > 0) {
        Matrix<N - 1> temp;
        int sign = 1;

        for (size_t dimension = 0; dimension < N; dimension++) {
            temp = subMatrix(matrix, 0, dimension);
            determinant += sign * matrix[0][dimension] * getDeterminant(temp);
            sign = -sign;
        }
    }

    else {
        throw std::invalid_argument("expected square matrix");
    }

    return determinant;
}

int main(int argc, char const* argv[]) {
    static const int length = 3;

    Matrix<length> matrix = {{{1, 2, 3},
                         {4, 5, 6},
                         {7, 8, 9}}};

    printf("determinant = %.2f\n", getDeterminant(matrix));
}

评论

0赞 eccentricOrange 3/12/2023
感谢您的详细解释。事实上,我先尝试过,但它给出了这些例外stackoverflow.com/a/63372812/10907280 指示我使用 .你用指向的解释在这里有很大帮助。std::size_tintN - 1
1赞 Sam Varshavchik 3/12/2023
是的。我没有立即看到第二个问题。在修复了第一个编译错误后,出现了这个确切的错误。在 C++ 中,同一错误可能有不同的原因。学习如何理解编译器错误需要时间。不要盲目地接受搜索结果,除非阅读它并完全理解它如何应用于自己的代码。