2010-08-04 18 views
3

S'il vous plaît se référer le code ci-dessous:incapable de passer la fonction de modèle comme paramètre de rappel

typedef void (*TimerCallback)(int RequestID_in, void* AdditionalParameter_in); 
class MyTimer 
{ 
    public: 
     MyTimer(){} 
     bool schedule(int Interval_in, TimerCallback TimerCallback_in, void* AdditionalParameter_in) 
     { 
      //some logic 
      return true; 
     } 
}; 

namespace 
{ 
    template <class T> 
    void myTimerFunc(int RequestID_in, void* AdditionalParameter_in) 
    { 
     MyLogic<T>* pLogic = static_cast<MyLogic<T>*>(AdditionalParameter_in); 
     if(pLogic) 
     { 
      //do something 
     } 
    } 
} 

template <class T> 
class MyLogic 
{ 
public: 
    MyLogic(){} 

    void testMe() 
    { 
     MyTimer aTimer; 
     aTimer.schedule(10, myTimerFunc<T>, this); 
    } 
}; 

int main() 
{ 
    MyLogic<int> myLogic; 
    myLogic.testMe(); 
} 

J'utilise le compilateur VC6 et le compilateur plaids l'erreur suivante:

error C2664: 'schedule' : cannot convert parameter 2 from 'void (int,void *)' to 'void (__cdecl *)(int,void *)' None of the functions with this name in scope match the target type E:\test\BTest\BTest.cpp(46) : while compiling class-template member function 'void __thiscall MyLogic::testMe(void)'

Je l'ai testé ce code dans Visual Studio 2008 et ça marche bien sans aucun problème.

Je sais que VC6 est un compilateur obsolète mais mon code source du projet (hérité) est toujours compilé avec VC6.

Par conséquent, tout travail autour de possible de compiler ce code?

+0

Avec l'étiquette "6" vous voulez dire VC6? – codymanix

+0

oui. Je changerai. –

+0

avec '& myTimerFunc ', cela fonctionne-t-il? – Scharron

Répondre

0

Je crois que vous manquez un __stdcall là-bas:

typedef void (__stdcall *TimerCallback)(int RequestID_in, void* AdditionalParameter_in); 

Je ne sais pas pourquoi, mais c'est ce que le message d'erreur suggère. Peut-être que vous avez un paramètre de compilateur qui lui dit de supposer __stdcall au lieu de __cdecl, ou vice versa.

+0

Non, même avec la convention d'appel par défaut __cdecl this happend. Le compilateur n'obtient plus que 'void (__cdecl *) (int, void *)' est du même type que 'void (*) (int, void *) ' –

+0

Avez-vous essayé de définir __cdecl sur cette fonction manuellement? – Puppy

+0

Cela ne marche pas non plus. J'ai lancé VS6 avec le code d'OP pour vérifier cela aussi. C'est un bug de compilateur - Voir ma réponse. –

1

Toutes les versions de Visual Studio que j'ai rencontrées obtiennent des saisies lorsqu'elles doivent résoudre/convertir des fonctions de modèle en pointeurs de fonction. La solution que j'utilise, est d'utiliser une fonction id() qui renvoie son argument inchangé:

template<class T> 
T id(T t) 
{ 
    return t; 
} 

template <class T> 
class MyLogic 
{ 
public: 
    MyLogic(){} 

    void testMe() 
    { 
     MyTimer aTimer; 
     aTimer.schedule(10, id(myTimerFunc<T>), this); 
     //------------------^^(   ) 
    } 
}; 

Cette compile sous Visual Studio 6. S'il vous plaît noter que le type de myTimerFunc ne change pas ici, il aide simplement le compilateur pour résoudre les choses.

+0

Toutes les versions, ce code compile bien sur VS2010 et Je m'attends à ce qu'il le fasse aussi sur VS2008 – Puppy

+0

VS2010 est génial, alors ils ont probablement trié ça pour 2008. Pour l'année 2008, regardez ici: http://stackoverflow.com/questions/3395468/overloading-operator-to- accept-a-template-function Un problème similaire (conversion de la fonction de modèle en pointeur de fonction) OP a choisi ma solution de contournement pour la réponse En outre, je ne dis pas que chaque version tombe sous le même code. expérience, que ce type de conversion a tendance à être problématique avec VS. –

+0

En outre, une explication pour le downvote serait agréable. Ma déclaration était subjective ("Tout ce que j'ai rencontré") et n'a fait aucune assertion sur toutes les versions de VS. –