Как организовать универсальный шаблон с возвратом значения функции?
template<class F>
class SafeCall
{
F *funcPtr;
public:
SafeCall(F* func):funcPtr(func){}
template <typename Func, typename ...Args>
typename std::result_of<Func(Args...)>::type
Invoke(Func f, Args&&... args)
{
void* ret_addr_in_stack = _AddressOfReturnAddress();
uintptr_t temp = *(uintptr_t*)ret_addr_in_stack;
*(uintptr_t*)ret_addr_in_stack = 0;
typename std::result_of<Func(Args...)>::type && ret_val=f(args...);
*(uintptr_t*)ret_addr_in_stack = temp;
return ret_val;
}
template<class... Args>
__forceinline decltype(auto) operator()(Args&&... args)
{
return InvokeShellCode(funcPtr,std::forward<Args>(args)...);
}
};
Мне нужно, чтоб при вызове Invoke очищался адрес возврата из стека,по этому надо его восстановить после завершения проксирования функции : *(uintptr_t*)ret_addr_in_stack = temp;, но если тип функции void, тогда происходит ошибка:
typename std::result_of<Func(Args...)>::type && ret_val=f(args...);
//невозможно преобразовать "void" в "int &&"
Непонятно откуда там вообще берется тип int, но и не понятно как сделать универсальную функцию, в которой после вызова проксируемой функци, мы бы могли совершить какие то действия, то есть не писать вот так: return f(args...)
(SafeCall<decltype(Beep)>(Beep))(500,500);//Все ок
(SafeCall<decltype(Sleep)>(Sleep))(500);//Все не ок
Ответы (1 шт):
Автор решения: Chorkov
→ Ссылка
#include <type_traits>
#include <stdio.h>
#include <intrin.h>
template<typename T>
class TempValueRestore
{
T& ref;
T old_value;
public:
__forceinline TempValueRestore( T& ref, T new_value)
: ref(ref)
{
old_value = ref;
ref=new_value;
}
__forceinline ~TempValueRestore()
{
ref=old_value;
}
};
template<class F>
class SafeCall
{
F *funcPtr;
public:
SafeCall(F* func):funcPtr(func){}
template <typename Func, typename ...Args>
decltype(auto) Invoke(Func f, Args&&... args)
{
TempValueRestore< uintptr_t> restorer( *(uintptr_t*)_AddressOfReturnAddress(), 0 );
return f(std::forward<Args>(args)...);
}
template<class... Args>
__forceinline decltype(auto) operator()(Args&&... args)
{
return Invoke(funcPtr,std::forward<Args>(args)...);
}
};
int foo(int,int) { return 0; }
void bar(int,int) { }
int main()
{
(SafeCall<decltype(foo)>(foo))(500,500);//Все ок
(SafeCall<decltype(bar)>(bar))(500,500);//Все не ок
}