2012-03-10 53 views
1

我遇到C2783錯誤用Visual C++(不能推斷模板參數),我有以下測試例:無法推斷模板參數&指針構件

enum SPKType { A, B, C, D }; 

template<SPKType TypeCode, class ObjectType, typename U> 
struct SPKSetterPattern 
{ 
    typedef void (ObjectType::* func)(U); 
}; 
template<class ObjectType, typename U> 
struct SPKSetterPattern<B,ObjectType,U> { typedef void (ObjectType::* func)(U,U); }; 
template<class ObjectType, typename U> 
struct SPKSetterPattern<C,ObjectType,U> { typedef void (ObjectType::* func)(U,U,U); }; 
template<class ObjectType, typename U> 
struct SPKSetterPattern<D,ObjectType,U> { typedef void (ObjectType::* func)(U,U,U,U); }; 


template<typename ObjectType, SPKType TypeCode> 
struct helper 
{ 
    template<typename U> 
    static inline void add(ObjectType* obj, typename SPKSetterPattern<TypeCode,ObjectType,U>::func attrSetter) {} 
    //static inline void add(ObjectType* obj, void (ObjectType::*attrSetter)(U)) {} 
}; 

class test 
{ 
public: 
template<typename ObjType> 
void init() 
{ 
    // Supposed to work 
    helper<ObjType,A>::add(this, &test::setA); 
    //helper<ObjType,B>::add(this, &test::setB); 
    //helper<ObjType,C>::add(this, &test::setC); 
    //helper<ObjType,D>::add(this, &test::setD); 
    helper<ObjType,A>::add(this, &test::setAf); 

    // Supposed to fail 
    //helper<ObjType,B>::add(this, &test::setBf); 
} 

test() { init<test>(); } 

void setA(int a) {} 
void setB(float,float) {} 
void setC(int,int,int) {} 
void setD(int,int,int,int) {} 

void setAf(double a) {} 
void setBf(int,double) {} 
}; 

int main() 
{ 
test t; 
return 0; 
} 

當註釋行

static inline void add(ObjectType* obj, typename SPKSetterPattern<TypeCode,ObjectType,U>::func attrSetter) {} 

並取消註釋行後面的代碼編譯。

我不明白爲什麼,因爲我的第二個參數「幫手::添加」仍然是相同的......

感謝您的幫助。

回答

4

你問的編譯器做一個反向查找:找對SPKSetterPatternU和所有專業,他們的func所有的定義,發現您的實際參數相匹配的一個定義,然後推導出模板參數爲那些使用專業化。

它不這樣工作。

您不會得到模板匹配的反向查找。


EDIT:由於在評論請求:

以下代碼推導用於與所有相同類型的參數的方法的參數的類型,並且已知的結果類型void和類Class

template< class Class, class MethodPtr > 
struct ArgType; 

template< class Class, class Arg > 
struct ArgType< Class, void (Class::*)(Arg) > 
{ typedef Arg T; }; 

template< class Class, class Arg > 
struct ArgType< Class, void (Class::*)(Arg, Arg) > 
{ typedef Arg T; }; 

template< class Class, class Arg > 
struct ArgType< Class, void (Class::*)(Arg, Arg, Arg) > 
{ typedef Arg T; }; 

template< class Class, class Arg > 
struct ArgType< Class, void (Class::*)(Arg, Arg, Arg, Arg) > 
{ typedef Arg T; }; 

然後將原來的代碼可以修改如下:

template<typename ObjectType, SPKType TypeCode> 
struct helper 
{ 
    template< typename U > 
    static void ungoodAdd(
     ObjectType*            obj, 
     typename SPKSetterPattern<TypeCode,ObjectType,U>::func attrSetter 
     ) 
    { 
     (void)obj; (void)attrSetter; 
    } 

    template< typename MethodPtr > 
    static void add(
     ObjectType*  pObject, 
     MethodPtr  method 
     ) 
    { 
     typedef typename ArgType< ObjectType, MethodPtr >::T Arg; 
     ungoodAdd<Arg>(pObject, method); 
    } 

    // template<typename U> 
    // static inline void add(ObjectType* obj, typename SPKSetterPattern<TypeCode,ObjectType,U>::func attrSetter) {} 
    //static inline void add(ObjectType* obj, void (ObjectType::*attrSetter)(U)) {} 
}; 

但是,訪問一些C++ 11支持可能std::function是一個更好的選擇?

+0

感謝您的澄清。 但是,這是標準禁止嗎?有沒有辦法做到這一點? – Synxis 2012-03-11 09:01:55

+0

向上。有沒有辦法做到我在我的問題中暴露的內容?我可以通過明確定義每個專業化來解決問題,但它會導致代碼重複... – Synxis 2012-03-13 08:50:10

+0

@Synxis:請參閱編輯。 – 2012-03-13 16:27:00

相關問題