我要在这里完成的是一些NxN矩阵的行列式的计算。行列式的定义如下:

det M = MC(M),其中i从1到N循环,k是任意选择的常数,使得1
“ C”是定义如下的辅因子:

C(M) = (-1) det M,其中M {i,j}表示(N-1)x(N-1)矩阵,其条目由删除第i行第j列的M的原始条目组成

现在,这是我的代码:

template <typename T, const int N>
T determinant(const TMatrixNxM<T, N, N> &par_value)
{
    T result = T(0);

    switch (N)
    {
    case 1:
        //Hardcoded for 1x1 matrix:
        result = par_value[0][0];
        break;
    case 2:
        //Hardcoded for 2x2 matrix:
        result = par_value[0][0] * par_value[1][1] - par_value[0][1] * par_value[1][0];
        break;
    case 3:
        //Hardcoded for 3x3 matrix:
        result = par_value[0][0] * (par_value[1][1] * par_value[2][2] - par_value[1][2] * par_value[2][1]) - par_value[0][1] * (par_value[1][0] * par_value[2][2] - par_value[1][2] * par_value[2][0]) + par_value[0][2] * (par_value[1][0] * par_value[2][1] - par_value[1][1] * par_value[2][0]);
        break;
    default:
        //i loops through 0 to N-1, k is arbitrarily chosen to be 0
        for (int i = 0; i < N; i++)
        {
            result += par_value[i][0] * cofactor(par_value, i, 0);
        }
        break;
    }

    return result;
}

template <typename T, const int N>
T cofactor(const TMatrixNxM<T, N, N> &par_value, int par_i, int par_j)
{
    T result = T(0);

    //Construct the new matrix, without the i-th row j-th column
    TMatrixNxM<T, N - 1, N - 1> newMatrix;

    int k = 0;

    for (int i = 0; i < N - 1; i++)
    {
        int l = 0;

        if (k == par_i) k++;

        for (int j = 0; j < N - 1; j++)
        {
            if (l == par_j) l++;

            newMatrix[i][j] = par_value[k][l];

            l++;
        }

        k++;
    }

    result = pow(-1, (par_i + 1) + (par_j + 1)) * determinant(newMatrix); //I have to add +1 to i and j since I started from 0

    return result;
}


并对其进行测试:

TMatrixNxM<float, 3, 3> mat1;
//Set values
float det = determinant(mat1);


但是,编译器给我这些错误:
警告3警告C4200:使用了非标准扩展名:结构/联合中的零大小数组
错误4错误C2118:下标为负
指的是保存矩阵值的数据数组

当我看到编译器输出的其余部分时,我看到它正在尝试推导N设置为0甚至-1的参数。这里发生了什么?显然,它永远都不会走那么远(实际上,正如我所看到的,它不应该低于3)。

另外,如果我注释掉辅助因子函数中对行列式函数的递归调用,它将进行编译(它也可以正确计算新矩阵)。或者,如果我注释掉行列式函数中的整个“默认”部分,它将进行编译(并且它也可以正确计算硬编码的行列式)。

感谢您的时间

编辑1

在注释中请求的代码,显示数据数组的声明:

template <typename T, const int N, const int M>
class TMatrixNxM
{
public:
    TMatrixNxM(T = T(0));
    //Other things
protected:
    TVectorND<T, M> data[N];
};




template <typename T, const int N>
class TVectorND
{
public:
    TVectorND(T = T(0));
    //Other things
protected:
    T data[N];
};

最佳答案

即使未实际到达代码,编译器也需要能够编译determinant的整个主体。因此,即使对于N = 3,您仍然需要能够使用cofactor调用N = 3,而后者又会使用determinant调用N = 2。反过来,这要求能够使用cofactor调用N = 2并使用determinant调用N = 1,依此类推,直到获得N = -1和编译错误为止。

代替在switch中的N上使用determinant,而使用重载模板:

template <typename T>
T determinant(const TMatrixNxM<T, 1, 1> &par_value)
{
    T result = T(0);
    result = par_value[0][0];
    return result;
}

template <typename T>
T determinant(const TMatrixNxM<T, 2, 2> &par_value)
{
    T result = T(0);
    result = par_value[0][0] * par_value[1][1] - par_value[0][1] * par_value[1][0];
    return result;
}

template <typename T>
T determinant(const TMatrixNxM<T, 3, 3> &par_value)
{
    T result = T(0);
    result = par_value[0][0] * (par_value[1][1] * par_value[2][2] - par_value[1][2] * par_value[2][1]) - par_value[0][1] * (par_value[1][0] * par_value[2][2] - par_value[1][2] * par_value[2][0]) + par_value[0][2] * (par_value[1][0] * par_value[2][1] - par_value[1][1] * par_value[2][0]);
    return result;
}

template <typename T, const int N>
T determinant(const TMatrixNxM<T, N, N> &par_value)
{
    static_assert(N >= 4, "Default determinant called for N<4");
    T result = T(0);

    //i loops through 0 to N-1, k is arbitrarily chosen to be 0
    for (int i = 0; i < N; i++)
    {
        result += par_value[i][0] * cofactor(par_value, i, 0);
    }
    return result;
}


Demo

关于c++ - 模板参数推导出错,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24987240/

10-11 21:46