英文:
function::target(): How does the template type work for lambdas?
问题
-
我想要将一个lambda表达式存储在一个函数对象中,然后检索其底层的函数指针。 出于我不理解的原因,function::target() 是一个模板函数,如果传入的类型不正确,它会返回nullptr(我正在使用C++11)。
-
我应该在模板中使用什么类型来正确检索底层的lambda指针?
-
如果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).
- What type should I use in the template to correctly retrieve the underlying lambda pointer?
- Why does function::target() require a template if function is already templated?
- 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.
Relevant Links
- https://en.cppreference.com/w/cpp/language/lambda
- https://en.cppreference.com/w/cpp/utility/functional/function
- https://en.cppreference.com/w/cpp/utility/functional/function/target
Code Example
void foo(int) { std::cout << "foo" << std::endl; }
int main() {
std::function<void(int)> a(foo); // well-defined global function
std::function<void(int)> b([](int) -> void {}); // temporary lambda expression
auto bar = [](int) -> void {}; // lambda expression stored in variable
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;
}
答案1
得分: 2
一个lambda表达式的结果是一个对象,而不是一个函数。每个lambda表达式都有一个独特但无名的类型。
你可以从 c
中恢复一个对象,因为 bar
有一个名称;c.target<decltype(bar)>()
返回该类型对象的指针(请注意,这不是一个函数指针)。
你不能恢复 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<decltype(bar)>()
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论