The short answer is “templates are not string substitution”. void f(void)
has meaning only so far as it is an alias for void f()
in C++, in order to be backwards compatible with C.
The first step is to use variadics, as noted elsewhere.
The second step is figuring out how to map void
returning functions to … well, maybe something like std::function<void()>
, or maybe something else. I say maybe something else because unlike the other cases, you cannot call std::function<void()> foo; foo( []()->void {} );
— it isn’t a true continuation.
Something like this maybe:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
};
then use it like this:
auto someFunc = []()->void {};
Continuation<decltype(someFunc())>::type c;
which gives you the type you want. You could even add in an apply to continuation:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
cont( f(args...) );
}
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
f(args...);
cont();
}
};
which lets you apply a continuation to an execution of a function uniformly if the incoming type is a void or if it is a non-void type.
However, I would ask “why would you want to do this”?