C++ 函数对任何其他任意函数计时并返回其结果
我试图编写一个函数,它接受任何其他任意函数作为输入,并对其进行计时,然后返回该函数的结果。我已经做了几个小时了,我想我已经很接近了,但是我仍然不知道如何编译它 这就是我到目前为止所做的:C++ 函数对任何其他任意函数计时并返回其结果,c++,templates,generic-programming,C++,Templates,Generic Programming,我试图编写一个函数,它接受任何其他任意函数作为输入,并对其进行计时,然后返回该函数的结果。我已经做了几个小时了,我想我已经很接近了,但是我仍然不知道如何编译它 这就是我到目前为止所做的: // Some arbitrary function to pass to the timer int DoSomething(int x, double y) { // Does something with x and y return 0; } // Function used to t
// Some arbitrary function to pass to the timer
int DoSomething(int x, double y)
{
// Does something with x and y
return 0;
}
// Function used to time another function and return its result
template <typename T, typename Function, typename... Args>
T GetRuntime(const std::string& name, const Function& function, Args&&... args)
{
std::cout << name << " started..." << std::endl;
auto start = std::chrono::high_resolution_clock::now();
T result = function(std::forward<Args>(args)...);
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << name << " complete - duration: " << duration.count() << " milliseconds." << std::endl;
return result;
}
int main()
{
// Doesn't compile
int output = GetRuntime("DoSomething", DoSomething, 42, 42.42);
}
//要传递给计时器的任意函数
整数剂量测量(整数x,双y)
{
//对x和y做些什么
返回0;
}
//函数用于对另一个函数计时并返回其结果
模板
GetRuntime(常量std::字符串和名称、常量函数和函数、参数和…参数)
{
std::cout这里的问题是,T
在您的函数中是不可推断的。您分配返回的值不参与模板参数推断。要按原样使用它,您需要使用指定返回类型
int output = GetRuntime<int>("DoSomething", DoSomething, 42, 42.42);
^^^ specify T is an int
编译器无法推断T
。这是一个模板参数,但您的参数中没有可以推断它的内容
但是,您可以使用std::invoke_result
获取函数的返回类型:
template <typename Function, typename... Args, typename R = std::invoke_result_t<Function, Args...>>
auto GetRuntime(const std::string& name, const Function& function, Args&&... args) -> R {
// ...
}
template <typename Function, typename... Args>
auto LogRuntime(const std::string& name, const Function& function, Args&&... args)
{
std::cout << name << " starting..." << std::endl;
auto result = GetRuntime(function, std::forward<Args>(args)...);
std::cout << name << " complete - duration: ";
constexpr auto is_void = std::is_same_v<decltype(function(args...)), void>;
if constexpr (is_void) {
std::cout << result.count();
} else {
std::cout << std::get<0>(result).count();
}
std::cout << " milliseconds.\n";
if constexpr (!is_void) {
return std::get<1>(result);
}
}
模板
自动获取运行时(const std::string&name,const Function&Function,Args&…Args)->R{
// ...
}
NathanOliver已经给出了正确的答案。这只是一个关于如何使函数更通用的答案。它也与void
函数一起工作,不做任何日志记录。它返回一个包含传递函数的持续时间和返回值的元组。如果传递的函数返回void
,它只返回s直接表示持续时间(无元组)
(这都是C++17。)
通过创建一个作用域计时器,并将其添加到要调用的函数的顶部,您可以执行稍微不同的操作。构造函数将启动计时器,析构函数将停止计时器并打印持续时间。在函数开始时,您需要编写的唯一代码是ScopedTimer timer()如果函数
返回void
,则
将不起作用。将所有计时器内容移动到帮助器类的构造函数和析构函数中。在GetRuntime
中构造帮助器类,然后返回函数(std::forward(args)…)如果函数
返回void
@SamVarshavchik好的点,则
也会起作用。如果这是他们想要的,我会让OP来实现。我想我能处理。总的来说,这是一个很好的答案。我尝试了一下,现在就编译。将其标记为已接受。@tjwrona1992听起来不错,谢谢。如果需要帮助,mak要使其更通用,只需问一个后续问题。似乎即使在建议更改为使用帮助器类后,它仍然无法处理void函数。我进行了更改,并尝试传入void函数,但得到了“致命错误C1001:编译器中发生了内部错误”…感谢Microsoft提供了完全无用的错误消息!为什么这里的R
是一个模板参数,而不是在尾部返回类型中直接使用std::invoke_result\u t
?@KonradRudolph只是因为OP似乎想使用名称而不是auto
,SFINAE@GuillaumeRacicot那只是因为我不知道我不知道我在做什么哈哈哈
// Need these includes in addition to what you already include.
#include <tuple>
#include <type_traits>
template <typename Function, typename... Args>
auto GetRuntime(const Function& function, Args&&... args)
{
auto start = std::chrono::high_resolution_clock::now();
if constexpr (std::is_same_v<decltype(function(args...)), void>) {
function(std::forward<Args>(args)...);
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start);
} else {
auto&& func_result{function(std::forward<Args>(args)...)};
return std::make_tuple(
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start),
std::forward<decltype(function(args...))>(func_result));
}
}
auto duration = GetRunTime(void_func, arg1, arg2);
cout << "Took " << duration.count() << "ms.\n";
auto [duration, int_val] = GetRunTime(int_func, arg1, arg2);
cout << "Took " << duration.count() << "ms and returned " << int_val << '\n';
template <typename Function, typename... Args>
auto LogRuntime(const std::string& name, const Function& function, Args&&... args)
{
std::cout << name << " starting..." << std::endl;
auto result = GetRuntime(function, std::forward<Args>(args)...);
std::cout << name << " complete - duration: ";
constexpr auto is_void = std::is_same_v<decltype(function(args...)), void>;
if constexpr (is_void) {
std::cout << result.count();
} else {
std::cout << std::get<0>(result).count();
}
std::cout << " milliseconds.\n";
if constexpr (!is_void) {
return std::get<1>(result);
}
}