【问题标题】:Passing C++ Lambda Functions传递 C++ Lambda 函数
【发布时间】:2011-09-27 18:20:33
【问题描述】:

我一直在到处寻找这个,我似乎无法找到一个直接的答案。一些消息来源说这是不可能的,但这只会对我提出更多问题,我将在下面进一步解释。

所以情况就是这样。假设我有一个自定义容器类,其选择功能如下所示(这只是一个示例):

template <typename T>
class Container {
public:
    // ...

    Container<T> select(bool (*condition)(const T&)) const;

    // ...
};

如您所见,select 函数接受一个指向 condition 函数的指针。这是一个定义应该选择哪些项目的函数。因此,使用它的示例类似于:

bool zero_selector(const int& element) {
    return (element == 0); // Selects all elements that are zero
}

现在,如果我有一个装满 s = { 1, 1, 0, 0, 1, 0, 1, 0 } 的容器,我可以使用以下方法选择其中仅包含零的子集:

t = s.select(&zero_selector); // t = { 0, 0, 0, 0 }

如您所见,这有点笨拙。 Lambda 函数会使这更加优雅,所以我可以使用(我不确定这是否是正确的语法),例如:

t = s.select([&] (int x) -> bool { return (x == 0); });

我的问题是,这可能吗?如果是这样,我的函数原型应该是什么,Container::select() 才能接受 lambda 作为其参数之一?

如果不可能,那么像std::for_each 这样可以使用 lambda 表达式作为其参数之一的东西是如何实现的?任何能清楚解释这一点的资源将不胜感激。我发现的所有内容都只是给出了 lambda 函数的示例并使用 std::function&lt;&gt; 将它们作为参数传递,但没有解释 std::for_each 如何与 lambda 函数一起使用。

我想指出,此代码未按原样编译/测试。它仅用于演示目的。我已经尝试在实际项目中实现相同的原则,但它不起作用。

【问题讨论】:

    标签: c++ lambda


    【解决方案1】:

    无需添加下意识的[&amp;]-capture。你的 lambda 不需要它:

    [] (int x) -> bool { return (x == 0); }
    

    无捕获的 lambda 可以转换为相应的函数指针,所以这应该是开箱即用的。

    也就是说,您可能应该声明选择函数以接受std::function所有 lambdas 都可以转换为,无论是否捕获:

    Container<T> select(std::function<bool(const T&)> predicate) const;
    

    【讨论】:

    • &lt;bool(const T&amp;)&gt; 是什么意思?通过引用获取一个 T 类型的 const 参数并返回 bool 的函数?
    • @Wilson:是的,例如see here.
    【解决方案2】:

    您需要将 lambda 声明为无状态(即,使用空的捕获规范 [](int x)-&gt; bool {...})才能将其转换为函数指针。

    【讨论】:

    • 或使用std::function,或将select 设为模板
    • 我尝试了您的解决方案(在上面通过删除&amp; 发布的确切代码上),但它不起作用。它给了我错误 C2664,因为它无法将 '`anonymous-namespace'::' 转换为 'bool (__cdecl *)(const T &)'。
    • @teedayf,它是 C++11 的新成员。 Visual Studio 2010 还不支持它。您需要将 lambda 声明为 [](const int &amp;x) {...} 以匹配函数指针签名。
    • @MSN,啊,我明白了。是的,我尝试了另一个原型,但也没有用。所以它只是在 VS2010 上还不支持。
    • 不过应该​​在 VS2011 中。他们甚至会处理所有讨厌的 STDCALL 调用约定,因此您可以将无状态 lambda 传递给例如SetWindowsHookEx
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多