我有同样的东西:
auto dummy(std::function<int(int)> ifunc) {
auto vals = std::vector<int>(1000000);
for(auto& v: vals) {
v = ifunc(v);
}
}
假设std::function
没有绑定到具有状态的lambda(通过它可能绑定到没有状态的lambda),提取底层函数指针并将其替换为{{}的正确方法是什么? 1}}?
这是我的尝试,但如果我取消引用目标,它就会崩溃。
std::function
答案 0 :(得分:4)
std::function
存在的原因是提供具有特定签名的函数的抽象。 std::function
对象中保存的实际函数(或函数对象)不必具有std::function
对象提供的签名。例如,您的function<int(int)>
对象可以包含指向double
并返回char
的函数的指针; std::function
对象中的代码负责转换。
target
模板成员函数返回指向目标对象的指针,仅当目标对象的模板参数指定的确切类型为{{ 1}}。因此,例如,如果目标对象采用target
并返回double
,则调用char
将返回指向该函数的指针。使用任何其他参数类型调用它将返回一个空指针。
在此处提供的代码中,调用是ifunc.target<char(double)>
,除非目标对象的确切类型是“函数取ifunc.target<int(int)>()
,否则将返回空指针返回int
“。
如果您要使用此模板成员函数,必须检查空指针,然后再对返回的值执行任何操作。
答案 1 :(得分:3)
这是一种让它发挥作用的方法:
// while not (equals 0 or -1)
while (!( cell.Value.Equals("0") || cell.Value.Equals("-1")))
注意添加#include <iostream>
#include <functional>
#include <vector>
#include <cassert>
auto dummy(std::function<int(int)> ifunc) {
auto vals = std::vector<int>(10);
auto&& target = *ifunc.target<int(*)(int)>(); //added the missing (*)
assert(target);
for(auto& v: vals) {
v = target(v);
}
}
int main() {
dummy(+[](int x) {return x+1;}); //explicitly decay to function pointer
return 0;
}
以使语法正确((*)
存储函数指针,而不是函数),并且我们必须将lambda显式地衰减为函数指针。
由于你无法真正了解lambda的类型,你必须通过代码并在可能的情况下添加std::function
或将lambda包装到+
- 函数中,然后再传递给它decay_if_possible
。
答案 2 :(得分:2)
似乎你想要更快地调用函数的目标。让我提出一个解决方案,不要求你的functoin只能用一种类型来调用。
顺便说一句,您需要在target
中发送确切类型的事实使您的函数只能使用该类型进行有效调用。此时,您不应该隐藏它并将该类型作为函数的参数。让我解释一下:
// If ifunc don't contain a int(*)(int), runtime error!
auto&& target = ifunc.target<int(*)(int)>();
如果发送任何其他类型(例如lambdas),您的代码将编译,但会产生运行时错误。
通过使用该类型的参数,它确实使您的代码只能使用该类型调用,但是当尝试使用其他类型调用它时,会导致编译时错误:
auto dummy(int(*ifunc)(int)) { // safer!
auto vals = std::vector<int>(1000000);
for(auto& v: vals) {
v = ifunc(v);
}
}
但是,如果您需要速度和,您需要使用任何闭包类型调用您的函数?这里有一种语言功能:模板!
template<typename F>
auto dummy(F function) { // safer, faster than function pointer, and scalable
auto vals = std::vector<int>(1000000);
for(auto& v: vals) {
v = function(v);
}
}
这个版本比指向函数的速度更快。由于代码是模板化的,因此您发送的函数有更大的内联机会。您可以看到resulting assembly for yourself。
顺便说一下,
(通过它可能绑定到没有状态的lambda)
不完全。您必须首先将lambda显式转换为函数指针,否则内部闭包类型仍将是lambda的类型。