13

つまり、この巨大なツリーは基本的に大きなスイッチ/ケースであり、文字列キーと、キーと1つのメタデータに応じて1つの共通オブジェクトに対するさまざまな関数呼び出しがあります。

すべてのエントリは基本的に次のようになります

} else if ( strcmp(key, "key_string") == 0) {
    ((class_name*)object)->do_something();
} else if ( ...

ここでdo_somethingはさまざまな呼び出しを行うことができるため、関数ポインターだけを使用することはできません。また、一部のキーでは、オブジェクトをサブクラスにキャストする必要があります。

さて、これを高級言語でコーディングする場合は、ラムダの辞書を使用してこれを単純化します。

マクロを使用して、これを次のようなものに単純化できることに気づきました。

case_call("key_string", class_name, do_something());
case_call( /* ... */ )

case_callこのコードを最初のコードスニペットに展開するマクロはどこにありますか。

しかし、それが良いスタイルと見なされるかどうかについては、私は非常に危機に瀕しています。つまり、タイピング作業が減り、コードのDRYnessが向上しますが、実際にはマクロシステムを多少乱用しているように見えます。

あなたはその道を進みますか、それとも全部をタイプしますか?そして、そうする理由は何ですか?

編集

いくつかの説明:

このコードは、単純なKey-ValueプロパティとしてC++APIのいくつかの異なる側面にアクセスする単純化されたスクリプトAPI間の接着層として使用されます。ただし、プロパティはC++ではさまざまな方法で実装されます。getter/setterメソッドを持つものもあれば、特別な構造体で設定されるものもあります。スクリプトアクションは、共通の基本クラスにキャストされたC++オブジェクトを参照します。ただし、一部のアクションは特定のサブクラスでのみ使用可能であり、キャストダウンする必要があります。

将来的には、実際のC ++ APIを変更する可能性がありますが、現時点では変更できないと見なす必要があります。また、これは組み込みコンパイラで機能する必要があるため、boostまたはC ++ 11は(残念ながら)利用できません。

4

2 に答える 2

6

役割を少し逆にすることをお勧めします。オブジェクトはすでに特定の状況を処理する方法を知っているクラスであると言っているのでvirtual void handle(const char * key)、基本クラスにを追加し、オブジェクトがそれに適用される場合は実装をチェックして、必要なことを何でも実行します。

これにより、長いif-else-ifチェーンが排除されるだけでなく、型の安全性が高まり、これらのイベントをより柔軟に処理できるようになります。

于 2012-05-17T15:57:02.087 に答える
6

それは私にはマクロの適切な使用法のようです。結局のところ、それらは構文の繰​​り返しを排除するために作られています。ただし、構文の繰り返しがある場合、それは必ずしも言語のせいではありません。おそらく、この決定を完全に回避できる、より優れた設計上の選択があります。

一般的な知恵は、キーをアクションにマッピングするテーブルを使用することです。

std::map<std::string, void(Class::*)()> table;

次に、一度にアクションを検索して呼び出します。

object->*table[key]();

またはfind、失敗をチェックするために使用します。

const auto i = table.find(key);
if (i != table.end())
    object->*(i->second)();
else
    throw std::runtime_error(...);

しかし、あなたが言うように、関数に共通の署名がない場合(つまり、メンバー関数ポインターを使用できない場合)、実際に何をすべきかは、プロジェクトの詳細によって異なりますが、私にはわかりません。あなたが見ている繰り返しをなくす唯一の方法はマクロであるかもしれませんし、それを回避するためのより良い方法があるかもしれません。

自問してみてください:なぜ私の関数は異なる引数を取るのですか?なぜキャストを使用しているのですか?オブジェクトのタイプをディスパッチする場合は、共通のインターフェースを導入する必要がある可能性があります。

于 2012-05-17T15:48:11.647 に答える