#ifndef ELFSPY_HOOKIMPL_H #define ELFSPY_HOOKIMPL_H #include "elfspy/HookBase.h" namespace spy { /** * @namespace spy * @class HookImpl * Part of the Hook implementation to distinguish between void and non-void * return values. */ template class HookImpl : public HookBase { public: /// @return collection to register thunks that process return value static std::vector*>& return_thunks(); protected: static std::vector*> return_thunks_; static ReturnType&& use_return(ReturnType&& result); static ReturnType thunk(ArgTypes... args); using Base = HookBase; }; template std::vector*> HookImpl::return_thunks_; template inline std::vector*>& HookImpl::return_thunks() { return return_thunks_; } template ReturnType&& HookImpl::use_return(ReturnType&& result) { for (auto trap : return_thunks_) { trap->invoke(std::forward(result)); } return std::forward(result); } template ReturnType HookImpl::thunk(ArgTypes... args) { Base::run_thunks(std::forward(args)...); return use_return( std::forward((*Base::patch_)(std::forward(args)...))); } /// specialisation for void return template class HookImpl : public HookBase { protected: static void thunk(ArgTypes... args); private: using Base = HookBase; }; template void HookImpl::thunk(ArgTypes... args) { Base::run_thunks(std::forward(args)...); (*Base::patch_)(std::forward(args)...); } } // namespace spy #endif