C++ Function with variable number and types of arguments as argument of another function

Viewed 743

I would like to create function calling another function and printing its arguments.
It should be compatible with many functions (returning the same result) with many combinations of variables of arguments.

I would like to have something like this:

int fun1(){}
int fun2(int i){}
int fun3(std::string s, int i){}

void execute_and_print(std::function f, ...)
{
///code
}

int main()
{
execute_and_print(&fun1);
execute_and_print(&fun2, 3);
execute_and_print(&fun3,"ff",4);
}

It could print:

executed function with arguments:
executed function with arguments: 3
executed function with arguments: ff, 4

Is it even possible in C++?

3 Answers

In C++17 it is very simple

template <typename F, typename... Args>
void execute_and_print(F f, Args... args)
{
    (std::cout << ... << args);
    f(args...);
}

Prior to that there is extra ceremony

template <typename F, typename... Args>
void execute_and_print(F f, Args... args)
{
    int dummy[] = { (static_cast<void>(std::cout << args), 0)... };
    f(args...);
}

It is not foolproof, but any possible errors will be caught at compile time (ie. the code will not compile). It should work file, as long as the provided parameters match those of the called function, and a matching << operator exists for each parameter.

template<class Fn, class...Args>
void execute_and_print(Fn fn, Args...args) {
    int f[sizeof...(Args)] = { (std::cout << args << ", ", 0)... };
    fn(args...);
}

Refer to https://en.cppreference.com/w/cpp/language/parameter_pack. The sizeof... command is actually the number of elements, not their combined size.

You can use templates to get it done,

template <class... Args>
void RunThrough(Args&& ... args)
{
    ([&](auto& input)
        {
            std::cout << input << ", ";
        } (args), ...);
}

template<class Func, class... Args>
decltype(auto) execute_and_print(Func f, Args&&... args)
{
    f(args...);

    std::cout << "executed function with arguments: ";
    RunThrough(args...);
    std::cout << std::endl;
}

You can use lambdas, std::function objects and function pointers in this.

Reference: https://stackoverflow.com/a/60136761/11228029

Related