可变函数模板在这里的正确用法是什么?
What's the correct use of variadic function template here?
我碰巧在我的研究项目中计算了各种函数和算法所经过的 运行 时间,因此,我决定定义一个 elapsed_time
函数,它可能采用各种类型的函数和各种数量参数(如果有的话)以及各种 return 类型或 none (void
).
我想将函数传递给此 elapsed_time
函数并使用函数指针,指向已作为参数传递给 elapsed_time
函数的函数,从而计算它经过了 运行 时间。
我不确定我的代码是否接近正确,但我作为编程新手已经尽力了,如下:
MWE:
#include <iostream>
#include <chrono>
template<class return_type, class ... argument_types>
void elapsed_time(return_type func(argument_types ... args)){
return_type (* func_ptr)(argument_types ... args) = & func;
std::chrono::time_point<std::chrono::high_resolution_clock> start_;
std::chrono::time_point<std::chrono::high_resolution_clock> end_;
start_ = std::chrono::high_resolution_clock::now();
/* Put the Function whose elapsed time matter right HERE */
func_ptr(); /// What to pass here?
/* Put the Function whose elapsed time matter right HERE */
end_ = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_time (end_ - start_);
const double seconds(elapsed_time.count());
cout << "\nRuntime: " << seconds << " s\n\n";
}
现在以免考虑我有一个函数要传递给 elapsed_time 函数,如下所示:
vector<Point_CCS_xy> fun(const vector<Point_CCS_xy> point_vec, const Point_CCS_xy inquiry_pnt, const int sz);
其中 Point_CCS_xy
是笛卡尔坐标 (x,y) 的 class,即
struct Point_CCS_xy {
long double x_coordinate;
long double y_coordinate;
};
我的问题:
- 我写的函数对吗?我应该将什么传递给 func_ptr(),正如
elapsed_time
函数主体中所评论的那样?传递 argument_types ... args
会导致错误:'argument_types' does not refer to a value
- 在main()中,如何将
vector<Point_CCS_xy> fun(const vector<Point_CCS_xy> point_vec, const Point_CCS_xy inquiry_pnt, const int sz);
函数传递给elapsed_time
函数?
提前感谢您分享您的想法和评论。
我推荐以下方法
template<typename Func, typename... Args>
void elapsed_time(Func f, Args&&... args)
{
std::chrono::time_point<std::chrono::high_resolution_clock> start_;
std::chrono::time_point<std::chrono::high_resolution_clock> end_;
start_ = std::chrono::high_resolution_clock::now();
std::invoke(f, std::forward<Args>(args)...);
end_ = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_time (end_ - start_);
const double seconds(elapsed_time.count());
cout << "\nRuntime: " << seconds << " s\n\n";
}
在上面,我将整个函数类型设为单个模板参数。这样做的好处是允许您传递任何类型的可调用对象,而不仅仅是函数指针。然后,我使用 std::invoke
来实际调用传入的对象,因为它旨在处理使用提供的参数调用任何可调用对象。
因此,对于您的 fun
函数,您可以将其传递给此版本的 elapsed_time
,例如
elapsed_time(fun, point_vec, inquiry_pnt, sz);
如果您传递的可调用对象恰好是一个重载函数,那么您只需要将该调用包装在一个 lambda 表达式中,例如
elapsed_time([&](){ fun(point_vec, inquiry_pnt, sz); });
我碰巧在我的研究项目中计算了各种函数和算法所经过的 运行 时间,因此,我决定定义一个 elapsed_time
函数,它可能采用各种类型的函数和各种数量参数(如果有的话)以及各种 return 类型或 none (void
).
我想将函数传递给此 elapsed_time
函数并使用函数指针,指向已作为参数传递给 elapsed_time
函数的函数,从而计算它经过了 运行 时间。
我不确定我的代码是否接近正确,但我作为编程新手已经尽力了,如下:
MWE:
#include <iostream>
#include <chrono>
template<class return_type, class ... argument_types>
void elapsed_time(return_type func(argument_types ... args)){
return_type (* func_ptr)(argument_types ... args) = & func;
std::chrono::time_point<std::chrono::high_resolution_clock> start_;
std::chrono::time_point<std::chrono::high_resolution_clock> end_;
start_ = std::chrono::high_resolution_clock::now();
/* Put the Function whose elapsed time matter right HERE */
func_ptr(); /// What to pass here?
/* Put the Function whose elapsed time matter right HERE */
end_ = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_time (end_ - start_);
const double seconds(elapsed_time.count());
cout << "\nRuntime: " << seconds << " s\n\n";
}
现在以免考虑我有一个函数要传递给 elapsed_time 函数,如下所示:
vector<Point_CCS_xy> fun(const vector<Point_CCS_xy> point_vec, const Point_CCS_xy inquiry_pnt, const int sz);
其中 Point_CCS_xy
是笛卡尔坐标 (x,y) 的 class,即
struct Point_CCS_xy {
long double x_coordinate;
long double y_coordinate;
};
我的问题:
- 我写的函数对吗?我应该将什么传递给 func_ptr(),正如
elapsed_time
函数主体中所评论的那样?传递argument_types ... args
会导致错误:'argument_types' does not refer to a value
- 在main()中,如何将
vector<Point_CCS_xy> fun(const vector<Point_CCS_xy> point_vec, const Point_CCS_xy inquiry_pnt, const int sz);
函数传递给elapsed_time
函数?
提前感谢您分享您的想法和评论。
我推荐以下方法
template<typename Func, typename... Args>
void elapsed_time(Func f, Args&&... args)
{
std::chrono::time_point<std::chrono::high_resolution_clock> start_;
std::chrono::time_point<std::chrono::high_resolution_clock> end_;
start_ = std::chrono::high_resolution_clock::now();
std::invoke(f, std::forward<Args>(args)...);
end_ = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_time (end_ - start_);
const double seconds(elapsed_time.count());
cout << "\nRuntime: " << seconds << " s\n\n";
}
在上面,我将整个函数类型设为单个模板参数。这样做的好处是允许您传递任何类型的可调用对象,而不仅仅是函数指针。然后,我使用 std::invoke
来实际调用传入的对象,因为它旨在处理使用提供的参数调用任何可调用对象。
因此,对于您的 fun
函数,您可以将其传递给此版本的 elapsed_time
,例如
elapsed_time(fun, point_vec, inquiry_pnt, sz);
如果您传递的可调用对象恰好是一个重载函数,那么您只需要将该调用包装在一个 lambda 表达式中,例如
elapsed_time([&](){ fun(point_vec, inquiry_pnt, sz); });