簡體   English   中英

函數參數包的模板參數推導后跟其他參數

[英]Template arguments deduction for function parameter pack followed by other parameters

f1f2的演繹是否形成不良?

template<class... T, class U>
void f1(T..., U){}

template<class... T>
void f2(T..., int){}

int main()
{
    f1(1);
    f2(1);
    return 0;
}

g ++接受兩者,clang只接受f2 ,而msvc拒絕這兩者。

相關標准措辭:

[temp.deduct.call]

當函數參數包出現在非推導的上下文([temp.deduct.type])中時,永遠不會推導出該參數包的類型。

[temp.deduct.type] P5

未推斷的上下文是:

  • 函數參數包,不會出現在參數聲明列表的末尾。

所以似乎MSVC拒絕兩者都是正確的?

這是否意味着即使您明確指定模板args,模板的任何實例化都將是格式錯誤的?

f1<int>(1, 2); // ill-formed?
f2<int>(1, 2); // ill-formed?

如果是這樣的話,為什么要在第一時間允許這樣的聲明呢?

這個特定問題DR1388有一個DR。 顯然,似乎GCC和CLANG還沒有實現它CLANG DR1388

這是否意味着即使您明確指定模板args,模板的任何實例化都將是格式錯誤的?

 f1<int>(1, 2); // ill-formed? f2<int>(1, 2); // ill-formed? 

如果是這樣的話,為什么要在第一時間允許這樣的聲明呢?

否如果您明確指定模板參數,則不會發生扣減,因此上面顯示的代碼是合法的。

我自己研究過這個問題,我發現得到一個明確的答案是非常困難的。 我可以說, f1(1)應該被拒絕但是f2(1)應該被接受

那說:

  • clang ++ - 5.0接受兩者
  • g ++ - 6接受兩者
  • EDG 4.14拒絕兩者

正如您所指出的,未在列表末尾出現的函數參數包是非推導的上下文([temp.deduct.type] p5):

未推斷的上下文是:

  • ...
  • 函數參數包,不會出現在參數聲明列表的末尾。

和[temp.deduct.call] p1(通過CWG 1388修訂)澄清了從未推斷出這樣的參數包。

當函數參數包出現在非推導的上下文中時,永遠不會推導出該參數包的類型。

另外,[temp.arg.explicit] p3指定:

未以其他方式推導出的尾隨模板參數包(14.5.3)將被推導為空的模板參數序列。

因此,將此考慮到f2(1)調用:包T是一個尾隨模板參數包 (盡管它不是一個尾隨函數參數包 ),因此它推斷為空包並且該調用有效。

但是,對於f1(1) ,包T也不是尾隨模板參數包,因為它后跟U ,因此不會假定每個[temp.arg.explicit] p3為空包。 因此,由於模板參數包T不能推斷出對f1(1)的調用,所以它不應該參與重載決策,並且調用應該失敗。


請注意,在其他討論中提出了幾個類似的問題/示例,但它們都有微妙的不同:

  • CWG 1388CWG 1399的示例代碼中的f(0)調用是有效的,因為有問題的包是尾隨模板參數包,因此它屬於我上面提到的情況。 以下是CWG 1399的代碼:
     template <class... T> void f(T..., int, T...) { } int main() { f(0); // OK f<int>(0,0,0); // OK f(0,0,0); // error } 
  • LLVM 錯誤21774的討論中的示例代碼類似於CWG 1399示例,該包是尾隨模板參數包。 同樣對於這個問題
  • 未解決的CWG 2055涉及類似的測試案例。 無論什么時候解決,它的解決方案都可能會對這個問題中的例子的正確行為有所了解。 以下是CWG 2055中提到的問題:

    目前尚不清楚[標准的當前措辭]是否允許以下​​示例:

     template<typename... T> void f(typename T::type...) { } int main() { f<>(); } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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