2015-11-13 46 views
5

下面是一個小例子,觸發編譯錯誤:爲什麼這種可變參數模板參數替換失敗? (包固定前參數)

#include <utility> 
void foo(int, double, int) 
{} 

template <class... Args> 
void post_forwarder(void(*fun)(Args..., int), Args&&... aArgs) 
{ 
    fun(std::forward<Args>(aArgs)..., 5); 
} 

int main() 
{ 
    post_forwarder(foo, 6, 6.1); // Compilation error on instantiation 
    return 0; 
} 

我懷疑問題是相關的事實是,可變參數模板參數是固定的int參數之前的函數類型擴展,但如果是這樣的話,我無法找到一個合理的理由。

通過鏘3.6報告的錯誤是:

error: no matching function for call to 'post_forwarder' 
note: candidate template ignored: failed template argument deduction 
+1

您能否發佈錯誤?這將有所幫助。 – lodo

+1

另外,推導出'Args && ...'轉發給預期的函數指針'Args ...'並不是一個好的計劃。只要確保你知道這一點。 – Yakk

+0

@Yakk我必須承認,我真的可以使用一些關於你正在提出的觀點的更多細節:) –

回答

7

參數推導這裏失敗:

template <class... Args> 
void post_forwarder(void(*fun)(Args..., int), Args&&... aArgs) 
          // ^^^^^^^ 

該參數的包裝必須在年底前抵扣的一般規則。通常的解決方案是將其包含在不可推論的上下文中,以至於甚至不嘗試扣除:

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

template <class... Args> 
void post_forwarder(void(*fun)(typename identity<Args>::type..., int), Args&&... aArgs) 
{ 
    fun(std::forward<Args>(aArgs)..., 5); 
} 
+0

那麼,從技術上講,第一個'Args ...'已經在非推導的上下文中。 –

+1

@ T.C。是的,但現在它是一個**超級**未推斷的上下文。 [另外,我沒有完整的解釋] – Barry

+0

http://stackoverflow.com/questions/26885239/whats-the-point-of-boostmplidentityttype-here。作爲一個旁註,我真的更喜歡在這些上下文中使用'identity'的別名,比如'dont_deduce',所以即使我不明白這個機制,至少我知道它的目的是什麼。 –

0

編輯:改寫答案:

形式Args..., int不允許推斷Args...

+0

你確定嗎?在'fun'簽名中有一個明確的最後'int',我期望它將'Args ...''限制到前兩個參數。 –

1

這工作:

template <class F, class... Args> 
void post_forwarder(F f, Args&&... aArgs) { 
    f(std::forward<Args>(aArgs)..., 5); 
} 

LIVE DEMO

+1

它確實有效,但問題是試圖理解爲什麼提出的最小示例不起作用? (因爲它是從一個更復雜的系統中提取出來的,你提出的替代方案不能取代預期的功能)。 –

+0

@AdN對不起,我有一些重要的東西,無法回覆。這是一個不可扣除的背景,這就是它失敗的原因。但是你已經有了答案。 – 101010

相關問題