通用函数调度机制

Oma*_*air 3 c++ templates c++14

我正在尝试编写一个通用函数调度机制,在调用实际函数之前我会做一些额外的工作(例如,函数执行的时间).以下代码有效,除了void f(....)我们声明ret 的类型的函数.

#define execute(fn, ...)    exec_helper(#fn, fn, ##__VA_ARGS__)
#define execute0(fn)        exec_helper(#fn, fn)

template <typename TASK, typename... ARGS>
auto exec_helper(const char *fn_name, TASK&& task, ARGS&&... args)
{
      //std::function<std::result_of_t<TASK(ARGS...)> ()> func
      //           = std::bind(std::forward<TASK>(task),
      //                       std::forward<ARGS>(args)...);

#ifdef TIME_FUNC
      auto start = std::chrono::steady_clock::now();
#endif

      auto ret = task(std::forward<ARGS>(args)...);

#ifdef TIME_FUNC
      auto end = std::chrono::steady_clock::now();
      auto diff = end - start;
      auto time = std::chrono::duration<double, std::milli>(diff).count();
      std::cout << "\n" << fn_name << "\t = "
                << std::setprecision(3) << time << " ms\n";
#endif

      return ret;
}
Run Code Online (Sandbox Code Playgroud)

有没有办法使它适用于这些类型的功能?也许使用一些模板技巧?

Naw*_*waz 5

C++的一个有趣特性是你可以这样写:

return f();
Run Code Online (Sandbox Code Playgroud)

即使返回类型fvoid.通过这种方式,您实际上可以避免使用ret变量.

牢记这一点,如何析构函数的作品,你可以用在工作之前,任务和工作后任务的一类 - 分别称它们在构造函数和析构函数,如下图所示:

struct watch
{
     extern watch(char const *fn_name) 
            : _fn_name(fn_name),
              _start(std::chrono::steady_clock::now()) {}

    ~watch()
     {
       auto end = std::chrono::steady_clock::now();
       auto diff = end - _start;
       auto time = std::chrono::duration<double, std::milli>(diff).count();
       std::cout << "\n" << _fn_name << "\t = "
                << std::setprecision(3) << time << " ms\n";
     }

     char const *_fn_name;
     decltype(std::chrono::steady_clock::now()) _start;
};
Run Code Online (Sandbox Code Playgroud)

并将其用作:

template <typename TASK, typename... ARGS>
auto exec_helper(const char *fn_name, TASK&& task, ARGS&&... args)
{
 #ifdef TIME_FUNC
      watch start_watching { fn_name };
 #endif

     return task(std::forward<ARGS>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.


您甚至可以将包装类概括为:

struct invariant_executor //choose a more general name now!
{
   using F = std::function<void()>;

   invariant_executor(F before, F after): _after(std::move(after)) 
   {
       before(); 
   }

   ~invariant_executor()
   {
       _after(); 
   }
   F _after;
};
Run Code Online (Sandbox Code Playgroud)

并将其用作:

template <typename TASK, typename... ARGS>
auto exec_helper(const char *fn_name, TASK&& task, ARGS&&... args)
{
 #ifdef TIME_FUNC
      decltype(std::chrono::steady_clock::now()) start;
      invariant_executor local 
      {
         [&] {  start = std::chrono::steady_clock::now(); },

         [&] {
            auto end = std::chrono::steady_clock::now();
            auto diff = end - start;
            auto time = std::chrono::duration<double, std::milli>(diff).count();
            std::cout << "\n" << fn_name << "\t = "
                << std::setprecision(3) << time << " ms\n";
         }
      };
 #endif

     return task(std::forward<ARGS>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以灵活地在构造函数和析构函数中执行任何代码invariant_executor.