I've been looking around SO for a while now but cannot find quite the answer that I am looking for - this question is probably the closest to what I am thinking.
In a sentence: is it possible to declare a template function that takes a parameter of an std::function
and deduce template parameters for both the return type and the parameter types of the function? Example:
//this works to pass the std::function in
template<class T>
void doSomething(std::function<T> f) {
f();
}
//this is more what i am looking for - can R and P be deduced automatically - does not work!
template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
f();
}
Is this because the function signature or function type is considered one thing in itself, and as such cannot be "broken" up? I realise there are decltype
and std::result_of
but cannot think how I might use them here.
As an additional point, how might I extend the second example to have multiple parameters and deduction, using variadic templates?
Will work, but it only works if you pass a
std::function
to the function and that function has one non void parameter. This is kind of limiting though. You can useWhich will take any
std::function
and the arguments for it and calls them as if you did it in the call site. This is still limiting though because the call site requires you use astd::function
so you can't pass it anything implicitly convertible to astd::function
.With C++17 and class template argument deduction (CTAD) this is no longer an issue though. We can create an overload that takes any type, and then construct a std::function using CTAD to fill in the types for us. That would look like
And now anything that isn't a
std::function
will go tovoid doSomethingElse(Func&& f, Args&&... args)
, get converted to astd::function
, and get passed tovoid doSomethingElse(std::function<R(Args...)> f, Args&&... args)
so you can use the return type and argument(s) type(s) in there.