首页 > 解决方案 > 如何防止模板类的实例化?

问题描述

我正在研究模板化矩阵类,目前正在研究模板行列式函数。这是一个递归函数,可以找到每个子矩阵的行列式一直到基本情况,并将这些子行列中的每一个加/减在一起。这是功能:

//Determinant - Only square matrices have a determinant
template <typename T, std::size_t size>
T Determinant(Matrix<T, size, size> &mat)
{
    ASSERT(size >= 2, "Wtf? 1x1 matrix?")

    T determinant = {};

    //Base case - Smallest size of matrix we can calculate the determinant is 2x2
    if (size == 2)
    {
        return ((mat.m_data[0][0] * mat.m_data[1][1]) - (mat.m_data[0][1] * mat.m_data[1][0]));
    }
    else //otherwise, we need to grab the sub matrix within the current matrix and get the determinate of those. 
    {
        Matrix<T, size - 1, size -1 > subMatrix;

        //Note: We're filling in the new sub matrix column order
        for (int topRow_ColumnIndex = 0; topRow_ColumnIndex < size; ++topRow_ColumnIndex)
        {
            int newSubCol = 0;
            for (int subCol = 0; subCol < size; ++subCol)
            {
                int newSubRow = 0;

                if (subCol == topRow_ColumnIndex)
                {
                    continue;
                }

                //Sub matrices will start one row below the top row.
                for (int subRow = 1; subRow < size; ++subRow)
                {
                    subMatrix[newSubCol][newSubRow] = mat[subCol][subRow];
                    ++newSubRow;
                }
                ++newSubCol;
            }
            determinant = determinant + (T)pow(-1, topRow_ColumnIndex) * mat.m_data[topRow_ColumnIndex][0] *Determinant(subMatrix);
        }
    }
    return determinant;
}

我遇到的问题是这个模板部分。特别是这部分代码:

Matrix<T, size - 1, size - 1 > subMatrix;

这样做的目的是创建一个矩阵,其尺寸适合子矩阵(比当前小 1)。

正在发生的事情是这个特定的模板正在被实例化:

Matrix<float, 0, 0> 

这是不行的,因为矩阵中的基础数据是一个数组,我们不能有零长度数组。

1)有什么办法可以防止这个特定的模板被实例化?

2) 可能是一个愚蠢的问题,但我使用传入的 Matrix3x3 调用此函数。为什么编译器实例化每个维度为 3 的模板一直到 0?(如果可能的话,一个低层次的解释会很好)

标签: c++templates

解决方案


您可以专门化Determinant<T, 1>,这样它就不会创建Matrix<T, 0, 0>.

template <typename T>
T Determinant<T, 1> (Matrix<T, 1, 1> &mat) {
    // Implementation here
    // Avoid Matrix<T, 0, 0>
}

你也可以专门Determinant<T, 2>化,这样你就可以放弃if else内部,因为检查模板变量最好在编译时完成。

template <typename T, std::size_t size>
T Determinant<T, size> (Matrix<T, size, size> &mat) {
    // original "else" part here
}

template <typename T>
T Determinant<T, 2> (Matrix<T, 2, 2> &mat) {
    return ((mat.m_data[0][0] * mat.m_data[1][1]) - (mat.m_data[0][1] * mat.m_data[1][0]));
}

推荐阅读