Caller function with optional argument of varying type

Viewed 45

I am trying to write a caller function that can take an optional argument of varying template type.

#include <iostream>
#include <string>

void f_int(int x){std::cout << "f_int\n";}
void f_double(double x){std::cout << "f_double\n";}
void f_void(void){std::cout << "f_void\n";}

template<typename T>
void caller(void (*fun)(T), T arg)
{
    (*fun)(arg); 
}


int main()
{
  caller(f_int, 3);
  caller(f_double, 2.1);
  caller(f_void);         // compilation error
  caller(f_void, void);   // compilation error
  void* p;
  caller(f_void, *p);     // compilation error
}

When writing this code, I was hoping that T could be of type void. Can it be? If yes, why does the above code not work? Is void a valid type or is only void* a valid type?

1 Answers

You could do most of it with a variadic template and perfect forwarding:

template<typename F, class... Args>
void caller(F func, Args&&... args) {
    func(std::forward<Args>(args)...);
}

//...

caller(f_int, 3);
caller(f_double, 2.1);
caller(f_void);

You may also return the value from the called function in the function template by using auto, even when called function is declared void:

int f_int(int x) {
    return x*2;
}
double f_double(double x) {
    return x*1.5;
}
void f_void(void) {
    std::cout << "f_void\n";
}

template<typename F, class... Args>
auto caller(F func, Args&&... args) {          // note the "auto"
    return func(std::forward<Args>(args)...);  // and return
}

//...

auto rv1 = caller(f_int, 3);
auto rv2 = caller(f_double, 2.1);
caller(f_void);                                // you can't assign void though
Related