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

时间:2017-09-04 13:36:56

标签: c++ c++11 lambda std-function

我有同样的东西:

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

3 个答案:

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