【问题标题】:Is it bad that C++0x's lambda expressions don't have a named type?C++0x 的 lambda 表达式没有命名类型是不是很糟糕?
【发布时间】:2010-12-02 10:06:04
【问题描述】:

我最近在互联网上阅读了一些关于 lambda 表达式的内容,在我看来,C++0x 的 lambda 表达式不会有一个(或多个)专门绑定到 lambda 表达式的类型——在其他换句话说,lambda 表达式只会匹配模板参数或auto 参数/变量。正如here 所述,会发生什么

支持 lambda 的编译器将 创建一个唯一的匿名函子类型 对于每个 lambda 表达式

我的问题是,这是一件坏事吗?有一些只匹配 lambda 表达式的关键字是否有意义,例如lambda,其工作原理如下

void f(std::function<int(int)> func)
{
     func(2);
}

template<typename T>
void g(T func)
{
     func(2);
}

void h(lambda func)
{
     func(2);
}

int main()
{
    int fpointer(int);
    struct { int operator()(int var) { return var; } } functor;

    f(fpointer); //ok (actually a linker error, but for the sake of example)
    f(functor); //ok
    f([](int var) { return var; }); //ok

    g(fpointer); //ok
    g(functor); //ok
    g([](int var) { return var; }); //ok

    h(fpointer); //error -- function pointer isn't a lambda expr
    h(functor); //error -- functor isn't a lambda expr
    h([](int var) { return var; }); //ok

    return 0;
}

说实话,我实际上看不到它的用处(尤其是考虑到auto 接受 lambda 表达式,因此可以将 lambda 分配给变量),但它仍然不适合我lambda 表达式是匿名类型,不能专门绑定到一种特定类型(排除所有其他类型)。

本质上,我的问题是,lambda 表达式是匿名的是否可以(无论是在实用性方面——缺乏lambda 类型是否使我们失去了某些功能——而且在哲学上——它真的使感觉 lambda 表达式总是具有“类型”auto)?

【问题讨论】:

  • 听起来你好像不知道你也可以使用std::function&lt;int(int)&gt; 接受 lambda 表达式。
  • 我是,但是由于一般功能与 auto 的工作方式相匹配(afaik),我认为没有必要添加 another 组示例函数/函数调用(但它是还是值得一提,所以谢谢 litb)
  • 我认为对 auto 存在误解。 auto 不能用作函数中的参数类型。它不是一种类型。 auto 只是说“从初始化程序中推断出类型,因为我太懒或无法命名类型”。
  • 在这种情况下,我已经更改了 auto 参数。我仍然相信你可以做到auto = [](int a) { ... }; 但是(......对吗?;))
  • op() 的全部目的是您不必担心函子类型。现在,如果您将某些内容限制为仅 lambdas(我当然认为实现将提供一些 __is_lambda 元函数或您可以与 enable_if 一起使用的东西),那么摆脱接受函数指针等的能力会有什么意义。我不'没有看到任何东西,我相信它没有任何意义。

标签: c++ lambda c++11


【解决方案1】:

Lambda 是独立的类型。代码

void h(lambda func)
{
     func(2);
}

没有任何意义,因为 lambdas 没有运行时多态性。回想一下,lambda 相当于

struct unique_name
{
    return_type operator()(Arg1 a1, Arg2 a2, ... , Argn an)
    {
        code_inside_lambda;
    }
}

这本身就是一种独特的类型。上面的代码和说的一样

void h(class C)
{
     C(2);
}

即使我们保证 C 有operator(),这也是没有意义的。你需要一个模板:

template<typename T>
void g(T func)
{
     func(2);
}

int main()
{
    g([](int x){return x + 2;});
}

【讨论】:

  • 您对拥有void h(class C) 的想法提出了很好的意见,但是我可以 使用void h(functor_name C),它只会匹配特定函子类型的参数。我不能对 lambda 表达式做同样的事情。
  • 如果您需要通过名称引用特定的 lambda,您应该使用 struct 以旧方式定义它。根据定义,lambda 表达式是匿名的。
  • 这是一个很好的观点,如果你需要专门研究 lambda 表达式(即使它不提供任何功能),你可能无论如何都在错误地使用它们(并且会违背 lambda 表达式的理论)。另外,正如我提到的以及其他所有人都提到的那样,它可能没有实用程序(尽管 litb 是正确的,有人会为其添加非标准编译器扩展)。我已经接受了这个答案
【解决方案2】:

我认为没有理由根据函数是否有名称来区分函数类型。 Lambda 函数只是一种简写形式,让您可以轻松定义便利函数。有名或无名,调用时函数的行为是一样的。

这样想。您的软件的早期版本具有定义为匿名函数的谓词。随着时间的推移,需求变得更加复杂,您的谓词也变得更加复杂——也许您需要从多个地方调用它。明智的做法是重构,以便您拥有一个命名函数。

被调用函数(调用谓词的函数)没有理由关心这一点。简单或复杂,命名或匿名 - 它仍然只是一个谓词函数。

一个小问题是闭包问题 - 我还没有检查过,但幸运的是,C++ 将获得带有闭包和 lambda 的嵌套命名函数。

【讨论】:

    猜你喜欢
    • 2010-11-02
    • 2022-07-21
    • 1970-01-01
    • 2010-12-16
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    相关资源
    最近更新 更多