简体   繁体   English

如何使用variadic模板使用std :: function

[英]How to use std::function using variadic template

There is a template for constructing std::function : 有一个用于构造std::function模板:

template< class R, class... Args >
class function<R(Args...)>;

I have not figured out how to invoke it. 我还没弄明白如何调用它。 (VC++, if that matters.) (VC ++,如果重要的话。)

Question: How can I use std::function with a variadic list without using std::bind ? 问题:如何在不使用std::bind情况下将std::bind std::function与variadic列表一起使用?

#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 . 有一个用于构造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 . 它是模板类std::function The specialization is the only definition of std::function; 专门化是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. 您希望获取可调用对象和一些值,并创建一个新的可调用对象来存储这些值,这些值具有一个operator()重载,该重载使用这些值调用给定函数。 std::function does not do that; std::function不这样做; it has no constructors for doing so. 它没有这样做的构造函数。

This is exactly what std::bind is for. 正是 std::bind的用途。 Basically, your code is fine as is: storing the result of bind within function is entirely valid. 基本上,你的代码很好:在function存储bind的结果是完全有效的。

In that case, you can just wrap the function in a lambda and construct your std::function from it. 在这种情况下,您可以将函数包装在lambda中并从中构造std::function

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. 我让lambda变得可变,所以std::forward不会默默地不动。

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: 在C ++ 20中,这变得更容易:

[f = std::forward<F>(f), ...args = std::forward<Args>(args)...]() mutable {
    std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM