Cha*_*ime 6 c++ lambda function
你好,我想创建一个可以执行任何类型函数的函数,在执行结束时指示它所花费的时间。被调用的函数可以有一个或没有返回值,以及 0 个或多个任何类型的参数。
调用函数必须打印如下内容:
Running "myFunction" .....
Done ! (5210ms)
Run Code Online (Sandbox Code Playgroud)
基本上我想创建一个函数,通过在调用前后添加代码来调用作为参数传递的任何类型的函数。
现在我是这样做的。
调用函数:
Running "myFunction" .....
Done ! (5210ms)
Run Code Online (Sandbox Code Playgroud)
主要的
template <typename T>
T callFunctionPrintTime(std::string fnName, std::function<T()> fn) {
std::cout << ">> Running " << fnName << " ... " << std::endl;
auto t1 = std::chrono::high_resolution_clock::now();
//Call to the target function
T retVal = fn();
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
std::cout << "Done ! (" << duration << " ms)" << std::endl;
return retVal;
}
Run Code Online (Sandbox Code Playgroud)
myFunction
这个函数没有关系,它可以是任何东西。
在这里,我们在给定的最大时间或最大循环次数内执行 while 循环,并检索执行的循环次数。
int main()
{
//Store the function to call
std::function<unsigned long()> fn = []() {
return myFunction(15, 10000);
};
//Use of the function we are interested in
auto i = callFunctionPrintTime("myFunction", fn);
//The return value of myFunction can be used in the rest of the program.
std::cout << "i: " << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
你这样做的最佳方法是什么?我对我的代码不满意。
我不确定我是否使用正确的方式通过参数传递任何类型的函数。
此外,通过使用 lambda 表达式来存储我的函数,我无法检索被调用函数的名称。所以我必须通过参数传递它的名字。
我很确定什么是最好的没有单一的答案- 但在我看来这是一个小小的改进,因为它更通用一些。
#include <chrono>
#include <iostream>
#include <string>
#include <type_traits>
// enable it for invocables with any type of arguments
template <class Func, class... Args,
std::enable_if_t<std::is_invocable_v<Func, Args...>, int> = 0>
decltype(auto) callFunctionPrintTime(std::string fnName, Func fn, Args&&... args)
{
std::cout << ">> Running " << fnName << " ... " << std::endl;
auto t1 = std::chrono::high_resolution_clock::now();
//Call to the target function by forwarding the arguments to it
decltype(auto) retVal = fn(std::forward<Args>(args)...);
auto t2 = std::chrono::high_resolution_clock::now();
auto duration =
std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
std::cout << "Done ! (" << duration << " ms)" << std::endl;
return retVal;
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您不打算对不可调用项进行重载(当我想到这一点时,这似乎很明显您不会这样做),您可以使用static_assert
而不是 SFINAE:
template <class Func, class... Args>
decltype(auto) callFunctionPrintTime(std::string fnName, Func fn, Args&&... args)
{
static_assert(std::is_invocable_v<Func, Args...>, "must be invocable");
//...
Run Code Online (Sandbox Code Playgroud)
测试用法:
int& a_func(int i) {
static int rv = 0;
rv += i;
return rv;
}
int main() {
int& ref = callFunctionPrintTime("a_func 1", a_func, 10);
std::cout << ref << '\n'; // prints 10
ref += 20;
callFunctionPrintTime("a_func 2", a_func, 100);
std::cout << ref << '\n'; // prints 130 (10 + 20 + 100)
}
Run Code Online (Sandbox Code Playgroud)
或者一些拨打电话的替代方案myFunction
:
std::function<unsigned long()> fn = []() { return myFunction(15, 100000); };
std::cout << callFunctionPrintTime("myFunction", fn);
Run Code Online (Sandbox Code Playgroud)
std::cout << callFunctionPrintTime("myFunction",
[]() { return myFunction(15, 100000); });
Run Code Online (Sandbox Code Playgroud)
std::cout << callFunctionPrintTime("myFunction", myFunction, 15, 100000);
Run Code Online (Sandbox Code Playgroud)
一些有用的链接:
decltype(auto)
、std::enable_if_t
、std::is_invocable_v
、SFINAE