c++functionvariadic-templates

How could I implement a function wrapper that supports both void and other types of return value?


I implemented something like this:

   template<typename F, typename... Args>
    static auto run_func(F&& f, const string& msg, Args&&... args) -> decltype(f(args...)) {
        using T = decltype(f(args...));
        cout << msg << endl;
        auto timer = Timer(); // something that can record time


        auto res = std::invoke(f, args...); // here is the position of failure 
        cout << "\t- time used: " << timer.time_duration() << endl;

        return res;
    }

This works as what I want it to work only if f is not void f(...):

    int func1(a, b) {return a + b;} 
    void func2(a, b, c) {cout << a + b + c << endl;} 
    
    cout << run_func(func1, 1, 2); // this works
    run_func(func2, 2, 3, 4); // this fails

Do you know how could I make this run_func work in all manners?


Solution

  • You can reutrn the result of calling the function from a function template even when it turns out to be void. Hence, you can modify Timer to print the results in its destructor and refactor your code to this:

    #include <iostream>
    #include <string>
    #include <functional>
    
    using std::string;
    using std::cout;
    using std::endl;
    
    template<typename F, typename... Args>
    static auto run_func(F&& f, const string& msg, Args&&... args) -> decltype(f(args...)) {
          using T = decltype(f(args...));
          cout << msg << endl;
          auto t = Timer(); 
          return std::invoke(f, args...);
    }
    
    void foo() {}
    
    int main() {
        run_func(foo,"msg");
    }