【问题标题】:How do I create a lambda function to match a boost::function parameter without using C++0x?如何在不使用 C++0x 的情况下创建 lambda 函数以匹配 boost::function 参数?
【发布时间】:2011-07-08 13:07:29
【问题描述】:

如何使用 boost 或 stl 创建一个 lambda 函数,以匹配 Fmain 的第三个 sn-p 代码中预期的 boost::function 参数?

#include <iostream>
#include <boost/function.hpp>

void F(int a, boost::function<bool(int)> f) {
    std::cout << "a = " << a << " f(a) = " << f(a) << std::endl;
}

bool G(int x) {
    return x == 0;
}

int main(int arg, char** argv) {
    // C++0x
    F(123, [](int i) { return i==0; } );

    // Using seperate function
    F(0, &G);

    // How can I do it in place without C++0x
    F(123, /* create a lambda here to match */);
}

我不能使用 C++0x,并且想避免创建几个单独的函数。如果有帮助,我可以使用 boost::function 以外的其他东西,我的首要任务是简洁地创建 lambda。

【问题讨论】:

  • 我现在想知道......为什么你不能使用 C++0x 但你想使用 std::function 这是 C++0x 的一部分?顺便说一句,看看 boost lambda 库,因为它可能是您正在寻找的。​​span>
  • @David: boost::function 不是 std::function

标签: c++ boost stl


【解决方案1】:
#include <functional>    // STL
#include <boost/lambda/lambda.hpp>   // Boost.Lambda
#include <boost/spirit/include/phoenix_core.hpp>     // Boost.Pheonix
#include <boost/spirit/include/phoenix_operator.hpp> // Boost.Pheonix also

...

// Use STL bind without lambdas
F(0, std::bind2nd(std::equal_to<int>(), 0));
F(123, std::bind2nd(std::equal_to<int>(), 0));

// Use Boost.Lambda (boost::lambda::_1 is the variable)
F(0, boost::lambda::_1 == 0);
F(123, boost::lambda::_1 == 0);

// Use Boost.Phoenix
F(0, boost::phoenix::arg_names::arg1 == 0);
F(123, boost::phoenix::arg_names::arg1 == 0);

您可能需要添加一些using namespace 以简化代码。

Boost.Lambda 严格用于定义具有类 C++ 语法的内联函子,而 Boost.Phoenix 是一种建立在 C++ 之上的函数式编程语言,滥用 (☺) 其语法和编译时计算能力。 Boost.Phoenix 比 Boost.Lambda 强大得多,但前者也需要更多时间来编译。

【讨论】:

  • 此外,从 Boost 1.47 开始,Boost.Lambda 已正式弃用,取而代之的是 Boost.Phoenix v3。即,Boost.Lambda 现在是一个遗留库,不打算在新代码中使用。
【解决方案2】:

简短回答:不。

C++0x lambda 的发明正是为了满足您的需求。它们实际上只不过是在下面的匿名/内联示例中制作Increment 的一种方式。这是在任何标准 C++ 中获取匿名函数的唯一方法。

struct Increment {
    int & arg;
    Increment (int a) : arg (a) {}
    void operator () (int & i)
        {arg += i;}
};

void foo (const std :: vector <int> & buffer, int x)
{
    std :: for_each (
        buffer .begin (), buffer .end (),
        Increment (x)); // C++98

    std :: for_each (
        buffer .begin (), buffer .end (),
        [&x] (int & i) {x += i;}); // C++0x
}

关于 lambda 的唯一神奇之处在于它们的类型无法拼写,但编译器可以将内部隐藏类型绑定到 std::function(在某些情况下甚至是 C 函数指针)。

我发布上述代码是因为我认为您的问题可能并不意味着您认为它的作用。 Lambdas 绝对是 C++0x 的东西,但在这个例子中,Increment 是一个 闭包。 (有人会说它只有在你返回它并且绑定变量转义它被绑定的上下文时才成为一个闭包——这是挑剔的,但它就是,比如说,Javascript 所做的)。

您的问题是关于 lambda 还是闭包?

【讨论】:

  • 为什么这被否决了?代码是可靠的。编辑:除了Increment 构造函数应该采用int&amp; 而不是int
  • @Mike :可能是因为 C++03 有多个 lambda 库。 (我没有投反对票。)
  • 我认为我们只是不同意“lambda”的含义。由于作者的聪明而艰巨的工作,C++03“lambda 库”可能看起来像 lambda,但它们不是 lambda。我不禁觉得有点辛苦:-(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 2023-03-09
  • 2019-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多