[英]Template arguments deduction for parameter type of function pointer involving non-deduced parameter pack
這類似於問題 ,但更具體的情況。 這次,沒有編譯器按預期工作。
template<class T>
struct nondeduced
{
using type = T;
};
template<class T>
using nondeduced_t = typename nondeduced<T>::type;
template<class... T, class U>
void f(void(*)(nondeduced_t<T>..., U)) {}
void g(int, char) { }
int main()
{
f<int>(g); // error?
}
在上面的示例中,不能推導出參數包T
,但是編譯器應該能夠在顯式參數替換包T
之后推導出U
(在這種情況下是單個int
)。
預計上述內容也可以在沒有nondeduced_t
技巧的情況下工作:
template<class... T, class U>
void f(void(*)(T..., U)) {}
因為根據[temp.deduct.type] p5 ,參數包T
已經在非推導的上下文中
未推斷的上下文是:
- 函數參數包,不會出現在參數聲明列表的末尾。
不幸的是,我測試過的編譯器(g ++ / clang)都沒有接受代碼。 值得注意的是,下面的內容適用於g ++和clang。
template<class... T>
void f(void(*)(nondeduced_t<T>..., char)) {}
而且,這對兩者都不起作用:
template<class... T>
void f(void(*)(T..., char)) {}
我的期望是錯的嗎?
通過[temp.deduct.type] p5,其中一個非推斷的上下文是
函數參數包,不會出現在參數聲明列表的末尾。
從未推斷出未作為模板函數的最后一個參數出現的參數包,但完全正確地指定禁用推導的參數類型。 例如
template<class T1, class ... Types> void g1(Types ..., T1);
g1<int, int, int>(1,2,3); // works by non-deduction
g1(1,2,3) // violate the rule above by non-deduced context
但是,即使保留模板參數,也要更改函數參數的順序,刪除非推導的上下文條件並打破參數包的無限擴展。 例如
template<class T1, class ... Types> void g1(T1, Types ...);
g1(1,2,3) // works because its a deduced context.
您的代碼無法編譯有兩個原因:
函數參數的順序創建了一個非推導的上下文 ,它導致函數f中所述模式中的參數包T的類型永遠不會被推導出來。
模板參數T僅作為函數參數中的限定符出現(例如nondeduced_t ),而不是直接指定為函數參數(允許參數推導)。
要使代碼編譯,您要么放置參數包的擴展,因為它忘記了nondeduced_t間接,如
template<class... T,class U>
void f( void(*)(U,T...) ) { }
f(g);
或更改模板參數的順序,並在函數調用中指定模板參數,如
template<class U,class... T>
void f( void(*)(U,typename nondeduced<T>::type...) ) {}
f<int,char>(g);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.