首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++11:将lambda转换为源代码中的函数对象

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

Stack Overflow用户
提问于 2015-02-06 21:10:29
回答 2查看 136关注 0票数 2

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

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

EN

回答 2

Stack Overflow用户

发布于 2015-02-07 01:16:50

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

从理论上讲,这样的工具可能是存在的,但即使它确实存在,首先简单地切换到更新的编译器也会更实用。

让我们考虑以下代码:

代码语言:javascript
运行
复制
template <class F>
auto apply_0(F f) -> decltype(f(0)) {
    auto g = [f] (int x) { return f(x); };
    return g(0);
}

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

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

考虑最小的lambda:

代码语言:javascript
运行
复制
auto f = [] { return 0; };
cout << is_pod<decltype(f)>::value << endl;

当使用g++编译时-此代码将写“0”,使用clang++ -它将写“1”。如果我们将这个lambda转换成函数,那么在gcc和clang中产生的结构都将是POD类型。另一个例子:

代码语言:javascript
运行
复制
int x = 42;
auto f = [x] { return x; };
cout << is_pod<decltype(f)>::value << endl;

g++仍将给予“0”,clang++仍将给予“1”。在转换为结构的过程中,我们需要为函数对象的绑定成员x编写一些初始化器(构造函数或其他函数)-根据实现方式,它可以是POD或非POD,无论是哪种方式-这可能与编译器为lambda创建匿名闭包对象时所做的不同。

C++11标准§5.1.2.3列出了其他可能发生变化的内容:

一个实现可以定义不同于下面描述的闭包类型,前提是这不会改变程序的可观察行为,而不是通过改变:

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

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

票数 2
EN

Stack Overflow用户

发布于 2015-02-07 01:08:33

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

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28366572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档