[英]C++ template friend operator overloading
我的代碼有什么問題?
template<int E, int F>
class Float
{
friend Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);
};
G++ 只是不斷警告:
float.h:7: warning: friend declaration 'Float<E, F> operator+(const Float<E, F>&, const Float<E, F>&)' declares a non-template function
float.h:7: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
如警告說明中所述,我嘗試add <> after the function name here
,但是 g++ 給了我一個錯誤。
我用 clang++ 編譯了代碼,很好,根本沒有警告。
這只是關於語言的一個棘手方面的警告。 當你聲明一個friend
函數時,它不是聲明所在類的成員。為了方便你可以在那里定義它,但它實際上屬於命名空間。
在類模板中聲明一個不是模板的友元函數,仍然在命名空間中聲明了一個非模板函數。 它既不是類的成員,也不是模板。 但是,它是由類模板生成的。
從模板生成非模板函數有點模糊。 例如,您不能在class
塊之外為該函數添加聲明。 因此,您也必須在class
塊中定義它,這是有道理的,因為類模板會生成它。
關於朋友的另一個棘手的事情是class Float {}
中的聲明沒有在命名空間中聲明函數。 您只能通過依賴於參數的含義重載解析來找到它,即指定參數具有Float
類型(或引用或指針)。 這對於operator+
來說不是問題,因為無論如何它都可能被重載,並且除了用戶定義的類型之外永遠不會調用它。
作為潛在問題的示例,假設您有一個轉換構造函數Float::Float( Bignum const& )
。 但是Bignum
沒有operator+
。 (對不起,人為的例子。)你想依靠operator+(Float const&, Float const&)
來進行Bignum
加法。 現在my_bignum + 3
將無法編譯,因為這兩個操作數都不是Float
因此它找不到friend
函數。
或許,您無需擔心,只要所討論的函數是operator
。
或者,您也可以將friend
更改為模板。 在這種情況下,它必須在class {}
塊之外定義,並在它之前聲明,而不需要在內部聲明和定義。
template<int E, int F> // now this is a template!
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);
template<int E, int F>
class Float
{
// deduce arguments E and F - this names operator+< E, F >.
friend Float<E, F> operator+<> (const Float<E, F> &lhs, const Float<E, F> &rhs);
};
這是一個相當古老的話題,但我認為聲明運算符的最簡單方法是在 Float 類中定義它。
template<int E, int F>
class Float
{
public:
friend Float operator+ (const Float &lhs, const Float &rhs)
{
// Whatever you need to do.
}
};
語法更容易編寫和理解,並且它的工作方式完全相同(除了它會被內聯),它不會是一個成員函數。
MSDN:在類聲明中定義的友元函數不考慮在封閉類的范圍內; 它們在文件范圍內。
您需要完全按照警告說的做:
template<int E, int F>
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);
template<int E, int F>
class Float
{
friend Float<E, F> operator+<> (const Float<E, F> &lhs, const Float<E, F> &rhs);
};
這將運算符模板的完全特化聲明為類模板的特定實例的朋友。 在對問題的評論中,UncleBens 友好地提供 了一個鏈接,解釋了為什么這如此復雜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.