无法推导出模板参数&指向成员的指针 [英] Could not deduce template argument & pointer to member
问题描述
我遇到了使用Visual C ++的C2783错误(无法推导模板参数),我有以下测试用例:
枚举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,void(ObjectType * obj,typename SPKSetterPattern< TypeCode,ObjectType,U> :: func attrSetter){}
// static inline attrSetter)(U)){}
};
class test
{
public:
template< typename ObjType>
void init()
{
//假定工作
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);
//假设失败
//帮助器< ObjType,B> :: add(this,& test :: setBf);
}
test(){init< test>(); }
void setA(int a){}
void setB(float,float){}
void setC(int,int,int){}
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){}
pre>
并取消注释下面的代码。代码编译。
我不明白为什么,因为'helper :: add'的第二个参数仍然相同...
感谢您的帮助。
解决方案您要求编译器进行反向查找:找到
的所有专业化
以及它们对U
SPKSetterPatternfunc
的所有定义,找到与您的实际参数匹配的一个定义,然后将模板参数推导为用于该专门化。
它不起作用。
你不能反向查找模板匹配。
EDIT :由于发表请求:
以下代码推导出具有相同类型的所有参数,已知结果类型
void
和类类$的方法的参数类型c $ c>:
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<类型名U>
static void ungoodAdd(
ObjectType * obj,
typename SPKSetterPattern< TypeCode,ObjectType,U> :: func attrSetter
)
{
obj; (void)attrSetter;
}
template< typename MethodPtr>
static void add(
ObjectType * pObject,
MethodPtr方法
)
{
typedef typename ArgType< ObjectType,MethodPtr> :: T Arg;
ungoodAdd< Arg>(pObject,method);
}
// template< typename U>
// static inline void add(ObjectType * obj,void(ObjectType * obj,void)(ObjectType * obj,typename SPKSetterPattern< TypeCode,ObjectType,U> :: func attrSetter){} :* attrSetter)(U)){}
};但是,访问一些C ++ 11支持可能std :: 函数
是更好的选择吗?I am encountering the C2783 error with Visual C++ (could not deduce template argument), I have the following test case:
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; }
When commenting the line
static inline void add(ObjectType* obj, typename SPKSetterPattern<TypeCode,ObjectType,U>::func attrSetter) {}
and uncommenting the line following, the code compiles.
I don't understand why, because for me the second argument of 'helper::add' is still the same...
Thanks for help.
解决方案You're asking the compiler to do a reverse lookup: to find all specializations on
U
ofSPKSetterPattern
and all their definitions offunc
, find the one definition that matches your actual argument, and then deduce the template arguments as those used for that specialization.It doesn't work like that.
You don't get reverse lookup for template matching.
EDIT: due to requests in comment:The following code deduces the argument type for a method with all arguments of the same type, and known result type
void
and classClass
: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; };
The original code can then be amended as follows:
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)) {} };
However, with access to some C++11 support probably
std::function
is a better alternative?这篇关于无法推导出模板参数&指向成员的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!