如何避免C++类模板中的无限递归

Adr*_*thy 3 c++ recursion templates matrix

我有一个矩阵类,其大小由模板参数决定.

template <unsigned cRows, unsigned cCols>
class Matrix {
    ...
};
Run Code Online (Sandbox Code Playgroud)

我的程序使用几种大小的矩阵,通常是2x2,3x3和4x4.通过使用模板参数而不是运行时参数设置矩阵大小,编译器可以进行大量的内联和优化.

但是现在我需要一个成员函数来返回一个新的矩阵,该矩阵的行少一列,列少一列.

Matrix<cRows - 1, cCols - 1> Reduced(unsigned row, unsigned col) const { ... }
Run Code Online (Sandbox Code Playgroud)

这个想法是它将返回一个删除了指定行和列的矩阵.在实践中,这将仅使用具有至少三行和三列的矩阵来调用,在最小的位置返回2x2.

编译器没有看到下限,因此它会陷入无限递归,试图以不断减小的大小实例化模板.我尝试在函数本身中放入两条线索,这些较小的尺寸不会发生:

Matrix<cRows - 1, cCols - 1> Reduced(unsigned row, unsigned col) const {
    static_assert(cRows > 1 && cCols > 1);
    if (cRows <= 1 || cCols <= 1) throw std::domain_error();
    Matrix<cRows - 1, cCols - 1> r;
    // ... initialize r ...
    return r;
}
Run Code Online (Sandbox Code Playgroud)

对于编译器而言,static_assert或者if-statement似乎都不是一个足够强大的线索,即永远不会生成0x0矩阵.(具有讽刺意味的是,它确实抱怨if-statement具有恒定的编译时条件.)

有没有人有任何关于如何避免这种编译时无限递归的建议?

CB *_*ley 12

您需要为没有行或没有列的Matrix提供专门化.

例如

template<unsigned cRows>
class Matrix< cRows, 0 >
{
    Matrix<cRows - 1, 0> Reduced() { return Matrix<cRows - 1, 0>(); }
};


template<unsigned cCols>
class Matrix< 0, cCols >
{
    Matrix<0, cCols - 1> Reduced() { return Matrix<0, cCols - 1>(); }
};


template<>
class Matrix< 0, 0 >
{
    Matrix<0, 0> Reduced() { return Matrix<0, 0>(); }
};
Run Code Online (Sandbox Code Playgroud)

您遇到的问题是尝试使用一组特定的模板参数实例化Matrix Reduced函数时,总是需要为不同的参数集(cRows - 1,cCols -1)实例化Matrix模板.这种递归必须在某处停止.如果你只处理方形矩阵,那么你可以减少专业化.

此外,如果你永远不会使用1x1矩阵,那么你可以用一个完全空的类来停止递归,这是2x2矩阵上的reduce的结果.

template<>
class Matrix< 1, 1 > {};
Run Code Online (Sandbox Code Playgroud)