簡體   English   中英

為什么模板參數推導因 std::function 回調的可變參數模板參數而失敗?

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

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