Home > Enterprise >  What's the correct use of variadic function template here?
What's the correct use of variadic function template here?

Time:03-03

I happen to compute the elapsed running time of various functions and algorithms in my research project, so, I decided to define an elapsed_time function which might take various type of functions with various number of arguments(if any) and also various return types or none (void).

I want to pass a function to this elapsed_time function and make use of a function pointer, pointing to the function that has been passed as an argument of the elapsed_time function, and thus compute its elapsed running time. I am not sure if my code is even close to be correct, but I did my best as a newbie in programming, as follows:

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";
}

and now lest consider I have a function to be passed to elapsed_time function, as follows:

vector<Point_CCS_xy> fun(const vector<Point_CCS_xy> point_vec, const Point_CCS_xy inquiry_pnt, const int sz);

where Point_CCS_xy is a class of cartesian coordinates (x,y), i.e.,

struct Point_CCS_xy {
    long double x_coordinate;
    long double y_coordinate;

};

My questions:

  1. Is the function I have written correct? what should I pass to func_ptr() as commented in the body of the elapsed_time function? Passing argument_types ... args leads to the error: 'argument_types' does not refer to a value
  2. In the main(), how to pass vector<Point_CCS_xy> fun(const vector<Point_CCS_xy> point_vec, const Point_CCS_xy inquiry_pnt, const int sz); function to the elapsed_time function?

In advance, I appreciate that you share your thoughts and comments.

CodePudding user response:

I recommend the following approach

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";
}

In the above I make the entire function type a single template parameter. This has the advantage of allowing you to pass any type of callable object, not just function pointers. I then use std::invoke to actually call the passed in object as it is design to handle invoke any callable with the provided arguments.

So for your fun function, you would pass it to this version of the elapsed_time like

elapsed_time(fun, point_vec, inquiry_pnt, sz);

If the callable you are passing happens to be an overloaded function, then you would just need to wrap that call in a lambda expression like

elapsed_time([&](){ fun(point_vec, inquiry_pnt, sz); });
  • Related