【发布时间】:2015-02-01 13:29:00
【问题描述】:
假设我有一些具有完全相同的捕获和完全相同的签名的 lambda。
int captured;
auto l0 = [&captured](int x){ captured += x; };
auto l1 = [&captured](int x){ captured -= x; };
auto l2 = [&captured](int x){ captured = x + 1; };
现在,假设我需要将这些 lambda 存储在 std::vector 中,以便在运行时调用它们。
我不能使用原始函数指针,因为捕获的变量会强制 lambda 成为仿函数,而不是常规函数。
我可以使用std::function,但这有点矫枉过正,因为我确定所有的 lambda 表达式都具有相同的签名和相同的捕获。由于 std::function 支持具有相同签名但捕获不同的 lambda,我(很可能)支付了额外的运行时成本,可能是 (?) em> 避免。
std::vector<decltype(l0)> v0; // Ok
v0.emplace_back(l0); // Ok
v1.emplace_back(l1); // Nope: `decltype(l0) != decltype(l1)`
v2.emplace_back(l2); // Nope: `decltype(l0) != decltype(l2)`
我想找出所有 lambda 之间的共同类型,但 std::common_type 不起作用。
// Nope: does not compile
using LCT = std::common_type_t<decltype(l0), decltype(l1), decltype(l2)>;
基本上,我需要一个介于原始函数指针和std::function 之间的东西。这样的东西存在吗?而且……这样的事情真的可以实现吗?
【问题讨论】:
-
每个 lambda 都有一个与其他任何东西无关的唯一类类型。即使是写两次的同一个 lambda 表达式也有不同的类型。如果可能的 lambda 类型的数量是有限的,请考虑使用标记联合。
-
“很可能” 听起来不像您通过测量发现
std::function对于您的用例而言太慢了... -
@T.C.:我明白你的意思。但本能地在我看来
l0、l1和l2确实具有相同的内存布局(尽管标准可能无法保证)。困扰我的是,如果我对具有相同内存布局的 lambda 表达式是正确的,那么就没有办法(除非使用极其不安全的reinterpret_cast或使用std::function支付额外费用)将它们组合在一起。 -
@VittorioRomeo 通过完全相同的捕获,您是指在
[]之间声明的捕获列表的相同形式,还是您想要的所有 lambda存储在该向量中将捕获完全相同的变量,具有完全相同的值,因此每个闭包对象实际上将存储相同的数据值,并为每个闭包对象存储这些值对象是多余的? -
为什么不转向无捕获 lambda,然后通过引用 lambda 显式传入
captured?然后你有一个指向简单的双参数函数的指针向量。
标签: c++ c++11 types lambda c++14