[英]Why does the variadic template argument deduction fail for this function pointer?
[英]Why does template argument deduction failed with variadic template parameters of a std::function callback?
讓我們考慮以下功能:
// run_cb_1(): Explicitly defined prototype
void run_cb_1(const std::function<void(int)> & callback, int p)
{
callback(p);
}
// run_cb_2(): One template parameter
template <typename T>
void run_cb_2(const std::function<void(T)> & callback, const T & t)
{
callback(t);
}
// run_cb_3(): Variable number of template parameters
template <typename ... Args>
void run_cb_3(const std::function<void(Args...)> & callback, const Args & ... args)
{
callback(args...);
}
現在,如果我想按如下方式使用這些功能:
int main()
{
auto f = [](int a){
std::cout << a << '\n';
};
run_cb_1(f, 5); // OK
run_cb_2(f, 5); // KO --> I understand why
run_cb_2<int>(f, 5); // OK
run_cb_3(f, 5); // KO --> I understand why
run_cb_3<int>(f, 5); // KO --> I don't understand why...
return 0;
}
我使用run_cb_2()
和run_cb_3()
得到“沒有匹配的 function 調用” ,而它與run_cb_1()
完美配合。
我認為它的行為符合預期,因為我沒有提供模板參數的類型(因為它不能像run_cb_1()
那樣簡單地推斷出來)。
但是指定模板類型可以解決run_cb_2()
的問題(如我所料),但不能解決run_cb_3()
的問題。
我知道我可以通過明確聲明f
來解決它:
std::function<void(int)> f = [](int a){
std::cout << a << '\n';
};
或通過 f 傳遞:
run_cb_2(std::function<void(int)>(f), 5);
run_cb_3(std::function<void(int)>(f), 5);
我的問題是:為什么即使明確指定模板類型,模板參數推導run_cb_3()
(帶有可變參數模板參數)而失敗?
很明顯,我錯過了一些東西(也許是基本的),但我不知道它是什么。
任何幫助將不勝感激。
失敗的原因是編譯器可以使用的類型不止一種。 當你這樣做
run_cb_2<int>(f, 5);
編譯器查看run_cb_2
並看到只有一個模板參數。 由於您已提供它跳過扣除階段並標記出run_cb_2<int>
。
和
run_cb_3<int>(f, 5);
你在另一條船上。 run_cb_3
有一個可變參數模板參數,這意味着僅提供int
不足以跳過扣除。 您指定了第一個參數,但可能還有更多參數,因此它會進入參數推導階段以找出答案。 這意味着它會檢查callback
以確保它在那里推斷出的內容與它為args
推斷出的內容相匹配。 由於 lambda 不是std::function
它不能從中推斷出Args...
一旦發生這種情況,編譯器就會停止並發出錯誤。
使用run_cb_3<int>
,您無需明確提供完整的Args...
,只是第一種類型; 它可能還有其他。
例如在 function 中使用它,例如std::make_unique
:
template <class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args);
和
std::make_unique<MyObj>(var1, var2); // T = MyObj
// Args... = [decltype((var1)), decltype((var2))]
額外的參數是從參數推導出來的。
要強制評估,您可以使用:
(&run_cb_3<int>)(f, 5); // OK
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.