#include <chrono>
#include <iostream>
#include <ctime>
#include <thread>
#include <tuple>
#include <typeinfo>
#include <functional>
template<typename Fn, typename... Args>
typename std::enable_if<!std::is_void<typename std::result_of<Fn&&(Args...)>::type>::value,
std::tuple<std::chrono::duration<double>, typename std::result_of<Fn&&(Args...)>::type>
>::type
countTime(Fn&& fn, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
auto fnret = std::forward<Fn>(fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start, fnret);
}
template<typename Fn, typename... Args>
typename std::enable_if<std::is_void<typename std::result_of<Fn&&(Args...)>::type>::value,
std::tuple<std::chrono::duration<double>>
>::type
countTime(Fn&& fn, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
std::forward<Fn>(fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start);
}
template<typename R, class C, typename... Args>
typename std::enable_if<!std::is_same<R, void>::value,
std::tuple<std::chrono::duration<double>, R>
>::type
countTime(R (C::*fn)(Args...), C& obj, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
auto fnret = (obj.*fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start, fnret);
}
template<class C, typename... Args>
std::tuple<std::chrono::duration<double>>
countTime(void (C::*fn)(Args...), C& obj, Args&&... args) {
auto start = std::chrono::high_resolution_clock::now();
(obj.*fn)(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
return std::make_tuple(stop - start);
}
void test1() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
void test2(int a) {
std::cout << __PRETTY_FUNCTION__ << " " << a << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(a));
}
int test3(int a) {
std::cout << __PRETTY_FUNCTION__ << " " << a << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(a));
return a;
}
struct A {
int a;
A(int a = 5) {
this->a = a;
std::cout << __PRETTY_FUNCTION__ << " " << a << std::endl;
}
~A() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void test1() {
std::cout << __PRETTY_FUNCTION__ << " " << a << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(a));
}
void test2(int b) {
std::cout << __PRETTY_FUNCTION__ << " " << a << " and " << b << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(a + b));
}
int test3(int b) {
std::cout << __PRETTY_FUNCTION__ << " " << a << " and " << b << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(a + b));
return a + b;
}
};
int main()
{
using namespace std;
{
auto ret = countTime(test1);
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
}
{
auto ret = countTime(test2, 2);
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
}
{
auto ret = countTime(test3, 2);
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
cout << "function returned: " << std::get<1>(ret) << endl;
}
A a;
{
auto ret = countTime(&A::test1, a);
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
}
{
auto ret = countTime(&A::test2, a, 5);
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
}
{
auto ret = countTime(&A::test3, a, 5);
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
cout << "function returned: " << std::get<1>(ret) << endl;
}
{
std::cout << "std::bind(&A::test2, ref(a), 10)" << std::endl;
auto ret = countTime(std::bind(&A::test2, ref(a), 10));
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
}
{
std::cout << "std::bind(&A::test3, ref(a), 15)" << std::endl;
auto ret = countTime(std::bind(&A::test3, ref(a), 15));
cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count()
<< endl;
cout << "function returned: " << std::get<1>(ret) << endl;
}
{
std::cout << "lambda" << std::endl;
auto ret = countTime([](int a) -> int {
std::this_thread::sleep_for(std::chrono::milliseconds(a));
return a * 2;
}, 10);
std::cout << "function executed in: " <<
std::chrono::duration_cast<std::chrono::milliseconds>(std::get<0>(ret)).count() <<
" milliseconds." << std::endl;
std::cout << "function returned: " << std::get<1>(ret) << std::endl;
}
return 0;
}