Comment typedef un pointeur sur une méthode qui retourne un pointeur sur la méthode?

StackOverflow https://stackoverflow.com/questions/160974

  •  03-07-2019
  •  | 
  •  

Question

J'ai essentiellement la classe suivante:

class StateMachine {
...
StateMethod stateA();
StateMethod stateB();
...
};

Les méthodes stateA () et stateB () devraient pouvoir renvoyer des pointeurs sur stateA () et stateB (). Comment typer le StateMethod?

Était-ce utile?

La solution

GotW # 57 recommande d'utiliser une classe proxy avec une conversion implicite pour cela. but même.

struct StateMethod;
typedef StateMethod (StateMachine:: *FuncPtr)(); 
struct StateMethod
{
  StateMethod( FuncPtr pp ) : p( pp ) { }
  operator FuncPtr() { return p; }
  FuncPtr p;
};

class StateMachine {
  StateMethod stateA();
  StateMethod stateB();
};

int main()
{
  StateMachine *fsm = new StateMachine();
  FuncPtr a = fsm->stateA();  // natural usage syntax
  return 0;
}    

StateMethod StateMachine::stateA
{
  return stateA; // natural return syntax
}

StateMethod StateMachine::stateB
{
  return stateB;
}
  

Cette solution a trois principaux   points forts:

     
      
  1. Cela résout le problème si nécessaire. Mieux encore, il est digne de ce nom et   portable.

  2.   
  3. Son mécanisme est transparent: vous obtenez une syntaxe naturelle pour le   appelant / utilisateur et syntaxe naturelle pour   propre fonction de la fonction " return stateA; "   déclaration.

  4.   
  5. La surcharge est probablement nulle: sur les compilateurs modernes, la classe proxy,   avec son stockage et ses fonctions, devrait   en ligne et optimiser loin de rien.

  6.   

Autres conseils

Utiliser simplement typedef:

class StateMachine {  

 public:  

  class StateMethod;     
  typedef StateMethod (StateMachine::*statemethod)();   

  class StateMethod {  

    statemethod   method; 
    StateMachine& obj; 

   public:  

    StateMethod(statemethod method_, StateMachine *obj_)  
      : method(method_), obj(*obj_) {} 

    StateMethod operator()() { return (obj.*(method))(); }  
  };  

  StateMethod stateA()  { return StateMethod(&StateMachine::stateA, this); }  

  StateMethod stateB()  { return StateMethod(&StateMachine::stateB, this); }  

};    

EDIT: NJSF m'a prouvé le contraire ici. Vous trouverez peut-être plus facile de gérer les conversions statiques, je vais donc laisser le reste ici.

Il n'y a pas de type statique 'correct' puisque le type complet est récursif:

typedef StateMethod (StateMachine::*StateMethod)();

Votre meilleur choix est d'utiliser typedef void (StateMachine :: * StateMethod) (); puis effectuez le déplorable state = (StateMethod) (this- > * state) () ;

PS: boost :: function nécessite un type de retour explicite, du moins à partir de ma lecture de docs : boost :: function0 < ReturnType >

Ma philosophie est de ne pas utiliser les pointeurs de fonction de membre brut. Je ne sais même pas comment faire ce que vous voulez en utilisant une syntaxe de type pointeur brut, la syntaxe est si horrible. J'aime utiliser boost :: function.

Ceci est presque certainement faux:

class X
{
  public:
    typedef const boost::function0<Method> Method;

    // some kind of mutually recursive state machine
    Method stateA()
    { return boost::bind(&X::stateB, this); }
    Method stateB()
    { return boost::bind(&X::stateA, this); }
};

Ce problème est certainement beaucoup plus difficile qu’il n’est au premier abord

Je ne me souviens jamais de l'horrible fonction C ++ declspec. Ainsi, chaque fois que je dois trouver la syntaxe qui décrit une fonction membre, par exemple, je provoque simplement une erreur intentionnelle du compilateur, qui affiche généralement la syntaxe correcte pour moi.

Donc, étant donné:

class StateMachine { 
    bool stateA(int someArg); 
};

Quelle est la syntaxe de typedef de stateA? Aucune idée .. alors essayons de lui attribuer quelque chose de différent et voyons ce que dit le compilateur:

char c = StateMachine::stateA

Le compilateur dit:

error: a value of type "bool (StateMachine::*)(int)" cannot be used to initialize 
       an entity of type "char" 

Le voici: "bool (StateMachine :: *) (int)" est notre typedef.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top