我遇到了使用Visual C ++的C2783错误(无法推断出模板参数),我有以下测试用例:
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) {}
并取消注释以下行,代码编译。
我不明白为什么,因为对我来说'helper :: add'的第二个论点仍然是相同的......
感谢您的帮助。
答案 0 :(得分:4)
您要求编译器进行反向查找:查找U
SPKSetterPattern
及func
所有定义的所有特化项,找到与您的实际匹配的定义参数,然后将模板参数推断为用于该特化的参数。
它不像那样。
您没有获得模板匹配的反向查找。
<小时/> 编辑:由于评论请求:
以下代码推导出具有相同类型的所有参数的方法的参数类型,并且已知结果类型为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
可能是更好的选择吗?