メソッドへのポインタを返すメソッドへのポインタをtypedefする方法は?
-
03-07-2019 - |
質問
基本的に次のクラスがあります:
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)();
を使用して、thenい 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"
それは:&quot; bool(StateMachine :: *)(int)&quot; typedefです。