C ++ 11:将lambda转换为源中的函数对象

时间:2015-02-06 13:10:29

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

我有一个C ++ 11代码库,我需要在不支持lambdas的旧编译器上构建。将所有lambda手动更改为手工制作的函数对象是不切实际的。

有没有人知道我可以作为预编译步骤运行的工具,它会自动将所有lambda提取到它们的等效函数类中?我想知道我是否可以使用clang的前端。

2 个答案:

答案 0 :(得分:2)

  

有没有人知道我可以作为预编译步骤运行的工具,它会自动将所有lambda提取到它们的等效函数类中?

嗯,理论上可能存在这样的工具,但即使这样做,首先只需切换到更新的编译器也会更实际。

让我们考虑以下代码:

template <class F>
auto apply_0(F f) -> decltype(f(0)) {
    auto g = [f] (int x) { return f(x); };
    return g(0);
}

在这种情况下,我们的工具需要生成函数对象,返回auto类型(这意味着,生成的代码需要使用C ++ 14进行编译)或实例化模板以检测所有可能的返回类型,出现在代码中(此时切换到C ++ 14会更容易)。

但是,让我们考虑一下最乐观的情况:整个项目中的所有lambda表达式都使用->来定义它们的返回类型,并且它们不会出现在模板函数中 - 在这种情况下理论上你可以将lambda表达式转换为等效的struct operator()和构造函数,它将变量捕获为结构成员 - 它会给你代码,行为方式相同吗?答案是:它是实施定义的

考虑即使是最小的lambda:

auto f = [] { return 0; };
cout << is_pod<decltype(f)>::value << endl;

使用g ++编译时 - 此代码将写入'0',使用clang ++ - 它将写入'1'。如果我们将这个lambda转换为函数对象 - 结果struct在gcc和clang中都是POD类型。另一个例子:

int x = 42;
auto f = [x] { return x; };
cout << is_pod<decltype(f)>::value << endl;

g ++仍然会给'0',clang ++仍然会给'1'。在转换为struct期间,我们需要为我们的函数对象的绑定成员x编写一些初始化程序(构造函数或其他) - 取决于实现它可能是POD或非POD,无论哪种方式 - 它可能不同于什么编译器在为lambda创建匿名闭包对象时执行。

其他可能发生变化的事项由C ++ 11标准§5.1.2.3列出:

  

实现可以定义闭包类型与下面描述的不同,前提是这不会改变可观察的行为   除了改变以外的程序:

     
      
  • 封闭类型的大小和/或对齐方式
  •   
  • 封闭类型是否可以轻易复制(第9条),
  •   
  • 闭包类型是标准布局类(第9条)还是
  •   
  • 闭包类型是否为POD类(第9条)。
  •   

与往常一样,您的代码不应该依赖于实现定义的语言部分 - 所以这不是什么大问题,但它可能会导致意想不到的后果。

答案 1 :(得分:-1)

据我所知,还没有建立这样的工具,但如果您尝试实施一个工具,那么您对基础设施的最佳选择将是ClangROSE。< / p>