friend
函数声明像第一个例子是奇怪的野兽。 myArray<T,Size>
的每个实例都会创建一个截然不同的friend
函数,只能通过参数依赖查找找到myArray<T,Size>
。
一个免费的operator*
没有声明,这种方式不行。
你可以让你的代码,这样的工作:
template<class Val, class T, int size>
myArray<T,size> operator*(const Val &lhs, const myArray<T,size> &rhs){
myArray<T,size> mat_t;
for(int i = 0;i < size; i++)
mat_t._array[i] = lhs * rhs._array[i];
return mat_t;
}
模板参数这里所有的template<>
列表中列出,他们是从参数*
全部抵扣。
请记住将您的operator*
放在与myArray
相同的命名空间中。
friend myArray operator*(const T&lhs, const myArray &rhs){
myArray mat_t;
for(int i = 0;i < size; i++)
mat_t._array[i] = lhs * rhs._array[i];
return mat_t;
}
非template
朋友operator*
:
不过,就个人而言,我会一起去。再次,其中一个是“产生”每个myArray<T,size>
,但它本身不是template
。这具有某些优点,比如它对转换构造函数更好。
再进一步,我们得到:
friend myArray& operator*=(myArray&mat, const T&scalar){
for(int i = 0;i < size; i++)
mat._array[i] *= scalar;
return mat;
}
friend myArray operator*(const T&scalar, myArray mat){
mat *= scalar;
return mat;
}
friend myArray operator*(myArray mat, const T&scalar){
mat *= scalar;
return mat;
}
,我们先创建一个*=
,然后在它的条款写*
。请注意,*
需要按值myArray
(因为无论如何我需要返回一个副本,也可能在方法外发生),并且我支持mat*scalar
和scalar*mat
和mat*=scalar
。
另请注意,矩阵矩阵...只是工作。
这个friend operator
是一个好主意的原因是说明here。注意代码不能编译。现在编译为#define ADL
to move the operator*
into the class as friends
。 Koenig运营商让operator*
在不作为模板的情况下在template
类上运行,并且模板的参数匹配规则很难正确得到,不会过于狭窄,过于宽泛或使用讨厌的SFINAE。
template<class Array
class=std::enable_if_t<std::is_same<std::decay_t<Array>,myArray>>
>
friend Array operator*=(Array&&mat, const T&scalar){
for(int i = 0;i < size; i++)
mat._array[i] *= scalar;
return std::forward<Array>(mat);
}
这是更复杂的,但确实有趣的事情与完美转发(用于缩写C++ 14):
下一步,operator*=
可以通过得到改善。一个临时的myArray
得到move
d到返回值(它允许参考寿命延长工作),而非临时myArray
返回一个参考。
这提供了一个原因,即使*=
应该是friend
。它允许r和lvalues都以相同的方法实现。
另一方面,可能你不希望*=
与rvalues一起使用。在这种情况下,请使用带有&
参考类别限定符的常规方法来消除该选择。
您有问题吗? – user463035818
模板朋友可能[出了名的困难](https://isocpp.org/wiki/faq/templates#template-friends)得到正确。发布第二个案例的错误和朋友声明。 – TartanLlama
你期望T和大小是什么?你想支持Array是什么?也许你只想让Array成为另一个myArray,在这种情况下,你应该已经指定了。但是,如果您希望函数的返回独立于输入类型而改变类型,那么您需要指定它(然后不能推导出它)。 –
JSF