1

私は露出しようとしていました

typedef std::function<bool (int)> Filter;

それはの一部です

#include <functional>

ユーザーがフィルターを作成し、それをコンポーネントに渡して処理できるようにします。この要件では、テンプレート化された関数で処理を実行できないことが要求されます。

フィルタタイプのサイズはSTLの実装に依存するため、インターフェイスでSTLを使用することは適切ではないことを理解しています。私の代替オプションは何ですか?ただし、生の関数ポインター、またはテンプレート化された関数によって受信されるファンクターの場合です。

4

3 に答える 3

2

ここではそれほど重要ではないにしてもサイズですが、ライブラリを使用する人がSTLの異なる実装を使用している場合、コードの使用に失敗するので、別のオプションは何ですか?これにはインターフェイス(純粋な仮想クラス)を使用します。

struct MyCallback {
    virtual bool filter( int ) = 0;
};
class MyImplementation {
public:
    ...
    void set_callbacks( MyCallback* );
};

このアーキテクチャを使用すると、ユーザーがC ++の機能を使用できるようにすると同時に、STLに依存する必要がなくなります。

于 2012-10-12T07:21:55.373 に答える
1

の結果として関数ポインタを渡すことができますstd::bind。例えば:

typedef std::function<bool (int)> Filter;

bool Foo(int i)
{
    return i == 0;
}

void BarCaller(Filter bar) //pass by value
{
   bar(2);
}

Filter bar = std::bind(&Foo, std::placeholders::_1); //now you can pass bar wherever you want
BarCaller(bar);
于 2012-10-12T06:24:10.297 に答える
1

Cスタイルのコールバックインターフェイスは通常、関数ポインタとユーザーデータポインタの2つの値を渡すことによって実行されます。必要に応じて、構造体でラップすることでこれを空想することができます。

したがって、dllインターフェイスをCスタイルのままにしたい場合はstd::function、そのペアでラップする手段を提供してください。何かのようなもの:

bool c_style_callback(void *userdata, int n) {
    return (*static_cast<const Filter*>(userdata))(n);
}

呼び出し元のdllで実行され、本当に必要なインターフェイスを提供する便利な関数をヘッダーファイルで提供できます。

inline void register_callback(const Filter &filter) {
   register_c_style_callback(c_style_callback, static_cast<void*>(&filter));
}

filter私は怠惰で、コールバックが登録されている限りそれが有効であり続けることを保証するのは発信者の責任になりました。そのコピーを動的に割り当て、コールバックが登録解除されたときにそれを取得して解放するコードを追加することで、これを修正できます(このコードも呼び出し元のdllで実行されます)。登録解除が呼び出し元によって開始された場合、登録されたコールバックを表す何らかのハンドルが必要になります。

怠惰はFilter、戻った後に再びそれを使用しないアルゴリズムに渡された述語である場合に報われます。フィルタが無期限に登録されている場合にのみ、ライフタイムを管理するためのメカニズム全体が必要になります。

于 2012-10-12T08:31:14.807 に答える