如何从std ::函数中提取和执行目标



我的东西与此相同:

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的类型。

相关内容

最新更新