[英]Deduction of template arguments for friend function declared in class template
考慮以下示例:
#include <iostream>
template <class T, int V>
struct S
{
friend int Func(T) // decl-1
{
return V;
}
};
struct U
{
friend int Func(U); // decl-2
};
template struct S<U, 42>; // spec-1
int main()
{
std::cout << Func(U{}) << std::endl; // Compiles and prints 42
}
我的理解是表達式Func(U{})
導致函數Func
的非限定名稱查找,並通過 ADL 找到聲明decl-2 。 但是,這不是重載決議的可行候選函數(因為它沒有定義),因此編譯器選擇聲明decl-1 。 誤解,與問題無關,請參閱@LanguageLawyer 的評論
我的問題是標准中的哪些規則允許編譯器使用來自專業規范 spec-1的模板參數來實例化包含decl-1的類模板。
搜索cppreference ,我發現唯一似乎適用的規則是指函數模板的重載解析,並引用:
對於函數模板,執行模板參數推導和檢查任何顯式模板參數,以找到可以在這種情況下使用的模板參數值(如果有):
- 如果兩者都成功,則模板參數用於合成相應函數模板特化的聲明,將其添加到候選集中,並且這些特化被視為非模板函數,除非在決勝規則中另有規定;
- 如果參數推導失敗或合成的函數模板特化格式不正確,則不會將此類函數添加到候選集中。
來源: https ://en.cppreference.com/w/cpp/language/overload_resolution#Details
出於重載決議的目的, decl-1是否被視為函數模板? 編譯器是否使用spec-1合成聲明template int Func<U, 42>(U)
(可能是通過模板參數推導)? 還是這里有別的東西在起作用?
編輯:我可能有的另一個誤解是spec-1到底是什么,我目前的理解是,它是將類模板S
的顯式特化聲明為不完整類型,如果可能,請澄清這是否正確。
我可能還有一個誤解是 spec-1 到底是什么,我目前的理解是,它是將類模板 S 的顯式特化聲明為不完整類型,如果可能,請澄清這是否正確。
這是不正確的。
template struct S<U, 42>; // spec-1
根本不是專業化,而是顯式實例化。
它只是告訴編譯器發出帶有參數T=U
和V=42
的S
的相同實例化,如果您在任何其他上下文中引用S<U, 24>
則會發出這些實例化。
作為不完整類型的專業化看起來像
template <> struct S<U, 42>;
標准中的哪些規則允許編譯器使用專業規范 1 中的模板參數來實例化包含 decl-1 的類模板。
這是在temp.explicit-12中指定的,它指出:
命名類模板特化的顯式實例化定義顯式實例化類模板特化,並且是僅在實例化點已定義的那些成員的顯式實例化定義。
(強調我的)
由於spec-1
是一個明確的實例化定義,結果將是類模板特化S<U, 42>
的實例化
出於重載決議的目的,decl-1 是否被視為函數模板?
不, decl-1
是普通(非模板)函數的定義。 此外,這個decl-1
只不過是在decl-2
中聲明的函數的定義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.