为什么这是有效的?(模板友元函数和带有不同参数的模板类)

Why is this working? (template friend function with template class with different arguments)

本文关键字:参数 友元 有效 为什么 函数      更新时间:2023-10-16

我有一个矩阵类:

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也包括在内的事实。应该是tmatrixx &;T, N, P>等

两件事:

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,它看起来会起作用……这就是你在第一部分所做的