我正在學習 C 中的模板,因此嘗試了不同的示例。下面給出了一個我無法理解其輸出的示例:
template<typename T> void func(T p) {
g<T>(p); //ERROR
g(p); //NO ERROR?
}
int main()
{
}
當我嘗試編譯上面的代碼片段時,我收到錯誤訊息:
prog.cc: In function 'void func(T)':
prog.cc:2:1: error: 'g' was not declared in this scope
2 | g<T>(p); //ERROR
| ^
prog.cc:2:4: error: expected primary-expression before '>' token
2 | g<T>(p); //ERROR
| ^
我的問題是:
- 為什么我收到此錯誤?
- 為什么我只為陳述句
g<T>(p);而不是為陳述句收到錯誤g(p);?我認為寫作g(p);相當于g<T>(p);因為由于模板引數推導模板引數g將被推導為T.
uj5u.com熱心網友回復:
情況1
在這里,我們考慮以下宣告:g<T>(p);
template<typename T> void func(T p) {
g<T>(p); //ERROR
}
int main()
{
}
在上面的代碼片段中,名稱g是一個不合格的從屬名稱。從源代碼:兩階段查找:
在第一階段,在決議模板時,使用普通查找規則查找不合格的依賴名稱。對于不合格的從屬名稱,初始普通查找(雖然不完整)用于確定名稱是否為模板。
現在讓我們將此應用于陳述句g<T>(p);。決議函式模板時,遇到func陳述句。g<T>(p);由于是g依賴限定名稱,因此根據上面參考的陳述句,使用普通查找規則查找名稱。這樣編譯器就可以決定名稱是否為模板。但是由于沒有宣告在此之前命名的函式模板,因此第一個尖括號被視為小于符號,因此會產生您提到的錯誤。另外,請注意ADL在第二階段完成ggg<. 但要做到這一點,我們必須首先成功決議函式的通用定義func。[來源:C 模板:完整指南:第 250 頁倒數第二段]
請注意,允許編譯器將錯誤延遲到實體化之前,這就是為什么某些編譯器編譯您的代碼而沒有任何錯誤的原因。演示。
案例2
這里我們考慮陳述句g(p);。
template<typename T> void func(T p) {
g(p); // NO ERROR
}
int main()
{
}
在這種情況下,名稱g也是不合格的從屬名稱。因此,根據我的答案開頭參考的陳述句,使用普通查找規則查找名稱g。但是由于此時沒有可見的,我們有一個錯誤。這里有兩點需要注意:g
- 由于這次您沒有明確(通過使用尖括號)呼叫
g,因此沒有語法錯誤。 - 并且由于在這種情況下沒有語法錯誤,并且您的程式中沒有POI ,
func所以這里沒有延遲錯誤并且程式編譯正常。但是,如果您實體化,func那么您將在實體化時收到錯誤,說g沒有宣告。
uj5u.com熱心網友回復:
模板使用兩階段名稱查找。
首先,在模板定義處,檢查模板的語法。
所以g(p);是正確的(從語法的角度來看)(假設ADLg找到了一個函式)。
對于g<T>(p);,我們有(直到 C 20):
盡管即使普通查找什么也沒找到,也可以通過 ADL 決議函式呼叫,但是對具有顯式指定模板引數的函式模板的函式呼叫需要有普通查找找到的模板的宣告(否則,它是語法錯誤遇到未知名稱后跟小于字符)
g<T>(p);不正確,(僅決議為(g < T) > p;(T是一種型別,因此它是錯誤的))。
如果存在任何模板函式g,則g可能被視為模板,并且從語法角度來看代碼是正確的(即使模板引數不匹配)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/425701.html
