用模板实现对任意函数计时功能


前言

前面一篇文章利用了可变参宏去实现任意函数计时功能,总觉得有点挫,而且无法带返回值。突然想到可以用模板实现这个功能。下面讲一下实现思路和中间碰到的问题。


一、万能函数模板

先介绍一下万能函数模板,用下面两个函数模板,无论是全局函数,还是类成员函数,统统可以执行。原理就是万能函数指针加上可变参。省略号的位置自己体会一下。

template<typename R, typename... Args>
R CheckPerf(R(*ptr)(Args...), Args... args)
{
    
    
	return ptr(args...);
}
template<typename R, typename T,typename... Args>
R CheckPerf(R(T::*ptr)(Args...), T* obj, Args... args)
{
    
    
	auto func = std::bind(ptr,obj);
	return func(args...);
}

二、void返回值问题

我要把函数放在中间计时,然后最后返回结果。自然而然的是想到分两种情况,因为void是无法定义中间变量的,于是我就写了下面的代码。但总感觉有点憨憨。

//返回值为void,
//当然可以去掉一些东西,typename std::enable_if这可以完全不要,直接特化
//但为了学习嘛
template<typename R, typename... Args>
typename std::enable_if<std::is_same<R, void>::value == true, R>::type
CheckPerf(char* funcname, R(*ptr)(Args...),  Args... args)
{
    
    
	auto t1 = chrono::system_clock::now();
	ptr(args...);
	auto t2 = chrono::system_clock::now();
	auto time = chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
	printf("[%s] pass time:%lld ms\n", funcname, time);
}

//返回值不为void
template<typename R, typename... Args>
typename std::enable_if<std::is_same<R, void>::value == false, R>::type
CheckPerf(char* funcname, R(*ptr)(Args...),  Args... args)
{
    
    
	auto t1 = chrono::system_clock::now();
	R result = ptr(args...);
	auto t2 = chrono::system_clock::now();
	auto time = chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
	printf("[%s] pass time:%lld ms\n", funcname, time);
	return result;
}

三、利用局部变量计时,解决void返回值接收问题

我们可以在局部变量的构造函数中记录开始时刻,析构函数中记录结束时刻,这样就可以直接return 函数,不用接收中间结果。

#include <functional>
#include <chrono>
class Time_span{
    
    
public:
	Time_span(char* funcname,int& time):time(time)
	{
    
    
		t1 = chrono::system_clock::now();
		this->funcname = funcname;

	}
	~Time_span()
	{
    
    
		auto t2 = chrono::system_clock::now();
		time = chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
		printf("[%s] pass time:%d ms\n", funcname.c_str(), time);
	}
private:
	std::chrono::system_clock::time_point t1;
	std::string funcname;
	int& time;

};
template<typename R, typename... Args>
R CheckPerf(char* funcname, int& time, R(*ptr)(Args...), Args... args)
{
    
    
	Time_span span(funcname,time);
	return ptr(args...);
}

完全版代码

class Time_span{
    
    
public:
	Time_span(char* funcname,int& time):time(time)
	{
    
    
		t1 = chrono::system_clock::now();
		this->funcname = funcname;

	}
	~Time_span()
	{
    
    
		auto t2 = chrono::system_clock::now();
		time = chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
		printf("[%s] pass time:%d ms\n", funcname.c_str(), time);
	}
private:
	std::chrono::system_clock::time_point t1;
	std::string funcname;
	int& time;

};
template<typename R, typename... Args>
R CheckPerf(char* funcname, int& time, R(*ptr)(Args...), Args... args)
{
    
    
	Time_span span(funcname,time);
	return ptr(args...);
}

template<typename R, typename T,typename... Args>
R CheckPerf(char* funcname,int& time R(T::*ptr)(Args...), T* obj, Args... args)
{
    
    
	Time_span span(funcname,time);
	auto func = std::bind(ptr,obj);
	return func(args...);
}
class Test
{
    
    
public:
	void print() {
    
    }
};

int TestFunc(int a,int b){
    
    return 1;}

#define check_perf_time_return(func,t,...) CheckPerf(#func,t,func, ##__VA_ARGS__)

int main()
{
    
    
  Test test;
  int time;
  check_perf_time_return(&Test::print,time,&test);
  check_perf_time_return(TestFunc,time,1,2);
}

Guess you like

Origin blog.csdn.net/qq_16952303/article/details/121149464