我有一个C++11代码库,需要在不支持lambda的旧编译器上构建。手动将所有lambda更改为手工制作的函数对象是不切实际的。
有没有人知道我可以作为预编译步骤运行的工具,它可以自动将所有lambda提取到它们等效的函数类中?我想知道我能不能用一下clang的前端。
发布于 2015-02-07 01:16:50
有没有人知道一个我可以作为预编译步骤运行的工具,它会自动将所有lambda提取到它们等效的函数类中?
从理论上讲,这样的工具可能是存在的,但即使它确实存在,首先简单地切换到更新的编译器也会更实用。
让我们考虑以下代码:
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:
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”。在转换为结构的过程中,我们需要为函数对象的绑定成员x
编写一些初始化器(构造函数或其他函数)-根据实现方式,它可以是POD或非POD,无论是哪种方式-这可能与编译器为lambda创建匿名闭包对象时所做的不同。
C++11标准§5.1.2.3列出了其他可能发生变化的内容:
一个实现可以定义不同于下面描述的闭包类型,前提是这不会改变程序的可观察行为,而不是通过改变:
像往常一样,您的代码不应该依赖于语言的实现定义部分-所以这不是什么大问题,但它可能会导致意想不到的后果。
发布于 2015-02-07 01:08:33
据我所知,目前还没有这样的工具,但如果你想实现一个工具,你最好的基础设施选择是Clang和ROSE。
https://stackoverflow.com/questions/28366572
复制相似问题