Pergunta

Basicamente, eu tenho a seguinte classe:

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

A métodos stateâ () e stateB () deve ser ponteiros de retorno capazes de stateâ () e stateB (). Como typedef o StateMethod?

Foi útil?

Solução

GotW # 57 diz para usar uma classe proxy com uma conversão implícita para este fim.

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;
}

Esta solução tem três principais pontos fortes:

  1. Ele resolve o problema, conforme necessário. Melhor ainda, é tipo seguro e portátil.

  2. A sua máquina é transparente: Você começa sintaxe natural para o chamador / utilizador, e sintaxe natural para própria "stateâ retorno;" da função declaração.

  3. Provavelmente tem zero sobrecarga: On compiladores modernos, a classe proxy, com o seu armazenamento e funções, deverá em linha e optimize a nada.

Outras dicas

Usando apenas 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 me provou errado aqui. Você pode achar estática lançando mais simples de manter, no entanto, por isso vou deixar o resto aqui.

Não há nenhum tipo estático 'correta' desde o tipo completo é recursiva:

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

Sua melhor aposta é usar typedef void (StateMachine::*StateMethod)(); depois fazer o state = (StateMethod)(this->*state)(); feio

PS: boost::function requer um tipo de retorno explícito, pelo menos do meu leitura do docs : boost::function0<ReturnType>

A minha filosofia é não usar ponteiros de função membro matérias. Eu nem sequer realmente sabe como fazer o que quiser usando ponteiro bruto typedef é a sintaxe é tão horrível. Eu gosto de usar boost :: função.

Esta é quase certamente errado:

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); }
};

Este problema é definitivamente muito mais difícil do que parece à primeira vista

Eu nunca me lembro da horrível C ++ função declspec, então sempre que eu tenho que descobrir a sintaxe que descreve uma função membro, por exemplo, eu só induzir a um erro do compilador intencional, que normalmente exibe a sintaxe correta para mim.

Assim, dado:

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

O que é a sintaxe para typedef de stateâ? Nenhuma idéia .. então vamos tentar atribuir a ele algo não relacionado e ver o que o compilador diz:

char c = StateMachine::stateA

Compiler diz:

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

Aí está:. "Bool (StateMachine :: *) (int)" é o nosso typedef

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top