代码之家  ›  专栏  ›  技术社区  ›  Adrian McCarthy

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

  •  4
  • Adrian McCarthy  · 技术社区  · 16 年前

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

    template <unsigned cRows, unsigned cCols>
    class Matrix {
        ...
    };
    

    但现在我需要一个成员函数,它返回一个新的矩阵,该矩阵少了一行一列。

    Matrix<cRows - 1, cCols - 1> Reduced(unsigned row, unsigned col) const { ... }
    

    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;
    }
    

    也不是 static_assert 也不是 if 如果

    5 回复  |  直到 16 年前
        1
  •  12
  •   CB Bailey    16 年前

    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>(); }
    };
    

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

    template<>
    class Matrix< 1, 1 > {};
    
        2
  •  1
  •   sepp2k    16 年前

        3
  •  1
  •   anon    16 年前

    你似乎对编译时和运行时行为有点困惑,我对你的代码也有点困惑。但我认为你想要的是对值0的模板进行专门化,从而终止递归。

    如果你还没有,我建议你读一读 C++ Templates: The Complete Guide

        4
  •  0
  •   Reunanen    16 年前

    您需要明确指定希望递归结束的情况的行为。看 this DDJ article

    template<int n>
    class META_FACTORIAL
    {
    public:
      enum{
        RET = n * META_FACTORIAL<n-1>::RET
      };
    };
    
    template<>
    class META_FACTORIAL<0>
    {
    public:
      enum{ RET = 1 };
    };
    
        5
  •  0
  •   Stack Overflow is garbage    16 年前

    与其专门化整个类来终止递归,另一种选择可能是使用 boost::enable_if