2017-01-24 67 views
3
#include <utility> 

class Base { 
public: 
    virtual ~Base() {} 
    virtual void base() {} 
}; 

class Derived : public Base { 
public: 
    virtual void derived() {} 
}; 

template<typename... Params> 
using MemberFuncPtr = void(Derived::*)(Params...); 

template<typename... Params, typename... Args> 
void wrapper(MemberFuncPtr<Params...> ptr, Args&&... args) 
{ 
    Derived* d = new Derived(); 

    (d->*ptr)(std::forward<Args>(args)...); 

    delete d; 
} 

int main() 
{ 
    wrapper(&Derived::derived); 
    wrapper(&Derived::base); 
    return 0; 
} 

試圖運行該代碼(GCC 7.0)給了我以下錯誤:模板參數,它指向類成員函數

prog.cc: In function 'int main()': 
prog.cc:33:27: error: no matching function for call to 'wrapper(void (Base::*)())' 
    wrapper(&Derived::base); 
         ^
prog.cc:18:6: note: candidate: template<class ... Params, class ... Args> void wrapper(MemberFuncPtr<Params ...>, Args&& ...) 
void wrapper(MemberFuncPtr<Params...> ptr, Args&&... args) 
     ^~~~~~~ 
prog.cc:18:6: note: template argument deduction/substitution failed: 
prog.cc:33:27: note: mismatched types 'Derived' and 'Base' 
    wrapper(&Derived::base); 
         ^

我真的不明白,爲什麼從基類方法是問題?這也是派生類的一種方法。我已經完成了簡單的測試,其中我分配了Derived::baseDerived::*ptr類型並且工作正常。

回答

3

I don't really understand why method from the base class is an issue?

這只是一個什麼類型的問題。 &Derived::derived的類型爲void (Derived::*)(),但&Derived::base的類型爲void (Base::*)()。那不符合void (Derived::*)(Args...),所以扣除失敗。即使在這種情況下存在有效的模板,模板扣除也不允許轉換。

I've done simple test where I assigned Derived::base to Derived::*ptr type and that worked.

此:

MemberFuncPtr<> d = &Derived::base; 
wrapper(d); 

作品因爲現在d是正確類型的(現在比賽void (Derived::*)(Args...)),和第一行是很好,因爲它是有效的指針轉換爲成員將基類轉換爲指向派生類成員的指針。

+0

我想我應該記住的是,模板扣除不允許轉換。謝謝! –

1

I don't really understand why method from the base class is an issue?

@Barry已經解釋了爲什麼在his answer
作爲一個側面說明,請注意,您可以進一步推廣,並得到它的工作:

// ... 

template<typename T, typename... Params> 
using MemberFuncPtr = void(T::*)(Params...); 

template<typename T, typename... Params, typename... Args> 
void wrapper(MemberFuncPtr<T, Params...> ptr, Args&&... args) 
{ 
    // ... 
} 
+0

我擔心我會被迫在調用網站中投射void void(Derived :: *)()'。很高興知道額外的參數可以處理這個「不同的類型」問題。 –

相關問題