gpt4 book ai didi

c++ - gcc 4.9 递归 lambda 返回时的内部编译器错误

转载 作者:行者123 更新时间:2023-11-30 01:54:50 35 4
gpt4 key购买 nike

我有一小段代码可以在 clang repo head (3.5) 中正常编译,但不能在 gcc 4.9 repo head 中编译。虽然这看起来像一个 gcc 错误,但在向 bugzilla 发送垃圾邮件之前我想问你是否

  1. 这是有效的 c++1y 代码(处于当前草案状态)- 仅仅因为 clang 编译它并不能证明它是正确的代码,并且
  2. 如果有人可以重现这个错误。

使用clang编译运行的代码片段在这里:

http://coliru.stacked-crooked.com/a/acc691b9a407d6f2

但是使用

g++-4.9 -o main main.cpp -std=c++1y

给我前面提到的内部编译器错误:http://pastebin.com/3fqV7xzC

如果没有长转储,它会显示:

g++-4.9 -o main main.cpp -std=c++1y main.cpp: In instantiation of ‘composer::operator()(Func&&, Funcs&& ...):: [with auto:2 = float; Func = main(int, const char*)::; Funcs = {main(int, const char*)::}]’: main.cpp:33:88: required from here

main.cpp:19:41: internal compiler error: in retrieve_specialization, at cp/pt.c:1042
return f(c(std::forward<Funcs>(fs)...)(v));
^

为了完整起见,这里是片段(完整的 main.cpp)

#include <iostream>
#include <utility>

template <typename... Funcs>
struct composer;

template <>
struct composer<> {
auto operator()() {
return [&] (auto v) { return v; };
}
};

template <typename Func, typename... Funcs>
struct composer<Func, Funcs...> {
auto operator()(Func&& f, Funcs&&... fs) {
composer<Funcs...> c;
return [&] (auto v) {
return f(c(std::forward<Funcs>(fs)...)(v));
};
}
};

template <typename... Funcs>
auto compose(Funcs&&... fs) {
composer<Funcs...> c;
return c(std::forward<Funcs>(fs)...);
}


int main (int argc, char const* argv[]) {
float v = 3.5f;
auto t = compose([] (auto v) { return v >= 3; }, [] (auto v) { return int(v-0.5); })(v);
std::cout << std::boolalpha << t << "\n";
auto f = compose([] (auto v) { return v > 3; }, [] (auto v) { return int(v-0.5); })(v);
std::cout << std::boolalpha << f << "\n";
}

编辑:奖励!我根本不喜欢那个代码——如果有人有更好、可能更快的方法来做这件事,请考虑启发我……

编辑 2 有谁知道如何让 coliru(或类似服务)使用 g++ 4.9?

最佳答案

您的代码不是有效的 C++1y,至少在执行时不是。

您通过引用捕获变量,然后退出定义它们的范围,然后调用使用所述变量的 lambda。

现在,c 的状态从未被使用,但 operator() 调用仍然是 UB。

同样,虽然您的引用是对超出当前范围的数据的引用,但不能保证捕获的是原始变量而不是本地引用。实现本地捕获的一种方法是捕获指向本地堆栈帧的指针,并通过编译时来自所述堆栈帧的静态偏移量访问变量:当您退出堆栈帧时,这种读取会产生垃圾。 (这会将 [&] lambda 的大小减小到单个指针,这是一个非常好的优化!在某些机器上,通过指针的偏移量访问数据很快。)

一般而言,如果您的闭包(或其拷贝)将超过当前范围,则不要通过引用捕获(尤其是通过全局引用)。 return 语句中的 capture-by-global-reference 确实会生成警告。

修复该 UB,您的代码看起来有效。在 C++1y 中,您可以通过 move 或 -forward 进行捕获。

没有 C++1y 编译器,下面是一个尝试:

#include <iostream>
auto compose() {
return [](auto&& x) { return std::forward<decltype(x)>(x); };
}

template<typename F>
auto compose( F&& f ) {
return std::forward<F>(f);
}

template<typename F1, typename F2>
auto compose( F1&& f1, F2&& f2 ) {
return [lhs = std::forward<F1>(f1), rhs = std::forward<F2>(f2)]( auto&& x ) {
return lhs( rhs( std::forward<decltype(x)>(x) ) );
};
}

template<typename F0, typename... Fs>
auto compose( F0&& f0, Fs&&... fs ) {
static_assert( sizeof...(Fs) > 1, "other overrides should have handled this case! What went wrong?" );
return compose(
std::forward<F0>(f0),
compose(
std::forward<Fs>(fs)...
)
);
}

int main() {
auto a = compose( [](bool b){return !b;}, [](double d){ return d<3.0; } );
std::cout << a(2.0) << "," << a(3.0) << "\n";
return 0;
}

这也恰好是非 lambda 无类型的。

关于c++ - gcc 4.9 递归 lambda 返回时的内部编译器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21512780/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com