[英]Problems with friends of class template
我正在嘗試為我的 class 模板創建一些朋友功能。 我知道您必須首先在 class 之外聲明它們,但我得到了一些奇怪的結果。
...
template <typename T>
class Matrix;
template <typename T>
std::ostream& operator<<(std::ostream& os, const Matrix<T>& mtrx);
template <typename T>
std::istream& operator>>(std::istream& is, const Matrix<T>& mtrx);
template <typename T>
Matrix<T> operator*(const T& t, const Matrix<T>& mtrx);
template <typename T>
class Matrix
{
public:
friend std::ostream& operator<< <>(std::ostream&, const Matrix&);
friend std::istream& operator>> <>(std::istream&, const Matrix&);
Matrix operator*(const T&) const;
friend Matrix<T> operator* <>(const T& t, const Matrix& mtrx);
};
...
兩個 stream 運算符對我來說工作正常,但乘法運算符有問題。 出於某種原因,編譯器(Visual Studio)似乎認為我正在嘗試聲明一個數據成員並不斷拋出一堆錯誤。 喜歡
C2460 uses Matrix which is being defined;
C2433 friend not permitted on data declarations;
c2473 looks like a function definition, but there is no parameter list.
據我所知,實現與工作的 stream 運算符相同。 此外,如果我將 operator* 重命名為其他名稱,例如 foo,它可以正常工作。
現在,我實際上不需要把這個 function 變成朋友,我的定義只是顛倒了 arguments 的順序,並調用了成員 function 版本。 但我仍然想知道發生了什么,出了什么問題。
這里有兩件事在起作用。
C++ 編譯器被允許(但不是必需的)在模板被解析時診斷錯誤,而模板的所有實例都會產生該錯誤。
這意味着由於您尚未實例化 class 模板Matrix
,編譯器可以自由地診斷錯誤。 例如,給定程序被 msvc 拒絕,但在 C++20 中被 gcc 和 clang 接受(編譯)。 演示。
所以這不是 msvc 錯誤。 更詳細的解釋請參考Template class compiles with C++17 but not with C++20 if used function can't be compiled 。
另請注意,如果您通過編寫Matrix<int>
為某些模板參數實例化Matrix
,則該程序也會被 gcc 拒絕。 演示。 查看拒絕的原因。
這里要注意的重要一點是,無論您是否為給定的模板參數實例化Matrix
,所有帶有 C++17 的編譯器都會拒絕完全相同的程序。 演示
現在,讓我們看看 C++17 中所有編譯器拒絕程序的原因。
在您給定的程序中,當您嘗試與 function 模板operator*
的特化成為朋友時,編譯器開始查找(查找) operator*
並找到非模板重載版本,因此停止進一步查找。 現在,由於它找到了一個無法專門化的非模板版本,它在所有編譯器中都給出了錯誤。
讓我們看一個人為的例子:
template<typename T> void f(T){
}
template <typename T>
class Matrix
{
public:
int f(const T&) const; //#1
friend void f<>(const Matrix& mtrx); //lookup find #1 and stops looking and so gives error
};;
int main()
{
Matrix<int> m;
}
為了解決上述錯誤,我們必須重新排序聲明,以便在與專業化成為朋友時找不到operator*
的查找。
這意味着我們必須將上述程序更改為:
template<typename T> void f(T){ //#2
}
template <typename T>
class Matrix
{
public:
friend void f<>(const Matrix& mtrx); //lookup find #2
int f(const T&) const; //OK now
};;
int main()
{
Matrix<int> m;
}
要解決您遇到的錯誤,您必須重新排序operator*
的聲明,如下所示:
template <typename T>
class Matrix
{
public:
friend std::ostream& operator<< <>(std::ostream&, const Matrix&);
friend std::istream& operator>> <>(std::istream&, const Matrix&);
//reordered
friend Matrix<T> operator* <>(const T& t, const Matrix& mtrx);
Matrix operator*(const T&) const;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.