[英]How do I prevent a instantiation of a template class?
I'm working on a templated matrix class and currently working on the template determinant function. 我正在研究模板化的矩阵类,目前正在研究模板的行列式函数。 It's a recursive function that finds the determinate of each sub matrix all the way down to the base case and adds/subtracts each of these sub determinate's together.
这是一个递归函数,可找到每个子矩阵的确定值直至基本情况,并将每个子确定值相加/相减。 Here's the function:
功能如下:
//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;
}
The issue I'm having is with the template portion of this. 我遇到的问题与此模板部分有关。 Specifically this part of the code:
具体来说,这部分代码:
Matrix<T, size - 1, size - 1 > subMatrix;
What this is intended to do is to create a matrix with dimensions that fit the sub matrix (which is 1 less than the current). 这样做的目的是创建一个尺寸适合子矩阵(比当前小1)的矩阵。
What's happening is that this specific template is being instantiated: 发生的事情是正在实例化此特定模板:
Matrix<float, 0, 0>
which is a no go since the underlying data in the matrix is an array, and we can't have zero length arrays. 这是不可行的,因为矩阵中的基础数据是一个数组,而且我们不能有零长度的数组。
1) Is there any way to prevent this specific template from being instantiated? 1)有什么方法可以防止实例化此特定模板?
2) Possibly a stupid question but I'm calling this function with a Matrix3x3 passed in. Why does the compiler instantiate every template with a dimension of 3 all the way down to 0? 2)可能是一个愚蠢的问题,但我使用传入的Matrix3x3调用此函数。为什么编译器实例化尺寸为3一直到0的每个模板? (A low level explanation would be great if possible)
(如果可能的话,低级的解释会很好)
You can specialize Determinant<T, 1>
so it doesn't create Matrix<T, 0, 0>
. 您可以专门处理
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>
}
You can also specialize Determinant<T, 2>
so you can drop the if else
inside, since checking for template variables is better done at compile time. 您还可以专用于
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]));
}
如果可以访问C ++ 17,则可以使用if constexpr
而不是常规if
来实例化“废弃”分支:
if constexpr (size == 2)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.