我的东西与此相同:
auto dummy(std::function<int(int)> ifunc) {
auto vals = std::vector<int>(1000000);
for(auto& v: vals) {
v = ifunc(v);
}
}
假设std::function
不用状态绑定到lambda(可能会绑定到没有状态的lambda),那么提取底层函数指针的正确方法是什么,而不是 std::function
?
这是我的尝试,但是它会崩溃,无论我是否放弃目标。
auto dummy(std::function<int(int)> ifunc) {
auto vals = std::vector<int>(1000000);
auto&& target = *ifunc.target<int(int)>();
for(auto& v: vals) {
v = target(v);
}
}
存在std::function
的原因是提供具有特定签名的函数的抽象。std::function
对象中持有的实际函数(或函数对象)不必具有std::function
对象提供的签名。例如,您的function<int(int)>
对象可以将指针固定为采用double
并返回char
的函数;std::function
对象内的代码负责转换。
target
模板成员函数仅在目标对象具有精确类型时,返回目标对象>的指针。因此,例如,如果目标对象采用double
并返回char
,则调用ifunc.target<char(double)>
将为您提供指向该功能的指针。使用任何其他参数类型调用它都会使您回到零指针。
在此处介绍的代码中,调用为 ifunc.target<int(int)>()
,除非目标对象的精确类型是"函数取int
并返回int
"。
如果您要使用此模板成员函数,则必须在使用返回值的其他任何内容之前检查null指针。
这是使其起作用的一种方法:
#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;
}
请注意,添加的(*)
以获取语法正确(std::function
是存储功能指针,而不是函数),并且我们必须将Lambda明确衰减到功能指针中。
由于您真的不知道lambdas的类型,因此您必须通过代码进行 +
添加CC_20,或者将lambda包装到decay_if_possible
-功能中,然后再将其传递给std::function
。
看来,您似乎想获取更快地调用该功能的目标。让我提出一种解决方案,不需要您的函数仅使用一种类型。
顺便说一句,您需要发送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);
}
}
此版本比用于功能的指针更快。由于代码已模板,因此您发送的功能在此处构成了更大的机会。您可以自己看到最终的组件。
顺便说一句,
(以下可能会绑定到没有状态的lambda)
不完全。您必须首先将lambda明确转换为功能指针,否则内部闭合类型仍然是lambda的类型。