簡體   English   中英

`std::function` 和之前推導出的模板參數替換失敗 - 為什么?

[英]Substitution failure with `std::function` and previously deduced template parameter - why?

考慮以下代碼:

template <typename> 
struct S { };

void g(S<int> t);

template <typename T>
void f(T, std::function<void(S<T>)>);

嘗試調用時

f(0, g);

我收到以下錯誤:

 error: no matching function for call to 'f' f(0, g); ^ note: candidate template ignored: could not match 'function<void (S<type-parameter-0-0>)>' against 'void (*)(S<int>)' void f(T, std::function<void(S<T>)>); ^

godbolt.org 上的實時示例

雖然我知道通常不能推斷 std::function參數的類型,因為它是非推斷上下文

在這種情況下, T可以首先由傳遞的參數0推斷,然后代入std::function<void(S<T>)>以獲得std::function<void(S<int>)>

我希望在推導T=int之后,編譯器會在簽名中的任何地方替換T ,然后嘗試使用參數g構造std::function參數。

為什么不是這樣? 我認為替換/扣除發生的順序與此有關,但我想看看相關的標准措辭。

額外的問題:這是否可以在未來的標准中進行更改,同時保持向后兼容性,或者這種替代不起作用的根本原因是什么?

雖然我知道通常 std::function 參數的類型無法推斷,因為它是非推斷上下文。

它不是一個非推斷的上下文。 恰恰相反。 由於嘗試對std::function的參數進行推導,但參數不是std::function ,因此推導失敗。 The deduction of template arguments from function arguments must agree for all function arguments. 如果它失敗了,它就完全失敗了。

[temp.deduct.type]

2在某些情況下,使用單個類型 P 和 A 的集合進行推導,在其他情況下,將有一組對應的類型 P 和 A。類型推導是對每個 P/A 對獨立進行的,並且推導的然后組合模板參數值。 如果不能對任何 P/A 對進行類型推導,或者如果對任何 P/A 對的推導導致不止一組可能的推導值,或者如果不同的對產生不同的推導值,或者如果任何模板參數既不是推導的也不是顯式的指定,模板參數推導失敗。

將第二個 function 參數的類型變成非推斷上下文實際上是克服錯誤的方法。

#include <functional>

template<typename T>
struct type_identity {
    using type = T;
};

template <typename> 
struct S { };

void g(S<int> ) {}

template <typename T>
void f(T, typename type_identity<std::function<void(S<T>)>>::type) {}

int main() {
    f(0, g);
}

T從第一個 function 參數成功推導出來,沒有什么可推演的了。 所以推論被認為是成功的。

居住

雖然我知道通常std::function參數的類型無法推斷,因為它是非推斷上下文,但在這種情況下, T可以首先由傳遞的參數0推斷。

這不是真的。 T在這種情況下是可推導出的。 如果您將代碼更改為

template <typename T>
void f(std::function<void(S<T>)>);

int main()
{
    f(std::function<void(S<int>)>(g));
}

代碼將編譯並正確推導出T

您的問題是您將 object 傳遞給無法從中提取T的 function 。 編譯器在嘗試推斷T時不會對 function arguments 進行任何轉換。 這意味着您有一個int和一個 function 作為傳遞給 function 的類型。 它從0獲取int ,然后嘗試從您傳入第二個參數的std::function獲取類型,但由於您沒有傳遞std::function它無法提取T ,因此,您得到一個錯誤。

暫無
暫無

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

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