Не удалось вывести аргумент шаблона и указатель на член - PullRequest
1 голос
/ 11 марта 2012

Я сталкиваюсь с ошибкой 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) {}

ираскомментируя следующую строку, код компилируется.

Я не понимаю почему, потому что для меня второй аргумент 'helper :: add' все тот же ...

Спасибо запомощь.

1 Ответ

4 голосов
/ 11 марта 2012

Вы просите компилятор выполнить обратный поиск: найти все специализации на 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 является лучшей альтернативой?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...