簡體   English   中英

類模板中聲明的友元函數的模板參數的扣除

[英]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=UV=42S的相同實例化,如果您在任何其他上下文中引用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.

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