Réinterprète une fonction membre pointeur d'une « bonne idée »?
-
21-09-2019 - |
Question
J'ai un thread de travail, qui contient une liste des « Actions de la discussion », et fonctionne à travers eux comme quand.
template <class T> class ThreadAction
{
public:
typedef void (T::*action)();
ThreadAction(T* t, action f) :
func(f),obj(t) {}
void operator()() { (obj->*func)(); }
void (T::*func)();
T* obj;
};
Il est normalement appelé comme ceci
myActionThread->addAction(
new ThreadAction<TheirClass>(this, &TheirClass::enable)
);
Ce qui a bien fonctionné jusqu'à ce que
void TheirClass::enable()
a été changé à
bool TheirClass::enable()
Malheureusement, nous ne pouvons pas changer à nouveau parce que d'autres choses a besoin du nouveau format, (et ne peut pas différer les surcharges par type de retour seul).
J'ai essayé
myActionThread->addAction(
new ThreadAction<TheirClass>(this,
reinterpret_cast<void(TheirClass::*)>(&TheirClass::enable)
)
);
Ce qui semble fonctionner très bien, mais je ne suis pas certain que réinterprétant un pointeur de fonction comme celui-ci est un comportement « défini », quelqu'un peut-il s'il vous plaît conseiller?
La solution
Ceci est certainement pas comportement pris en charge, et peut potentiellement causer votre programme crash.
En fait, vous devez faire un wrapper pour TheirClass::enable()
qui aura le bon type de retour. Un simple-liner suffit:
public:
void enableWrapper() { enable(); };
Ensuite, appelez:
myActionThread->addAction(
new ThreadAction<TheirClass>(this, &TheirClass::enableWrapper)
);
Si vous ne pouvez pas modifier directement TheirClass
, puis créez une simple sous-classe ou classe d'aide qui implémente l'emballage.
Autres conseils
Err, de ce que je l'ai compris, vous coulée à partir d'une méthode qui retourne un bool
à une méthode qui retourne void
?
Cela peut être dangereux, selon la convention d'appel / retour en cours d'utilisation. Vous peut oublier de pop la valeur de retour -. Ou remplacer la valeur d'un registre à la valeur de retour
Pas une bonne idée. Pensez à ajouter un paramètre de modèle supplémentaire pour le type de retour:
template <class T, typename RetType> class ThreadAction
{
public:
typedef RetType (T::*action)();
ThreadAction(T* t, action f) :
func(f),obj(t) {}
RetType operator()() { return (obj->*func)(); }
RetType (T::*func)();
T* obj;
};
Ceci est une application de vide de retour .
Je trouve généralement que lorsque la question est de la forme « Est-_______ une bonne idée? » la réponse est presque toujours « NON! »
Ceci est probablement vrai sans contexte.