无法推导出模板参数&指向成员的指针 [英] Could not deduce template argument & pointer to member

查看:206
本文介绍了无法推导出模板参数&指向成员的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了使用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 SPKSetterPattern 以及它们对 func 的所有定义,找到与您的实际参数匹配的一个定义,然后将模板参数推导为用于该专门化。



它不起作用。



你不能反向查找模板匹配。





EDIT :由于发表请求:



以下代码推导出具有相同类型的所有参数,已知结果类型 void 和类

  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 of SPKSetterPattern and all their definitions of func, 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 class 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; };

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?

这篇关于无法推导出模板参数&amp;指向成员的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆