ここに行きます(未テスト):
template <typename HOOK, typename RET, typename... ARGS>
struct BeforeHook {
std::function<RET(ARGS...)> functor;
HOOK hook;
BeforeHook(blah) : blah {};
RET operator()(ARGS&&... args) const {
hook();
return functor(args...);
}
};
template <typename HOOK, typename RET, typename... ARGS>
BeforeHook<HOOK, RET, ARGS...> hook_before(const std::function<RET(ARGS...)> &original, HOOK hook) {
return BeforeHook<HOOK, RET, ARGS...>(original, hook);
}
使用法:
auto hooked = hook_before(original_functor, hook_functor);
hooked(args_for_original_functor); // calls hook_functor, then original_functor
または、それらの線に沿った何か。original_functor は に変換可能である必要がありますがstd::function
、呼び出し可能なものはほとんどすべてです。const
どちらのファンクターもコスト呼び出し可能である必要がありますが、必要に応じてfromを削除できoperator()
ます。
のインスタンスではなくラムダを返すことを試してみたい場合は、テンプレート引数とBeforeHook
で同じトリックを使用し、ラムダでテンプレート引数パックを使用できるかどうかを確認してください。RET
...ARGS
template <typename HOOK, typename RET, typename... ARGS>
std::function<RET(ARGS...)> hook_before(const std::function<RET(ARGS...)> &original, HOOK hook) {
return [=](ARGS&&... args) -> RET {
hook();
return original(args...);
};
}
std::function
いずれにせよ、重要なトリックは、テンプレートの引数推定で使用して、戻り値の型を引数から分離することだと思います。