【问题标题】:how to cache a lambda in c++0x?如何在 c++0x 中缓存 lambda?
【发布时间】:2010-12-29 21:17:20
【问题描述】:

在 C# 中大量使用 lambda 之后,我正在尝试在 C++ 中使用它们。我目前有一个 boost 元组(这是真正简化的版本)。

typedef shared_ptr<Foo> (*StringFooCreator)(std::string, int, bool)
typedef tuple<StringFooCreator> FooTuple

然后我将全局命名空间中的一个函数加载到我的 FooTuple 中。理想情况下,我想用 lambda 替换它。

tuplearray[i] = FooTuple([](string bar, int rc, bool eom) -> {return shared_ptr<Foo>(new Foo(bar, rc, eom));});

我无法弄清楚 lambda 元组的函数签名应该是什么。它显然不是函数指针,但我无法弄清楚 lambda 的签名应该是什么。 lambda 的资源现在都很稀少。我意识到 C++0x 目前正在不断变化,但我很好奇如何让它工作。我也意识到有更简单的方法可以做到这一点,但我只是在玩 C++0x。我使用的是 Intel 11.1 编译器。

【问题讨论】:

    标签: c++ c++11 boost lambda tuples


    【解决方案1】:

    -&gt; 操作符设置 lambda 的返回类型,在没有返回类型的情况下可以省略。此外,如果编译器可以推断出它,则可以省略返回类型。就像 Terry 说的那样,您不能将 lambda 分配给函数指针(GCC 不正确地允许这种转换),但您可以使用 std::function。

    此代码适用于 GCC 和 VC10(从 VC 的包含中删除 tr1/):

    #include <tr1/tuple>
    #include <tr1/functional>
    #include <tr1/memory>
    
    using namespace std;
    using namespace std::tr1;
    
    class Foo{};
    typedef function<shared_ptr<Foo>(string, int, bool)> StringFooCreator;
    typedef tuple<StringFooCreator> FooTuple;
    
    int main() {
        FooTuple f(
            [](string bar, int rc, bool eom) {
                return make_shared<Foo>();
            }
        );
    
        shared_ptr<Foo> pf = get<0>(f)("blah", 3, true);
    }
    

    【讨论】:

    • 不起作用 - lambda 表达式不是函数指针。它(概念上)是一个匿名函子类。
    • 从我读过的东西来看,编译器应该能够弄清楚,如果不能,会告诉我。我会看看它。谢谢。
    • @Terry 嗯,这很奇怪,因为这段代码现在可以在 GCC 上编译和运行。
    • "-> 操作符设置 lambda 的返回类型,在没有返回类型的情况下可以省略" - 当可以推断返回类型时也可以省略; “在您的情况下,您需要将返回类型设置为 shared_ptr” - 他没有,因为他的 lambda 的主体是单个 return 语句,这正是可以推断返回类型的上下文。
    • C++0x 现在已转换为非捕获 lambda 的函数指针,请参阅 FCD 中的 §5.1.2/6
    【解决方案2】:

    您应该能够将 lambda 存储在 std::function 中。在您的示例中,尝试将其存储在

    std::function&lt;std::shared_ptr&lt;Foo&gt;(std::string,int,bool)&gt;

    不要忘记 auto(尽管您无法创建 auto 数组等)。

    【讨论】:

    • 你知道 std::function 的标题吗? Google 没有帮助我...
    • 还有,你说的自动是什么意思?
    • std::function is in auto 是另一个 c++0x 特性
    • 呸,它在一些关于模板实例化的疯狂提升错误上失败了。谢谢
    • 我不了解其他人,但我不得不禁用 Boost 的一些 C++0x 功能(有 #defines 来启用/禁用它们)。
    【解决方案3】:

    来自Visual C++ Blog

    我提到将 lambda 存储在 tr1::函数。但你不应该这样做 除非有必要,否则 tr1::function 有一些开销。如果 你想重用一个 lambda,或者干脆 想给它起个名字,你可以用 自动。

    【讨论】:

    • auto 在这里没有帮助,因为它不能用作像 vector 这样的容器的类型参数。
    • 没错,我只是想提一下开销。
    • 在英特尔编译器上,带函数的 lambda 仍然比缓存函数指针快。我的测试大约快 3-5%。感谢您的提示。
    • @Pavel:您可以使用 auto 命名 lambda,然后对该名称进行 decltype 以获取 lambda 对象的类型。后者可以用作模板类型参数。
    • @sellibitze:此时你不妨定义T same_type&lt;T&gt;(T),然后写成decltype(same_type([]() ... ))。可以说,尽管付出了所有努力,编写一个仿函数更容易:)
    猜你喜欢
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    相关资源
    最近更新 更多