可变函数模板在这里的正确用法是什么?

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;

};

我的问题:

  1. 我写的函数对吗?我应该将什么传递给 func_ptr(),正如 elapsed_time 函数主体中所评论的那样?传递 argument_types ... args 会导致错误:'argument_types' does not refer to a value
  2. 在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); });