同じデータ構造に収容するには互いに異なりすぎる関数ポインタ自体を格納する代わりに、不一致のブリッジを処理するアダプタを格納できます。これは型消去の一形態です。例:
// Imaginary important resources
blaz_type get_blaz();
qux_type get_qux();
// The functions we'd like to put in our map
int foo(blaz_type);
std::string bar(qux_type);
using context_type = std::tuple<blaz_type, qux_type>;
using callback_type = std::function<void(context_type, socket_type&)>;
using std::get;
std::map<std::string, callback_type> callbacks = {
{
"foo"
, [](context_type context, socket_type& out)
{ marshall(out, foo(get<0>(std::move(context)))); }
}
, {
"bar"
, [](context_type context, socket_type& out)
{ marshall(out, bar(get<1>(std::move(context)))); }
}
};
void (*)(context_type, socket_type&)
この例では、アダプターはステートフルではないため、実際にとして使用できますcallback_type
。
この種の設計は、保存されたコールバックが必要とする可能性のあるすべての種類のパラメーターcontext_type
について知る必要があるという点で、少し脆弱であることに注意してください。後で新しい種類のパラメータを必要とするコールバックを保存する必要がある場合は、変更する必要があります-上記の設計を改善して、のようなマジックナンバーをパラメータとして使用しないようにすると、苦痛を軽減できます(特にから型を削除する逆の状況)。すべてのコールバックが同じパラメーターを使用する場合、これは問題ではありません。その場合、完全に不要になり、それらのパラメーターをコールバックに直接渡すことができます。context_type
0
1
std::get
context_type
context_type
LWSでのデモンストレーション。