是什么导致了这个张量外积中的无限模板递归

What causes infinite template recursion in this tensor outer product?

本文关键字:无限 递归 张量外 是什么      更新时间:2023-10-16

我正在使用张量的模板化表示来实现外部产品。

张量的基本原型如下所示:

template <int N>
struct Tensor
{
    Tensor<N - 1> x;
    Tensor<N - 1> y;
    Tensor<N - 1> z;
};

具有专门化,Tensor<1>退化为简单向量。我的Outer函数定义为:

template <int N, int M>
Tensor<N + M> Outer(const Tensor<N> &lhs, const Tensor<M> &rhs)
{
    Tensor<N + M> result;
    result.x = Outer(lhs.x, rhs);
    result.y = Outer(lhs.y, rhs);
    result.z = Outer(lhs.z, rhs);
    return result;
}
template <int N>
Tensor<N + 1> Outer(const Tensor<N> &lhs, const Tensor<1> &rhs)
{
    Tensor<N + 1> result;
    result.x = Outer(lhs.x, rhs);
    result.y = Outer(lhs.y, rhs);
    result.z = Outer(lhs.z, rhs);
    return result;
}
template <>
Tensor<2> Outer(const Tensor<1> &lhs, const Tensor<1> &rhs)
{
    Tensor<2> result;
    result.x.x = lhs.x * rhs.x;
    result.x.y = lhs.x * rhs.y;
    result.x.z = lhs.x * rhs.z;
    // and so on
    return result;
}

N阶张量A张量和M阶张量B的外积只是每个A元素与B张量的外积。任何阶张量N1 阶张量的外积定义类似。

基本情况只是两个1阶张量(向量)的外积。除了,如上所述,我在 MSVC 中收到C1202错误:

错误 C1202:递归类型或函数依赖项上下文过于复杂

我在对外产品的定义中做错了什么?

对我来说很干净:

template<int N>
struct Tensor
{
    Tensor<N - 1> x;
    Tensor<N - 1> y;
    Tensor<N - 1> z;
    Tensor() { }
    Tensor(const Tensor<N-1>& X, const Tensor<N-1>& Y, const Tensor<N-1>& Z)
      : x(X), y(Y), z(Z)
    { }
};
template<>
struct Tensor<1>
{
    double x;
    double y;
    double z;
    Tensor() : x(), y(), z() { }
    Tensor(double x, double y, double z) : x(x), y(y), z(z)
    { }
};
template<int N, int M>
Tensor<N + M> Outer(const Tensor<N>& lhs, const Tensor<M>& rhs)
{
    Tensor<N + M> result;
    result.x = Outer(lhs.x, rhs);
    result.y = Outer(lhs.y, rhs);
    result.z = Outer(lhs.z, rhs);
    return result;
}
template<int N>
Tensor<N + 1> Outer(const Tensor<N>& lhs, const Tensor<1>& rhs)
{
    Tensor<N + 1> result;
    result.x = Outer(lhs.x, rhs);
    result.y = Outer(lhs.y, rhs);
    result.z = Outer(lhs.z, rhs);
    return result;
}
template<int N>
Tensor<N + 1> Outer(const Tensor<1>& lhs, const Tensor<N>& rhs)
{
    return Outer(rhs, lhs);
}
Tensor<2> Outer(const Tensor<1>& lhs, const Tensor<1>& rhs)
{
    Tensor<2> result;
    result.x.x = lhs.x * rhs.x;
    result.x.y = lhs.x * rhs.y;
    result.x.z = lhs.x * rhs.z;
    result.y.x = lhs.y * rhs.x;
    result.y.y = lhs.y * rhs.y;
    result.y.z = lhs.y * rhs.z;
    result.z.x = lhs.z * rhs.x;
    result.z.y = lhs.z * rhs.y;
    result.z.z = lhs.z * rhs.z;
    return result;
}
int main()
{
    Tensor<4> a;
    Tensor<4> b;
    Outer(a, b);
}

值得注意的变化是:

  1. Tensor<1>专用化需要在任何Outer重载之前定义。
  2. Tensor<1>专用化需要默认构造,因为Tensor<2>将尝试默认构造其xyz数据成员。
  3. template<int N> Tensor<N + 1> Outer(const Tensor<1> &lhs, const Tensor<N> &rhs)重载需要与template<int N> Tensor<N + 1> Outer(const Tensor<N> &lhs, const Tensor<1> &rhs)对称,或者你需要添加一个需要double的重载来lhs
  4. Tensor<2> Outer(const Tensor<1> &lhs, const Tensor<1> &rhs)重载中删除template<> - 我们在这里重,而不是专门化。