function::target(): 模板类型如何用于 lambda 表达式?

huangapple go评论71阅读模式
英文:

function::target(): How does the template type work for lambdas?

问题

  1. 我想要将一个lambda表达式存储在一个函数对象中,然后检索其底层的函数指针。 出于我不理解的原因,function::target() 是一个模板函数,如果传入的类型不正确,它会返回nullptr(我正在使用C++11)。

  2. 我应该在模板中使用什么类型来正确检索底层的lambda指针?

  3. 如果lambda函数的类型与全局函数的类型不同,那么为什么两者都可以存储在同一个函数对象中?

我对lambda是如何表达的、导致临时函数并绑定到命名空间的印象比较模糊,因此不清楚这个印象是否正确,以及如何将其应用于模板参数。对于这里发生的C++魔法有任何了解的见解将不胜感激。

相关链接

代码示例

void foo(int) { std::cout << "foo" << std::endl; }

int main() {
    std::function<void(int)> a(foo); // 明确定义的全局函数
    std::function<void(int)> b([](int) -> void {}); // 临时lambda表达式

    auto bar = [](int) -> void {}; // 存储在变量中的lambda表达式
    std::function<void(int)> c(bar);

    std::cout << a.target<void(*)(int)>() << std::endl; // 0x7ffe8e74ecf0
    std::cout << b.target<void(*)(int)>() << std::endl; // 0
    std::cout << c.target<void(*)(int)>() << std::endl; // 0
    std::cout << &bar << std::endl; // 0x7ffe8e74ecef

    return 0;
}
英文:

I want to store a lambda expression in a function object, then retrieve its underlying function pointer. For reasons I do not understand, function::target() is a templated function that returns nullptr if the incorrect type is passed in (I'm working in C++11).

  1. What type should I use in the template to correctly retrieve the underlying lambda pointer?
  2. Why does function::target() require a template if function is already templated?
  3. If the type of a lambda function is different from that of a global function, then why can both be stored into the same function object?

I have a vague understanding of how lambdas are expressions that result in temporary functions that are bound to namespaces and thus have a different type depending on which namespace they reside in. I have no idea if that impression is correct or how to apply it to what I use in the template argument. Any insight into what C++ magic is going on here would be greatly appreciated.

Code Example

void foo(int) { std::cout &lt;&lt; &quot;foo&quot; &lt;&lt; std::endl; }

int main() {
    std::function&lt;void(int)&gt; a(foo); // well-defined global function
    std::function&lt;void(int)&gt; b([](int) -&gt; void {}); // temporary lambda expression

    auto bar = [](int) -&gt; void {}; // lambda expression stored in variable
    std::function&lt;void(int)&gt; c(bar);

    std::cout &lt;&lt; a.target&lt;void(*)(int)&gt;() &lt;&lt; std::endl; // 0x7ffe8e74ecf0
    std::cout &lt;&lt; b.target&lt;void(*)(int)&gt;() &lt;&lt; std::endl; // 0
    std::cout &lt;&lt; c.target&lt;void(*)(int)&gt;() &lt;&lt; std::endl; // 0
    std::cout &lt;&lt; &amp;bar &lt;&lt; std::endl;                     // 0x7ffe8e74ecef

    return 0;
}

答案1

得分: 2

一个lambda表达式的结果是一个对象,而不是一个函数。每个lambda表达式都有一个独特但无名的类型。

你可以从 c 中恢复一个对象,因为 bar 有一个名称;c.target&lt;decltype(bar)&gt;() 返回该类型对象的指针(请注意,这不是一个函数指针)。

你不能恢复 b 中的对象,因为你无法描述它的类型。

英文:

The result of a lambda expression is an object, not a function.
Every lambda expression has a unique but unnamed type.

You can recover an object from c since bar has a name; c.target&lt;decltype(bar)&gt;() returns a pointer to an object of that type (note that it's not a function pointer).

You can't recover the object in b since you can't describe its type.

答案2

得分: 1

"@n.m. 和 @j6t,你们的答案对于我的预期用途是正确的。我想要通过函数将 lambda 表达式传递给长时间存在的集合,这需要使用函数。然而,函数缺少 operator==(),所以我希望使用 .target() 来比较它们的底层指针。

根据 @molbdnilo 的说法,我不知道 lambda 表达式是“对象”,也不知道 std::function 存储 lambda 对象本身,而不是指向其他地方的“静态”对象的指针(或许是一种魔法思维)。因此,我希望使用 target() 来模拟两个存储 lambda 的函数对象之间的 operator==() 是有缺陷的。我认为我可以想出另一种应该有效的策略。谢谢大家。"

英文:

@n.m. and @j6t, your answers are on the right track for my intended use. I want to pass lambda expressions via function into long-lived sets, which necessitates the use of function. However, function lacks an operator==(), so I was hoping to use .target() to compare their underlying pointers.

Per @molbdnilo, I was unaware that lambda expressions were "objects", nor was I aware that std::function stores the lambda object itself, rather than a pointer to a "static" object living elsewhere (magic thinking, I suppose). So my hope of using target() as a makeshift operator==() between two function objects storing lambdas was flawed. I think I can come up with another strategy that should work. Thanks all.

huangapple
  • 本文由 发表于 2023年6月15日 12:37:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76479149.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定