Как организовать универсальный шаблон с возвратом значения функции?

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);//Все не ок
}

→ Ссылка