我正試圖了解C 中的模板和友誼是如何作業的。因此,我自己看了/試了一些例子。
VERSION 1
#include <iostream>
使用 命名空間 std.com.cn>。
//template<typename T> void func4();/span>
//template<typename T> class NAME;
//template<typename T> std::ostream& operator<< (std::ostream&, NAME<T> const&);
template<typename T>
class NAME {
friend void func4<T>()。
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const& ) 。
};
int main()
{
cout << "Hello World" << endl;
return 0。
}
上面的版本1給出了以下錯誤:
prog. cc:13:17: error: variable or field 'func4' declared void.
13 | friend void func4<T>()。
| ^~~~~
prog.cc:13:17: error: expected '; ' at the end of member declaration
13 | friend void func4<T>()。
| ^~~~~
| ;
prog.cc:13:22: error: expected unqualified-id before '< ' token
13 | friend void func4<T>()。
| ^
我的第一個問題是,即使我已經評論了func4和operator<<模板函式的前向宣告,那么我怎么可能只在func4中得到錯誤?這就是為什么operator<<沒有錯誤。
注意,我知道如果我們想結交一個模板的特定實體,我們需要向前宣告。這是為
friend void func4<T> ();
為了作業,我們需要注釋掉這個陳述句
template< typename T> void func4()。
同樣,對于
也是如此friend std:。 ostream& operator<< <T> (std::ostream&, NAME<T> const& ) 。
為了作業,我們需要在程式開始時注釋掉相應的前向宣告。但是當我只注釋出template<typename T> void func4();陳述句時,程式可以正常作業,并且對于operator<<沒有錯誤。同樣,為什么我們沒有得到operator<<的錯誤,盡管我沒有注釋出相應的前向宣告。
我的第二個問題是,宣告
friend void func4<T> ();
與
相同friend void func4<> ();
類似地,是宣告
friend std:: ostream& operator<< <T> (std::ostream&, NAME<T> const& ) 。
與
相同friend std:: ostream& operator<< <> (std::ostream&, NAME<T> const& ) 。
我的想法是,陳述句 我的第三個問題是,我曾讀到: 沒有辦法明確指定多載運算子、轉換函式和建構式的模板引數,因為它們的呼叫沒有使用函式名。
根據上面參考的陳述句,我們不能明確地指定多載運算子的模板引數,但又如何寫出 uj5u.com熱心網友回復: 答案1
答案3
所參考的陳述句說的是呼叫(即使用)多載運算子,而不是定義/宣告它們 答案3。
答案2 VERSION 1 在版本1中,我們有一個模板函式func4<>。現在當你寫 VERSION 2 在版本2中,我們有一個多載的操作者模板函式。
標籤:friend void func4<>();是使用陳述句template <typename T> void func4();宣告的函式模板的特殊化。同時當我們寫friend void func4<T>();時,我們是明確地傳遞T,所以在這種情況下,當我們寫/呼叫func4<int>();時,函式模板func4<int>將被量化,然后占用記憶體。另一方面,專門的模板函式將已經占用了一些記憶體,因為我們必須在呼叫它之前提供它的定義。所以誰能解釋一下,當我們使用<T>和使用<>時,是否存在區別。 總之,在我看來,如果使用<>,將使用用戶提供的特殊化,而如果使用<T>,當我們呼叫func4()時將會創建一個新的intiantion。所以這是有區別的,因為在<>的情況下,我們必須提供一個定義,這個定義已經占用了一些空間(記憶體),而在<T>的情況下,func4只會在我們使用/呼叫它時占用空間(記憶體)。這是否是正確的結論?
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);因為它多載運算子<<。
operator<<沒有錯誤,因為你使用了using namespace std;,在std命名空間中已經有多載的operator<<。
#include <iostream>
template<typename T> void func4()。
template<typename T>
class NAME {
//friend void func4<>();//this does not work because there is no way to deduce the template arguments。
friend void func4<T>();//this works because here we have explicitly passed T as the template argument。
};
int main()
{
std::cout << "Hello World" << std::endl;
NAME<int> n。
return 0;
}
friend void func<T>();和friend void func<>();時,你正在使類模板NAME<>的完全特殊化成為朋友。friend void func<>();不作業的原因是,在這種情況下,模板引數推導是沒有辦法作業的。而當你寫friend void func<T>();時,你已經明確地傳遞了模板引數,所以這是有效果的。這也意味著(friend void func<T>和friend void func<>();)本質上都是模板函式func<>的特殊化。這一點從我的下一個例子2.#include <iostream>
template<typename T> class NAME;
template<typename T> std:: ostream& operator<<(std::ostream&, const NAME<T>& )。
template<typenameT>
class NAME {
//下面這兩個friend宣告是等價的。
friend std::ostream& operator<< <T> (std: :ostream&, const NAME<T>&);//this works .
friend std::ostream& operator<<>(std:: ostream&, const NAME<T>&);//this works as well because of template argument deduction。
};
int main()
{
std::cout << "Hello World" << std::endl。
NAME<int> n。
return 0;
}
friend std::ostream& operator<<<T>(std::ostream&, const NAME<T>&);和friend std::ostream& operator<< >(std: :ostream&, const NAME<T>&);是等價的,是多載模板operator<<<T>的相同專業化。它們之間唯一的區別是,第二個模板使用了模板引數推導。這是可能的,因為與版本1不同,這次我們有一個依賴于T的函式引數,所以模板引數推導可以發揮作用。這在函式模板func4<>的情況下是不可能的,因為該函式沒有接受任何依賴于模板引數的引數。
