【问题标题】:Why is this working? (template friend function with template class with different arguments)为什么这行得通? (具有不同参数的模板类的模板友元函数)
【发布时间】:2014-07-22 02:44:45
【问题描述】:

我有一个矩阵类:

template <typename T, const int N, const int M>
class TMatrixNxM
{
    (...)
    friend TMatrixNxM operator*(const TMatrixNxM&, const TMatrixNxM&);
    (...)
}

现在,在数学中,将 NxM 矩阵与 MxP 矩阵相乘会返回 NxP 矩阵。因此,我需要一个返回 NxP 矩阵的运算符,并将 NxM 和 MxP 矩阵作为参数,如下所示:

template <typename T, const int N, const int M, const int P>
TMatrixNxM<T, N, P> operator*(const TMatrixNxM<T, N, M> &par_value1, const TMatrixNxM<T, M, P> &par_value2)
{
    TMatrixNxM<T, N, P> result;

    (...) //Calculate

    return result;
}

当我测试它时:

TMatrixNxM<float, 2, 3> m1;
(...) //Set the values

TMatrixNxM<float, 3, 4> m2;
(...) //Set the values

TMatrixNxM<float, 2, 4> m3 = m1 * m2;

m1.print(); //Matrix class has a print function for testing
printf("\n");
m2.print();
printf("\n");
m3.print();

它就是这样工作的。这究竟是如何以及为什么起作用的?重载运算符需要一个额外的模板参数,而类只需要 3 个,并且在声明中我没有指定任何内容。但是,如果我这样声明:

template <typename T, const int N, const int M>
class TMatrixNxM
{
    (...)
    template<typename T, const int N, const int M, const int P> friend TMatrixNxM<N, P> operator*(const TMatrixNxM<N, M>&, const TMatrixNxM<M, P>&);
    (...)
}

然后编译器抱怨模板参数太少。我希望我不会在这里遗漏一些明显的东西。

谢谢!

编辑

我现在看到“争论太少”的抱怨是针对我没有包括 T 的事实。应该是 TMatrixNxM 等

【问题讨论】:

  • 您的问题是编译器如何知道 template&lt;typename T&gt; void foo(T); foo(42); 之类的模板参数?
  • 将非类型模板参数声明为const 对我来说没有多大意义。无论如何它是不可变的。
  • 当然TMatrixNxM&lt;N, P&gt; 的模板参数太少了。
  • 是的,我明白了,事实证明我确实错过了一些明显的东西。你也是对的,dyp,我想我是不假思索地自动做到的,但这并不重要。

标签: c++ templates friend


【解决方案1】:

两件事:

1) 编译器理解类的模板参数和函数的模板参数之间的区别。您可以拥有一个具有 3 个模板参数的类和一个具有 4 个模板参数的函数。

所以当你声明时:

template <typename T, const int N, const int M, const int P>
TMatrixNxM<T, N, P> operator*(const TMatrixNxM<T, N, M> &par_value1, constXX TMatrixNxM<T, M, P> &par_value2)

您已经定义了一个接受 4 个模板参数的函数。然后,当编译器看到:

TMatrixNxM<float, 2, 4> m3 = m1 * m2;

编译器推导出 4 个模板参数:T、N、M 和 P。它推导出 T = float、N = 2、M = 4,并且 P = 来自 par_value2 的第三个模板参数。

还要注意,函数的模板参数名称不必与类上的模板参数名称相同:

template <typename FOO, const int BAR, const int BAZ, const int QUX>
TMatrixNxM<FOO, BAR, QUX> operator*(const TMatrixNxM<FOO, BAR, BAZ> &par_value1, const TMatrixNxM<FOO, BAR, QUX> &par_value2)

2) 在您的第二个示例中,您确实缺少模板参数。您正在尝试返回 TMatrixNxM 但 TMatrixNxM 需要 3 个参数。如果您将返回类型更改为 TMatrixNxM,看起来它会起作用......这就是您在第一部分中所做的。

【讨论】:

  • 啊,是的,您对第二点是正确的。但是我不明白第一点,那么编译器如何处理那个额外的参数呢?
  • 编译器在编译函数调用时推导出函数的模板参数。我会更详细地更新我的答案。
  • 只是为了好玩和学习,尝试编译这一行:auto m3 = m1 * m2;它应该仍然能够仅从 m1 和 m2 中计算出 T、N、M 和 P。它不应该需要你的“帮助”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-19
  • 1970-01-01
  • 2011-07-30
  • 1970-01-01
  • 2011-10-01
  • 2016-10-19
相关资源
最近更新 更多