具有相同签名和捕获的常见lambda类型

Vit*_*meo 3 c++ lambda types c++11 c++14

假设我有一些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; };
Run Code Online (Sandbox Code Playgroud)

现在,假设我需要将这些lambdas存储在一个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)`
Run Code Online (Sandbox Code Playgroud)

我想要找到所有lambda之间的共同类型,但std::common_type不起作用.

// Nope: does not compile
using LCT = std::common_type_t<decltype(l0), decltype(l1), decltype(l2)>;
Run Code Online (Sandbox Code Playgroud)

基本上,我需要原始函数指针和之间的东西std::function.这样的事情存在吗?并且......可以实际实现这样的东西吗?

qua*_*dev 5

C++标准部分§5.1.2[expr.prim.lambda]:

lambda表达式的类型(也是闭包对象的类型)是一个唯一的,未命名的非联合类类型 - 称为闭包类型

每个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;
}
Run Code Online (Sandbox Code Playgroud)

演示

注意:

正如Johannes Schaub所指出的,像这样的lambda变体不是默认的可构造的,即你不能写:

boost::variant< decltype(l0), decltype(l1), decltype(l2)> v;
Run Code Online (Sandbox Code Playgroud)

std::function<>默认是可构造的......