2015-11-17 89 views
3

我一直在試圖獲取一個模板函數來調用一組類似的函數來避免樣板。爲什麼我的模板參數包不工作?

FooA(float a, Widget* w); 
FooB(int b, Widget* w); 
FooC(int c, Widget* w); 
FooD(int d, int e, Widget* w); 

template <typename... Args> 
static void RunFoo(void (*foo)(Args..., Widget*), Args... args) { 
    Widget w 
    foo(args, &w); 
} 

我不明白爲什麼這工作正常:

float a = 10; 
RunFoo(FooA, a); 

但每當我嘗試用多個參數失敗:

int a = 10; 
int b = 3; 
RunFoo(FooD, a, b); 

它失敗,錯誤編譯: 「候選模板被忽略:失敗的模板參數推演」

這是超越C++模板的功能?

回答

4
template<class T>struct tag {using type=T;}; 
template<class Tag>using type_t=typename Tag::type; 
template<class T>using block_deduction=type_t<tag<T>>; 

template <typename... Args> 
static void RunFoo(block_deduction<void(*)(Args...,Widget*)> foo, Args... args) { 
    Widget w 
    foo(args, &w); 
} 

你不能像Args..., Widget*那樣推導 - 參數包必須是一般的最後一個。

這兩種情況在推論中都是「相等的」。 block_deduction防止在該參數上發生扣減。所以另一個演繹就會發生,並起作用。

請注意,這種扣減通常是一個壞主意。你不想推導出一個參數,並在別處生成一個函數指針。它很脆弱。

這可能會更好:

template <class F, class... Args> 
static std::result_of_t<F(Args..., Widget*)> RunFoo(F&& f, Args&&... args) { 
    Widget w 
    return std::forward<F>(f)(std::forward<Args>(args)..., &w); 
} 

如果傳遞過載設置,包過載過載設置對象設置。 std::result_of_t<?>是C++ 14,用C++ 11中的typename std::result_of<?>::type代替。

+0

@rhi謝謝,這是一個正確的編輯。 – Yakk

相關問題