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