我试图构建一个可以测量任意类型的函数执行时间的函数模板。到目前为止,这是我尝试过的:
#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(...)
功能。有什么办法可以摆脱第二个功能?
(首先我做了什么纠正?)
您可以使用enable_if
或标记调度。Enable_if
在这种情况下,似乎是更快的方法:
#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
}
另外,您应该使用完美转发将参数传递给被调用的函数:
auto timer(Fn fn, Args && ... args) // ...
~~~^
当您调用该函数时:
auto ret = fn( std::forward<Args>(args)...);
演示。注意,这适用于函数,lambda和可调用对象。几乎所有的东西operator()
。
从设计的角度来看,返回没问题std::pair
。由于C ++ 11具有std::tie
,所以返回pair
/tuple
是从函数返回多个结果的合法方法。我要说的是,为了保证void情况的一致性,您应该返回仅包含一个元素的元组。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句