假设我有一些具有完全相同的捕获和完全相同的签名的 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,我(很可能)支付额外的运行时成本,这可能是(?) 避免了。
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 之间的公共(public)类型,但 std::common_type
不起作用。
// Nope: does not compile
using LCT = std::common_type_t<decltype(l0), decltype(l1), decltype(l2)>;
基本上,我需要介于原始函数指针和 std::function
之间的东西。 是否存在类似的东西?而且……这样的事情真的可以实现吗?
最佳答案
C++ 标准部分§ 5.1.2 [expr.prim.lambda]:
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non union class type — called the closure type
每个 lambda 都有不同的类型:l0
, l1
和 l2
没有共同的类型。
因此请考虑 std::vector<>
变体类型,例如boost.variant (如果你知道 lambda 类型的集合),或使用 std::function<>
,这在这里似乎也很合适。
示例 boost::variant :
int main () {
int captured = 42;
auto l0 = [&captured](int x){ captured += x; };
auto l1 = [&captured](int x){ captured -= x; };
auto l2 = [&captured](int x){ captured = x + 1; };
std::vector<boost::variant< decltype(l0), decltype(l1), decltype(l2)>> variant;
variant.push_back(l0);
variant.push_back(l1);
variant.push_back(l2);
auto f = boost::get<decltype(l1)>(variant[1]);
int i = 1;
f(i);
std::cout << captured;
}
注意:
正如 Johannes Schaub 所指出的,像这样的 lambda 变体不是默认可构造的,即你不能写:
boost::variant< decltype(l0), decltype(l1), decltype(l2)> v;
而 std::function<>
是默认可构造的..
关于c++ - 具有相同签名和捕获的常见 lambda 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28263207/