基本的に私は次のクラスを持っています:
class StateMachine {
...
StateMethod stateA();
StateMethod stateB();
...
};
メソッド stateA() および stateB() は、stateA() および stateB() へのポインターを返すことができる必要があります。StateMethod を typedef する方法は?
基本的に私は次のクラスを持っています:
class StateMachine {
...
StateMethod stateA();
StateMethod stateB();
...
};
メソッド stateA() および stateB() は、stateA() および stateB() へのポインターを返すことができる必要があります。StateMethod を typedef する方法は?
GotW #57では、まさにこの目的のために、暗黙的な変換でプロキシ クラスを使用するように指示されています。
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;
}
このソリューションには、主に次の 3 つの強みがあります。
必要に応じて問題を解決します。さらに良いことに、タイプセーフで移植性があります。
その機構は透過的です。呼び出し元/ユーザーの自然な構文と、関数自体の「return stateA;」の自然な構文が得られます。声明。
オーバーヘッドはおそらくゼロです。最新のコンパイラでは、ストレージと関数を備えたプロキシ クラスをインライン化し、最適化してゼロにする必要があります。
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); }
};
編集: njsf は、ここで私が間違っていることを証明しました。ただし、静的キャストを維持する方が簡単だと思うかもしれませんので、残りはここに残します。
完全な型は再帰的であるため、「正しい」静的型はありません。
typedef StateMethod (StateMachine::*StateMethod)();
あなたの最善の策は、使用typedef void (StateMachine::*StateMethod)();
してから醜いことをすることですstate = (StateMethod)(this->*state)();
PS:boost::function
少なくともドキュメントを読んだことから、明示的な戻り値の型が必要です:boost::function0<ReturnType>
私の哲学は、生のメンバー関数ポインターを使用しないことです。生のポインター typedef の構文を使用して必要なことを行う方法が本当にわかりません。構文は非常に恐ろしいです。boost::function を使用するのが好きです。
これはほぼ確実に間違っています。
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); }
};
この問題は、最初に目にしたよりもはるかに難しいことは間違いありません
私はひどい C++ 関数の declspec を覚えていないので、たとえばメンバー関数を記述する構文を見つけなければならないときはいつでも、通常は正しい構文を表示する意図的なコンパイラ エラーを引き起こすだけです。
与えられた:
class StateMachine {
bool stateA(int someArg);
};
stateA の typedef の構文は何ですか? わからない..だから、それに無関係なものを割り当てて、コンパイラが何を言っているか見てみましょう:
char c = StateMachine::stateA
コンパイラは次のように述べています。
error: a value of type "bool (StateMachine::*)(int)" cannot be used to initialize
an entity of type "char"
「bool (StateMachine::*)(int)」は typedef です。