很抱歉,如果以前出现这种情况,我花了一段时间寻找类似的问题,但我看不出有任何问题这个
我正在编写一些使用拉普拉斯扩展递归计算矩阵行列式的代码 - 这需要计算出小矩阵,我已经将其实现为一个类,其中包含对实际矩阵的引用并提供类似的函数(例如大小和运算符( ))返回次要矩阵的正确值。次要矩阵类需要能够接受基本矩阵类或另一个次要矩阵类,因此需要模板化,对于行列式函数也是如此。
但是,我的代码(在VS2017上编译)产生错误'C1202:递归类型或函数依赖关系上下文过于复杂'。以下是重现错误的最小示例:
#include <iostream>
template <typename T>
class A
{
public:
typedef T type;
A(T value) : value(value) {}
type get_value() const { return value; }
private:
T value;
};
template <typename T>
class B
{
public:
typedef typename T::type type;
B(const T& t) : t(t) {}
type get_value() const { return t.get_value() - 1; }
private:
const T& t;
};
template <typename T>
typename T::type foo(const T& t)
{
if (t.get_value() == 0)
return 0;
else
return t.get_value() + foo(B<T>(t));
}
int main()
{
std::cout << foo(A<int>(5));
std::cin.ignore();
}
(我认为如果编译它应该打印15)。
任何意见都会受到赞赏。
编辑:这是非最小代码(根据要求) - 取决于boost :: ublas库
#include <boost/numeric/ublas/matrix.hpp>
#include <iostream>
template <typename Matrix>
class matrix_minor
{
public:
typedef boost::numeric::ublas::matrix<double>::const_reference const_reference;
typedef boost::numeric::ublas::matrix<double>::size_type size_type;
matrix_minor(const Matrix& A, unsigned int i, unsigned int j) :
A(A), i(i), j(j) {}
size_type size1() const { return A.size1() - 1; }
size_type size2() const { return A.size2() - 1; }
const_reference operator () (size_type i_, size_type j_) const
{
return A(
(i_ >= i ? i_ + 1 : i_),
(j_ >= j ? j_ + 1 : j_)
);
}
private:
const Matrix& A;
unsigned int i, j;
};
template <typename Matrix>
double det(const Matrix& A)
{
if (A.size1() != A.size2())
throw "Matrix must be square";
unsigned int n = A.size1(); //Size of the matrix
//Early returns for special cases
if (n == 1)
return A(0, 0);
else if (n == 2)
return A(0, 0) * A(1, 1) - A(1, 0) * A(0, 1);
unsigned int i = 0; //Row over which to compute the determinant
double d = 0; //Value of the determinant
for (unsigned int j = 0; j < n; ++j) {
d += (j % 2 == 0 ? 1 : -1) * A(i, j) * det(matrix_minor<Matrix>(A, i, j));
}
return d;
}
int main()
{
boost::numeric::ublas::matrix<double> m(3, 3, 1);
m(0, 0) = 2;
m(1, 1) = 3;
//m = ( (2,1,1), (1,1,1), (1,1,1) )
std::cout << det(m); //Should print 2
}
答案 0 :(得分:4)
templates
在编译时实例化。您的计算不在编译时,因此,编译器无法看到实例化的结束并实例化最大次数。
例如在gcc中,这将是:
In instantiation of ‘B<T>::B(const T&) [with T = B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<B<A<int> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >]’:
new.cpp:34:35: recursively required from ‘typename T::type foo(const T&) [with T = B<A<int> >]’
new.cpp:34:35: required from ‘typename T::type foo(const T&) [with T = A<int>]’
new.cpp:39:18: required from here
new.cpp:22:27: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
B(const T& t) : t(t) {}
模板递归可以这样完成:
template<int N>
constexpr int factorial()
{
return N * factorial<N - 1>();
}
template<>
constexpr int factorial<0>()
{
return 1;
}
这里编译器知道,N
为零时有特定的动作,它会停止递归。
你的例子就是这样的。注意:使用C ++ 17 if constexpr
。
template <typename T, T N>
class A
{
public:
typedef T type;
static constexpr type value = N;
static constexpr type get_value() { return value; }
};
template <typename T>
class B
{
public:
typedef typename T::type type;
static constexpr type get_value() { return T::get_value() - 1; }
};
template <typename T>
typename T::type foo()
{
if constexpr(T::get_value() == 0)
return 0;
else
return T::get_value() + foo<B<T>>();
}
答案 1 :(得分:0)
正如您所发现的那样,您无法以递归方式构造具有运行时值的模板类型,因为模板实例化必须以某种方式停止。
另一个想法是将matrix_minor
修改为不模板嵌套,但代价是更难实现。
template <typename Matrix>
class matrix_minor
{
public:
typedef boost::numeric::ublas::matrix<double>::const_reference const_reference;
typedef boost::numeric::ublas::matrix<double>::size_type size_type;
matrix_minor(const Matrix& A, unsigned int i, unsigned int j) :
A(A), is({i}), js({j}) {}
matrix_minor(const matrix_minor<Matrix>& inner, unsigned int i, unsigned int j) :
A(inner.A), is(inner.is), js(inner.js) { is.push_back(i); js.push_back(j); }
size_type size1() const { return A.size1() - is.count(); }
size_type size2() const { return A.size2() - js.count(); }
const_reference operator () (size_type i_, size_type j_) const
{
// I think this is correct for nested matrix_minors
for (size_type i : is)
{
i_ += i_ >= i;
}
for (size_type j : js)
{
j_ += j_ >= j;
}
return A(i_, j_);
}
private:
const Matrix& A;
vector<unsigned int> is, js;
};