簡體   English   中英

class模板的朋友有問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM