簡體   English   中英

涉及非推導參數包的函數指針的參數類型的模板參數推導

[英]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.

您的代碼無法編譯有兩個原因:

  1. 函數參數的順序創建了一個非推導的上下文 ,它導致函數f中所述模式中的參數包T的類型永遠不會被推導出來。

  2. 模板參數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.

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