There is a template for constructing std::function
:
template< class R, class... Args >
class function<R(Args...)>;
I have not figured out how to invoke it. (VC++, if that matters.)
Question: How can I use std::function
with a variadic list without using std::bind
?
#include <functional>
#include <iostream>
using vfunc = std::function<void()>;
using namespace std; // I know, I know.
template<class F, class... Args>
void
run(F&& f, Args&&... args) {
vfunc fn = bind(forward<F>(f), forward<Args>(args)...); //OK
//vfunc fn = vfunc(forward<F>(f), forward<Args>(args)...); // COMPILER ERROR
fn();
}
void foo(int x) {
cout << x << " skidoo\n";
}
int main() {
run(foo, 23);
return 0;
}
There is a template for constructing
std::function
.template< class R, class... Args > class function<R(Args...)>;
That's not what that declaration means. It's not declaring a constructor or a "template for constructing" anything; it's a specialization for the template class std::function
. The specialization is the only definition of std::function; the base template is never defined. I think the point of this has something to do with using a function signature in the template declaration. That is, being able to use the template via function rather than as function.
You want to take a callable object and some number of values and create a new callable object that stores those values, which has an operator()
overload that calls the given function with those values. std::function
does not do that; it has no constructors for doing so.
This is exactly what std::bind
is for. Basically, your code is fine as is: storing the result of bind
within function
is entirely valid.
In that case, you can just wrap the function in a lambda and construct your std::function
from it.
template<class F, class... Args>
void run(F&& f, Args&&... args) {
auto fn = vfunc{
[=]() mutable {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
};
fn(); // fn is of type std::function<void()>
}
I made the lambda mutable so std::forward
will not silently not move.
Note however that the [=]
capture will copy everything. To support move only types, you can use a tuple:
[f = std::forward<F>(f), args = std::tuple{std::forward<Args>(args)...}]() mutable {
std::apply(std::forward<F>(f), std::move(args));
}
In C++20, this becomes easier:
[f = std::forward<F>(f), ...args = std::forward<Args>(args)...]() mutable {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.