2016-03-07 65 views
1

我想使用指向成員函數指針和參數包的指針調用函數。下面給出代碼:使用參數包推導函數參數類型

class DemoClass { 
public: 
    void Printer(const DemoClass& sc, const int& i) { 
    } 
}; 



template<typename R, typename T, typename ... Args/*, typename ... Params*/> 
void MakeMemberActionDemoClass(R(T::*memberFunction)(Args...), Args&& ... args) 
{ 
} 

int main() 
{ 
    DemoClass d; 
    int z; 
    MakeMemberActionDemoClass(&DemoClass::Printer, d, z); 
} 

我獲得以下錯誤:

error C2782: 'void MakeMemberActionDemoClass(R (__thiscall T::*)(Args...),Args &&...)' : template parameter 'Args' is ambiguous 

1>   could be 'const DemoClass&, const int&' 
1>   or  'DemoClass&, int&' 

如果我刪除& &在MakeMemberActionDemoClass的最後一個參數,僅在誤差差值如下:

1>   could be 'const DemoClass&, const int&' 
1>   or  'DemoClass, int' 

什麼我應該這樣做,以便正確推導參數類型?

由於提前,

+1

使用'R(T :: * memberFunction)(Args ...),Params && ... args',使它們分別被推導出來 –

回答

2

Args兩個實例是在一個可推論上下文。它們必須產生相同的類型,否則你的編譯器會抱怨它不明確。

一種方法是在一個或另一個上下文中阻止演繹。另一種方法是停止連接它們。

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

template<class T>using block_deduction=type_t<tag_t<T>>; 

template<class R, class T, class...Args> 
void MakeMemberActionDemoClass(
    R(T::*memberFunction)(Args...), 
    block_deduction<Args>... args 
) 
{ 
} 

這具有可能將值複製兩次的代價。

template<class R, class T, class...Args, class...Params> 
auto MakeMemberActionDemoClass(
    R(T::*memberFunction)(Args...), 
    Params&&... params 
) 
->decltype((std::declval<T*>()->*memberFunction)(std::declval<Params>()...)) 
{ 
} 

將正確地推斷他們,讓你完美向前進入memberFunction和SFINAE及早檢測到過載故障。

+0

謝謝。請注意我不能使第二個解決方案工作 - 一個decltype。 Visual Studio 2013(更新5)不斷給我一些錯誤。另外,要注意的是,在第一個解決方案中,如果你想創建元組,你將需要使用std :: forward_as_tuple。 – user1578026

+0

@ user1578026我修正了第二個錯字。可能有幫助。但VS2013和2015對'decltype'的支持很差,所以... – Yakk

+0

@Piotr該死的你'操作員 - > *'我的老對手 – Yakk