C++ 保留一份将来要做的工作清单

C++ 保留一份将来要做的工作清单,c++,c++11,C++,C++11,由于函数指针需要提前知道提供了哪些参数,我不知道如何做到这一点 基本上我想要一份工作清单。每个条目都是一个要使用特定参数调用的函数。也就是说,我想在工作列表中添加foo(3,“abcd”),然后再添加bar(&h)。也就是说,我事先不知道会添加什么类型的函数 稍后我将迭代这个列表并执行指定的函数调用 这可以实现吗?您正在寻找的,或者是lambdas,或者 std::function是任意可调用函数的包装器。您可以在其中存储任何可以使用适当参数调用operator()的内容 可以存储在其中的一件事

由于函数指针需要提前知道提供了哪些参数,我不知道如何做到这一点

基本上我想要一份工作清单。每个条目都是一个要使用特定参数调用的函数。也就是说,我想在工作列表中添加
foo(3,“abcd”)
,然后再添加
bar(&h)
。也就是说,我事先不知道会添加什么类型的函数

稍后我将迭代这个列表并执行指定的函数调用

这可以实现吗?

您正在寻找的,或者是lambdas,或者

std::function
是任意可调用函数的包装器。您可以在其中存储任何可以使用适当参数调用
operator()
的内容

可以存储在其中的一件事是lambda:将调用和参数封装到非参数lambda中并调用它

您可以存储的另一个内容是
std::bind
的结果
std::bind实际上是一个元函数:它接受函数f和参数作为输入,并返回一个函数对象,其调用导致对参数调用f

以下是您如何将此应用于您的案例。常见设置:

std::vector<std::function<void()>> workList;

fillWorkList(workList);

for (auto& f : workList)
  f();
还有一个是lambdas:

void fillWorkList(std::vector<std::function<void()>>& workList)
{
  workList.push_back([]() { foo(3, "abcd"); });
  workList.push_back([]() { bar(&h); });
}
void fillWorkList(标准::向量和工作列表)
{
workList.push_back([](){foo(3,“abcd”);});
workList.push_back([](){bar(&h);});
}
这里有一个解决方案,允许使用
add(foo,3,“abcd”)

#include <functional>
#include <string>
#include <iostream>
#include <vector>
#include <utility>

void foo(int val, std::string text) { std::cout << val << '\t' << text << '\n'; }
void bar(int* ptr) { std::cout << *ptr << '\n'; }

class Worklist {
public:
    template <typename ...Args>
    void add(Args&&... args) {
        worklist.push_back(std::bind(std::forward<Args>(args)...));
    }

    void do_all()
    {
        for(auto& i : worklist) {
            i();
        }
    }

    std::vector<std::function<void(void)>> worklist;
};

int main()
{
    int h{9};
    Worklist worklist;
    worklist.add(foo, 3, "abcd");
    worklist.add(bar,&h);
    worklist.do_all();
}
#包括
#包括
#包括
#包括
#包括
void foo(int val,std::string text){std::coutA
std::function
表示可以调用的内容,但不返回任何内容

最清晰的东西是一只羔羊

std::function<void()> f = []{ foo(3, "abcd"); };
这会将
h
复制到lambda中,然后使用指向
h
的指针调用
bar
。有时您希望
h
是可变的:

std::function<void()> g = [h]()mutable{ bar(&h); };

然后
std::function f=custom{“abcd”};
是另一种表示您将使用
3调用
foo
,std::string(“abcd”)
调用
f()
的方式,当您在
f
上使用
std::bind
std::function>时,可以编写一个将lambda作为任务的类

这里,使用
std::unique_ptr
存储每个lambda:

#include <string>
#include <iostream>
#include <vector>
#include <memory>
#include <utility>

void foo(int val, std::string text) { std::cout << val << '\t' << text << '\n'; }
void bar(int* ptr) { std::cout << *ptr << '\n'; }

class Generic_Callable {
public:
    ~Generic_Callable() = default;
    virtual void call() = 0;
};

template <typename T>
class MyCallable : public Generic_Callable {
public:
    MyCallable(T &&t) : ptr{std::make_unique<T>(std::move(t))} {}

    void call() override
    {
        (*ptr)();
    }

    std::unique_ptr<T> ptr;
};

class Worklist {
public:
    template <typename T>
    void add(T &&t)
    {
        worklist.push_back(std::make_unique<MyCallable<T>>(std::move(t)));
    }

    void do_all() {
        for(auto& i : worklist)
            i->call();
    }

    std::vector<std::unique_ptr<Generic_Callable>> worklist;
};


int main()
{
    int h{9};
    Worklist worklist;
    worklist.add([]() {foo(3, "abcd"); });
    worklist.add([&h]() {bar(&h); });
    worklist.do_all();
}
#包括
#包括
#包括
#包括
#包括

void foo(int val,std::string text){std::cout如何指定foo(3,“abcd”)或bar(&h)作为函数的参数?即具有任意参数的任意函数。@JensJensen编译器将假定您正在传递返回值。即,它将对表达式求值。您需要使用绑定或将其包装在lambda中,以便将可调用对象作为参数传递。@JensJensen这就是答案所显示的。从m
std::bind
,或将其包装在lambda中。您能澄清您不理解的内容吗?lambda是否必须捕获
h
?因此,您能调用函数add_work(foo,3,'abcd')并将参数指定为std::bind binding吗?
std::function<void()> g = [h]()mutable{ bar(&h); };
struct custom {
  std::string s;
  void operator()() const {
    foo( 3, s );
  }
};
#include <string>
#include <iostream>
#include <vector>
#include <memory>
#include <utility>

void foo(int val, std::string text) { std::cout << val << '\t' << text << '\n'; }
void bar(int* ptr) { std::cout << *ptr << '\n'; }

class Generic_Callable {
public:
    ~Generic_Callable() = default;
    virtual void call() = 0;
};

template <typename T>
class MyCallable : public Generic_Callable {
public:
    MyCallable(T &&t) : ptr{std::make_unique<T>(std::move(t))} {}

    void call() override
    {
        (*ptr)();
    }

    std::unique_ptr<T> ptr;
};

class Worklist {
public:
    template <typename T>
    void add(T &&t)
    {
        worklist.push_back(std::make_unique<MyCallable<T>>(std::move(t)));
    }

    void do_all() {
        for(auto& i : worklist)
            i->call();
    }

    std::vector<std::unique_ptr<Generic_Callable>> worklist;
};


int main()
{
    int h{9};
    Worklist worklist;
    worklist.add([]() {foo(3, "abcd"); });
    worklist.add([&h]() {bar(&h); });
    worklist.do_all();
}