【问题标题】:Getting address of a lambda call operator for a lambda that captures获取捕获的 lambda 的 lambda 调用运算符的地址
【发布时间】:2021-04-03 14:51:08
【问题描述】:

是否可以获得具有捕获的 lambda 的 lambda 调用运算符的地址?甚至更多:将这样一个指针分配给一个公共指针,该指针可以指向具有相同捕获和相同调用参数的不同 lambda?严格来说,将一个结果 (class1::*)( ... ) 分配给另一个结果 (class2::*)( ... ) 不应该是直接可行的,但是您可能会做一些肮脏的伎俩并强制转换指针,这是可能的,因为 lambda 类在概念上是可互换的。

那么“正确”的语法是什么?即使是一个肮脏的把戏。

不幸的是,以下代码的最后一行不起作用:

int main()
{
    int i;
    auto l100 = [&]()
    {
        i += 100;
    };
    using l100_t = decltype(l100);
    using l100_fn = void (l100_t::*)();
    l100_fn fn100 = &l100_t::operator ();
}

【问题讨论】:

  • 你的意思不是使用std::function
  • Lambda 是 voldemort 类型。但是在紧要关头可以using mylambda_t = decltype(mylambda);
  • "lambda 类在概念上是可互换的。" 什么是完全不相关的类的“可互换”?
  • "具有相同捕获和相同调用参数的不同 lambda?" 听起来您想要一个派生类,而不是 lambda。不要使用 lambdas 作为一种快速而肮脏的方式来编写类型。
  • 我从 gcc、clang 和 msvc 那里得到的 l100_fn fn100 = &l100_t::operator (); 编译器错误都给出了如何纠正它的重要提示。

标签: c++


【解决方案1】:

它可以指向具有相同捕获和相同调用参数的不同 lambda

如果您有一些界面希望用户提供“捕获”一组特定值并采用一组特定参数的“lambda”,那么它就不再是 lambda。它只是一个函数指针,它被赋予一个const& 指向一个包含“捕获”值作为其参数之一的结构。毕竟,接收代码需要存储“捕获”的值,对吧?所以用户需要提供一个“capture”结构体和一个接受“capture”结构体和其他参数的函数指针。

这就是构建 API 的方式:清晰明确。确保他们捕获正确的参数不是用户的工作。 API 的工作是告诉用户想要的值被“捕获”,并且用户提供与它们交互的函数指针。

是的,用户不会自动将那些“捕获”的值视为可通过名称访问的;他们必须使用参数名称来获取它们。但 API 变得更加连贯且不那么脆弱。

【讨论】:

  • 谢谢,但这不是我想要的。
  • @BonitaMontero:我知道。您所要求的毫无意义,实际上是不可能的,即使可能,对于您正在尝试做的事情来说也是一个糟糕的解决方案。因此,这是一个实际可行的解决方案,可以更好地向用户传达系统的需求,并且不易损坏。
  • 其他人已经用函数-object展示了一个合适的解决方案。如果您不关心创建对象的成本,这几乎每次都适合。调用对象与调用纯函数指针具有几乎相同的性能。我已经有了你告诉自己的想法。但是有额外的参数会使代码更容易编写,有时它可能比使用带有预初始化捕获的 lamda 慢。
  • @BonitaMontero: "Others have shown a proper solution with a function-object." 但是你要求获得一个函数指针,不是std::function,它有一些开销。它也不会阻止用户捕获不同的值,您的问题明确表示这是系统的要求。
  • 当然函数对象有些不同,因为它还包括一个对象指针。但是你所建议的仍然不是我所要求的,因为使用初始化的 captues 调用 lambda-objects 比调用没有任何 caputes 而是参数的类似函数的 lambda 更有效。
猜你喜欢
  • 1970-01-01
  • 2013-11-26
  • 2019-01-26
  • 2018-07-02
  • 2020-03-02
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 2020-09-04
相关资源
最近更新 更多