c – 任意函数的计时器

前端之家收集整理的这篇文章主要介绍了c – 任意函数的计时器前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我尝试构建一个函数模板,可以测量任意类型函数的执行时间.这是我到目前为止所尝试的:
#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,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,Args &&... args) -> typename std::enable_if< 
    std::is_same< 
            decltype( fn( std::forward<Args>(args) ... )),double>::type
{
   // Implementation for void case
}

您还应该使用完美转发将参数传递给被调用函数

auto timer(Fn fn,Args && ... args) // ...
                      ~~~^

当你调用这个函数时:

auto ret = fn( std::forward<Args>(args)...);

Demo.请注意,这适用于函数,lambda和可调用对象;几乎所有的东西都有一个operator().

从设计的角度来看,我发现返回std ::对没有问题.由于C 11具有std :: tie,因此返回一对/元组是从函数返回多个结果的合法方式.我会继续说,为了在void情况下保持一致,你应该返回一个只有一个元素的元组.

猜你在找的C&C++相关文章