任意功能的定时器 [英] A timer for arbitrary functions
问题描述
我试图建立一个函数模板,可以测量任意类型的函数的执行时间。这是我到目前为止所尝试的:
I tried to build a function template that can measure the execution time of functions of arbitrary type. Here is what I've tried so far:
#include <chrono>
#include <iostream>
#include <type_traits>
#include <utility>
// Executes fn with arguments args and returns the time needed
// and the result of f if it is not void
template <class Fn, class... Args>
auto timer(Fn fn, Args... args)
-> std::pair<double, decltype(fn(args...))> {
static_assert(!std::is_void<decltype(fn(args...))>::value,
"Call timer_void if return type is void!");
auto start = std::chrono::high_resolution_clock::now();
auto ret = fn(args...);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
return { elapsed_seconds.count(), ret };
}
// If fn returns void, only the time is returned
template <class Fn, class... Args>
double timer_void(Fn fn, Args... args) {
static_assert(std::is_void<decltype(fn(args...))>::value,
"Call timer for non void return type");
auto start = std::chrono::high_resolution_clock::now();
fn(args...);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
return elapsed_seconds.count();
}
int main () {
//This call is ambigous if the templates have the same name
std::cout << timer([](double a, double b){return a*b;},1,2).first;
}
注意,我必须有一个不同名称的函数 void(...)
函数。有没有办法摆脱第二个函数?
Notice that I have to have a function with a different name for void(...)
functions. Is there any way to get rid of the second function?
(这是我在第一个地方做的正确吗?)
(And is what I did correct in the first place?)
推荐答案
您可以使用 enable_if
或标签分派。 Enable_if
似乎是这种情况下更快的方式:
You can use enable_if
or tag dispatching. Enable_if
seems to be the quicker way in this case:
#include <type_traits>
template <class Fn, class... Args>
auto timer(Fn fn, Args && ... args) -> typename std::enable_if<
// First template argument is the enable condition
!std::is_same<
decltype( fn( std::forward<Args>(args) ... )),
void >::value,
// Second argument is the actual return type
std::pair<double, decltype(fn(std::forward<Args>(args)...))> >::type
{
// Implementation for the non-void case
}
template <class Fn, class... Args>
auto timer(Fn fn, Args &&... args) -> typename std::enable_if<
std::is_same<
decltype( fn( std::forward<Args>(args) ... )),
void >::value,
double>::type
{
// Implementation for void case
}
将参数传递给调用函数:
Also you should use perfect forwarding to pass the arguments to the called function:
auto timer(Fn fn, Args && ... args) // ...
~~~^
当你调用函数时:
auto ret = fn( std::forward<Args>(args)...);
演示。注意,这适用于函数,lambda和可调用对象;几乎所有的东西都有一个运算符()
。
Demo. Notice that this works with functions, lambda and callable objects; pretty much everything with an operator()
.
从设计的角度来看, code> std :: pair 。由于C ++ 11有 std :: tie
,返回对
/ tuple
是从函数返回多个结果的合法方式。我会继续前进,并说,为了一致性在void case你应该返回一个元组只有一个元素。
From a design standpoint, I see no problem in returning a std::pair
. Since C++11 has std::tie
, returning a pair
/ tuple
is the legitimate way of returning multiple results from a function. I would go forward and say that for consistency in the void case you should return a tuple with only one element.
这篇关于任意功能的定时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!