2

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

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

4

2 回答 2

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 表达式转换为具有operator()和构造函数的等效结构,它将变量捕获为结构成员 - 它会给你代码,行为方式相同吗?答案是:它是实现定义的

考虑最小可能的 lambda:

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

当使用 g++ 编译时 - 此代码将写入“0”,使用 clang++ - 它会写入“1”。如果我们将此 lambda 转换为函数对象 - 生成的结构在 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 条)。

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

于 2015-02-06T17:16:50.413 回答
-1

据我所知,目前还没有这样的工具,但如果你要尝试实现一个,你最好的基础设施选择是ClangROSE

于 2015-02-06T17:08:32.607 回答