【问题标题】:Issue in passing argument to std::function for vector of functions将参数传递给 std::function 以获取函数向量的问题
【发布时间】:2015-11-25 03:45:51
【问题描述】:

我正在尝试创建一个 std::function 向量,然后将该向量传递给一个函数。我还需要将参数传递给函数对象,所以我使用的是 std::bind。代码如下:

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

using namespace std;

void execute(vector<function<void (int)>>& fs) {
    for (auto& f : fs) 
        f();
}

void func(int k) {
    cout << "In func " << k << endl;
}

int main()
{
    int i = 1;
    vector<function<void (int)>> x;
    auto f1 = bind(func, i);
    //f1(); // this does call intended function
    x.push_back(f1);

    execute(x);
}

但这会产生以下错误:

function_tmpl.cpp:在函数‘void execute(std::vector >&)’中: function_tmpl.cpp:14:5: 错误: 不匹配调用‘(std::function) ()’ F(); ^ 在 function_tmpl.cpp:1:0 包含的文件中: /usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include/c++/functional:2142:11:注意:候选人是: 类函数 ^ /usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include/c++/functional:2434:5: 注意:_Res std::function::operator()(_ArgTypes ...) const [with _Res =空白; _ArgTypes = {int}] 功能:: ^ /usr/lib/gcc/x86_64-pc-cygwin/4.9.2/include/c++/functional:2434:5:注意:候选人需要 1 个参数,提供 0

如果我在 main() 中调用 f(),则可以正常工作,这意味着该函数已与参数绑定,但是当作为参数传递给另一个函数时它不起作用

【问题讨论】:

  • function&lt;void (int)&gt; 只接受带有int 的函数。调用f() 缺少int。将其更改为 function&lt;void()&gt; 或使用 f(0)
  • @nwp,std::bind 不会将参数绑定到函数对象吗?
  • 可以,但function&lt;void (int)&gt; 仍然需要int。将int 绑定到函数后,绑定的函数不再需要int,因此它现在具有签名function&lt;void()&gt;
  • @nwp 那么在这种情况下如何传递参数?将其更改为function&lt;void()&gt; 不允许传递有界函数,f(0) 将无法达到目的?
  • int 绑定到函数时传递参数。如果您不知道绑定时函数应该具有的参数,则不应该绑定它,请返回function&lt;void(int)&gt;,并将参数的vector&lt;int&gt; 传递给execute,然后执行fs[i](arguments[i]) 之类的操作。

标签: c++11 vector arguments std-function stdbind


【解决方案1】:

您正在使用带有单个 int 参数的 void 函数向量:vector&lt;function&lt;void (int)&gt;&gt;,但实际上您正在推送 void(void) 函数。您需要做的就是将向量的元素类型更改为vector&lt;function&lt;void (void)&gt;&gt;。 Bind 的工作原理大致如下:

给定:

void f1(int i) { printf("%d", i); }

bind(f1, 1) 返回一个新函数f2

void f2() 
{
    f1(1);
}

并且由于您正在推送f2,因此向量应该存储void(void) 函数。

【讨论】:

  • @perreal 我不是在推动void(void) 函数。该函数绑定到 int 参数:auto f1 = bind(func, i);
  • 正确,但向量的元素类型不正确,因为您正在推送不带参数的绑定函数。所以你推送的函数的类型与原始函数不同。
  • @perreal 可能是我遗漏了一些东西,但是绑定的函数,即 func,需要一个参数吗?
  • @perreal +1 用于编辑中的绑定说明。这带来了清晰。好消息是我能够将仿函数和 lambda 函数也推送到同一个向量中。
【解决方案2】:

绑定后,函数的类型变成了void()。所以把vector的类型改成vector&lt;function&lt;void ()&gt;&gt;就行了。

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

using namespace std;

void execute(vector<function<void ()>>& fs) {
    for (auto& f : fs) 
        f();
}

void func(int k) {
    cout << "In func " << k << endl;
}

int main()
{
    int i = 1;
    vector<function<void ()>> x;
    auto f1 = bind(func, i);
    x.push_back(f1);

    execute(x);
}

结果:

In func 1

LIVE

【讨论】:

    【解决方案3】:

    std::bind 的返回类型未指定。因此,您不能指望std::bind 返回与std::function&lt;void(int)&gt; 相同类型的变量。使用decltype 和模板来解析。

    Here is an example

    #include <functional>
    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    template <typename T>
    void execute(vector<T>& fs) {
        for (auto& f : fs) 
            f();
    }
    
    void func(int k) {
        cout << "In func " << k << endl;
    }
    
    int main()
    {
        int i = 1;
        auto f1 = bind(func, i);
        vector<decltype(f1)> x; //deduce type of f1
        x.push_back(f1);
        execute(x);
    }
    

    【讨论】:

    • Q1 这解决了传递参数的一个问题。但是,我只是不想在向量中推送普通函数,我也想推送仿函数和 lambda 函数。所以我不能使用 decltype 来获取类型。如何解决这个问题?
    • 查看@songyuanyao 的回答,了解如何使用模板实现这一目标。示例:coliru.stacked-crooked.com/a/df682223032a9ec9
    • 或者你想写“没有”模板?
    • 是的,没有模板。
    【解决方案4】:

    f 是类型 函数& 因此编译器希望您提供一个参数,如下所示: f(1)

    【讨论】:

    • @ZunTzu,std::bind 不会将参数绑定到函数对象吗?
    • f1 是这样,但 f 不是这样,它被静态定义为带一个参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多