#include <type_traits>
#include <iostream>
using namespace std;

template<typename T, typename ...U>
 auto time_function(T&& func, U&& ...args) 
    -> typename enable_if<is_same<decltype(func(args...)), void>::value>::type
{
    std::cout<<"timing void function"<<std::endl;
    std::forward<T>(func)(std::forward<U>(args)...);

    std::cout<<"timing over"<<std::endl;
}

template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args)
 -> typename enable_if<!is_same<decltype(func(args...)), void>::value, decltype(func(args...))>::type
{
    std::cout<<"timing returning function"<<std::endl;
    auto val = std::forward<T>(func)(std::forward<U>(args)...);

    std::cout<<"timing over"<<std::endl;

    return val;
}


void foo(int){}
int foo_return(int){return 0;}

int main()
{

    time_function(foo, 2);
    int i = time_function(&foo_return, 1); //this generates an error
    std::cout<<i<<std::endl;

}