Como typedef um ponteiro para método que retorna um ponteiro o método?
-
03-07-2019 - |
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?
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:
Ele resolve o problema, conforme necessário. Melhor ainda, é tipo seguro e portátil.
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.
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 ??p>
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