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)
有没有办法使它适用于这些类型的功能?也许使用一些模板技巧?
C++的一个有趣特性是你可以这样写:
return f();
Run Code Online (Sandbox Code Playgroud)
即使返回类型f是void.通过这种方式,您实际上可以避免使用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.