![](/img/trans.png)
[英]Why does the variadic template argument deduction fail for this function pointer?
[英]Why does template argument deduction fail with overloaded function?
我有一個模板函數,它應該使用函數指針和參數,然后使用給定的參數調用函數指針(讓我們稱之為Invoke
)。 但是,當我使用重載函數作為參數調用模板函數時,模板推導失敗。
我使用了enable_if,只有一個重載才有效,但這沒有幫助。
#include <string>
#include <type_traits>
void foo(int, int){}
void foo(std::string, std::string) {}
template <bool Val1, bool Val2, bool ...Rest>
struct And
{
enum {value = And<Val1 && Val2, Rest...>::value};
};
template <bool Val1, bool Val2>
struct And<Val1, Val2>
{
enum {value = Val1 && Val2};
};
template <typename ...Params, typename ...Args, typename = typename std::enable_if<
And<std::is_convertible<Args, Params>::value...>::value
>::type>
void Invoke(void (*fn)(Params...), Args ...args){}
int main() {
Invoke(&foo, "a", "b");
return 0;
}
試試ideone 。
當兩個重載都存在時,編譯器會mismatched argument pack lengths while expanding 'std::is_convertible<Args, Params>::value'
時抱怨mismatched argument pack lengths while expanding 'std::is_convertible<Args, Params>::value'
。 當我注釋掉int
重載時,程序編譯得很好,當我注釋掉std::string
重載時,推理會失敗,因為const char[]
不能隱式轉換為int
。
標准(C ++ 17標准的第17.8.2.1.6.2節)說明如下:
如果參數是重載集(不包含函數模板),則嘗試使用集合中的每個成員進行試驗參數推導。 如果僅對其中一個重載集成員進行推導成功,則該成員將用作推導的參數值。 如果對重載集的多個成員進行推導成功,則將該參數視為非推導上下文。
所以我希望編譯器會嘗試int
重載,其中演繹會失敗。 當它嘗試std::string
重載時,推論會成功。
由於演繹只對其中一個重載集成員成功,我希望它會繼續進行,就好像int
重載不存在一樣,並且編譯會像其他重載被注釋掉時那樣成功,但是失敗。
我哪里錯了?
參考標准將不勝感激。
&foo
不是函數指針,而是重載集。 你必須明確:
Invoke(static_cast<void(*)(std::string, std::string)>(&foo), "a", "b");
為了簡化失敗的enable_if
,您可以使用一個未指定的函數指針類型,使用可變參數的arugment包,並檢查is_invocable
: https : is_invocable
這里的問題是有多個功能可以工作。 Params...
的推論Params...
將在您進入模板的SFINAE部分之前發生。 當它試圖從void (*fn)(Params...)
推導出Params..
它匹配void foo(int, int)
和void foo(std::string, std::string)
。 由於它找到了多個匹配項,因此17.8.2.1.6.2聲明它被視為非推導的上下文。
由於它無法推斷出類型,因此您會遇到硬停止錯誤。 SFINAE僅在模板參數扣除步驟之后發生,在這種情況下無法達到。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.