![](/img/trans.png)
[英]Can placeholder type in non-type template parameter involve overload resolution of the function passed as a template argument?
[英]Overload resolution for function templates with auto non-type template parameter
function 在非類型模板參數的情況下,如果參數之一是占位符類型,則重載模板的選擇規則是什么。 我對編譯器的當前行為感到困惑,請考慮下一個示例:
template<int N> struct A{};
template<auto... N> void f(A<N...>);
template<int N> void f(A<N>) {}
template<auto N> void g(A<N>);
template<int N> void g(A<N>) {}
int main() {
f( A<1>{} ); // ok in GCC and Clang, error in MSVC
g( A<1>{} ); // ok in GCC, error in Clang and MSVC
}
這里 MSVC 在兩組重載之間無法達到 select。 另一方面, GCC 始終選擇具有更具體類型<int>
的 function 模板。 Clang 在某種程度上處於中間位置,它更喜歡<int>
而不是參數包<auto...>
,但是在選擇<int>
和<auto>
重載時會出現歧義。 在線演示: https://gcc.godbolt.org/z/4EK99Gjhx
哪一種行為是正確的,或者標准沒有明確說明?
這可能是未指定的,但我們可以解釋具有部分排序規則的實現的一般行為。 在[temp.func.order]中,據說
要生成轉換后的模板,對於每個類型、非類型或模板模板參數(包括其模板參數包),分別合成一個唯一的類型、值或 class 模板,並將其替換為 function 類型中每次出現的該參數模板。
[注1:在為非類型模板參數合成的值的類型中替換占位符的類型也是唯一的合成類型。 ——尾注]
我突出顯示了注釋,它明確表示g<auto>
的轉換模板無效,因為A
需要一個int
參數,但接收到一個合成類型†的值。 因此,從g<int>
模板到g<auto>
模板的推導是有效的,但反之則不行,因此g<int>
被認為更專業。 即我相信 Clang 在g
上是錯誤的。
對於f
我們有來自[temp.deduct.type]/9.2的更簡單的規則,它管理專業化的部分排序,並且即使在用int
替換auto
時也會使可變參數重載更加專業化。
†我在有關無效轉換模板的措辭中找不到任何內容,只有 P0522 中的一個相關條款闡明了無效的重寫形式導致重寫的模板至少不那么專業(部分排序的直觀行為也是如此)。 但即使我們假設A
可以接受任意類型的值,即它本身有一個auto
參數,並且如果我們相應地調整代碼,偏序在 GCC 上仍然有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.