【问题标题】:Given the following, what type is "function"?鉴于以下情况,“函数”是什么类型?
【发布时间】:2015-06-20 07:39:46
【问题描述】:

鉴于以下情况,“函数”是什么类型?

#include <functional>
#include <vector>

template<class T>
class Foo
{
public:

    template<typename P, typename Q, typename R, typename... Args>
    void Attach(P (Q::*f)(Args...), R p)
    {
        auto function = [p, f](Args... args)
        {
            (*p.*f)(args...);
        };

        Listeners.push_back(function);
    }   

private:

    std::vector<std::function<T>> Listeners;
};

class Bar
{
public:

    int Handler(int x, int y, int z)
    {
        return 0;
    }
};

int main(void)
{
    auto foo = Foo<int(int, int, int)>();
    auto bar = Bar();

    foo.Attach(&Bar::Handler, &bar);
}

对于某些上下文,我正在尝试创建一个调用实例上的方法的 lambda,将该 lambda 存储到一个集合中。我的 push_back 编译失败,出现以下错误:

xrefwrap(283): 错误 C2440: 'return' : 无法从 'void' 转换为 'int'

我最初使用 std::bind 来创建一个可以存储的 std::function。显然我可以用 lambda(和可变参数模板,所以我不需要每个 arity 一个模板)来做到这一点,但到目前为止它打败了我。

【问题讨论】:

  • 您的 lambda 没有 return 语句,但您的处理程序返回一个 int。 (并且您使用的函数签名将 int 指定为返回类型。)
  • 你是对的。我把它改成 return (*p.*f)(args...),然后用 void(int,int,int) 测试它仍然有效,所以一切都很好。

标签: c++ lambda std-function


【解决方案1】:

当你构造了Foo,提供的显式模板参数是auto foo = Foo&lt;int(int, int, int)&gt;();

int main(void)
{
    auto foo = Foo<int(int, int, int)>(); //<<<< Here is the template arguments when constructing Foo 
    auto bar = Bar();

    foo.Attach(&Bar::Handler, &bar);
}

当您注册侦听器时,函数签名返回类型为 void

auto function = [p, f](Args... args)
    {
        (*p.*f)(args...);
    };

分辨率

所以要么你

  • 更改 Foo 的显式模板参数 auto foo = Foo&lt;void(int, int, int)&gt;(); 以返回 void 以匹配您的侦听器回调。
  • 或确保您的侦听器函数返回一个整数。 return (*p.*f)(args...);

注意您可能打算从侦听器返回状态代码,但您可能错过了?所以第二个解决点在我看来是一个明显合理的问题

【讨论】:

  • 您能否在答案中补充说,如果将 lambda 更改为 return (*p.*f)(args...); - 也就是说它现在可以编译,即使提供的模板参数是 void(...),它仍然会编译。谢谢。
猜你喜欢
  • 2016-09-25
  • 2015-06-22
  • 1970-01-01
  • 2019-02-07
  • 2019-07-13
  • 2014-12-22
  • 2018-06-01
  • 1970-01-01
  • 2014-06-09
相关资源
最近更新 更多