Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#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.

>Solution :

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); });
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading