mf_ptrがクラスのメンバ関数ポインタの typedef であるとします。そして、流れるコードがあります:
map<string, mb_ptr> cmd_table;
cmd_table["exit"] = &class_name::exit;
string cmd;
while (cin >> cmd){
(this->*cmd_table[cmd])();
}
では、while ループを終了するには、関数 exit() をどのように定義すればよいでしょうか?
mf_ptrがクラスのメンバ関数ポインタの typedef であるとします。そして、流れるコードがあります:
map<string, mb_ptr> cmd_table;
cmd_table["exit"] = &class_name::exit;
string cmd;
while (cin >> cmd){
(this->*cmd_table[cmd])();
}
では、while ループを終了するには、関数 exit() をどのように定義すればよいでしょうか?
いくつかのオプションがあります:
exit 関数で例外を発生させ、while ループでキャッチします。
while ループを終了するかどうかに関係なく、すべての関数がブール値を返すようにします。
次のようなことができます。
while (cin >> cmd && !class_name::exitLoop){
(this->*cmd_table[cmd])();
}
class_name::exitLoop
によって true に設定される場所class_name::exit()
。
私は個人的に行きます:
while(cin >> cmd && cmd != "exit") {
(this->*cmd_table[cmd])();
}
使用できます(上記のように指定した方法):
class_name::exit(void) { cin.setstate(eofbit); ... }
...
while(cin >> cmd)
(this->*cmd_table[cmd])();
この場合、ループはコマンドの処理後exit
に終了します(次の反復ラウンド>>
は失敗します)。
より複雑にしたい場合は、カスタムストリーム抽出演算子を作成できます。
friend istream & operator>>(istream & is, class_name::CmdExecutorClass &comm)
{
string cmd;
cin >> cmd;
if (cmd == "exit")
cin.setstate(eofbit);
else
(comm.table[cmd])();
return is;
}
私が見ることができる利点は、次のように簡単に書けることです。
while (cin >> cmd);
エラー/不明なコマンドを処理できます(たとえば、キーの要素が存在しない場合std::map<...>::operator[]
にマップに追加します-それはあなたが望むものではないかもしれません)。
ただし、クラスを作成するにはかなりの接着剤も必要です(埋め込みの「マスター」クラスから参照CmdExecutor
を渡すためのコンストラクターまたはテンプレートなど)。table[]
単純なケースでは、やり過ぎです。
編集:また、クロージング cin
(eof
ビットの設定が効果的に行われること)も望ましくない可能性があることを追加する必要があります。fail
ビット (後で再度クリアできる) の方が、おそらくより適切なオプションです。