C++ gcc 4.9递归lambda返回时出现内部编译器错误
我有一小段代码,在ClangRepoHead(3.5)中编译得很好,但在GCC4.9RepoHead中编译得不好。虽然这看起来像是一个gcc bug,但在垃圾发布bugzilla之前,我想问你C++ gcc 4.9递归lambda返回时出现内部编译器错误,c++,gcc,c++14,gcc4.9,C++,Gcc,C++14,Gcc4.9,我有一小段代码,在ClangRepoHead(3.5)中编译得很好,但在GCC4.9RepoHead中编译得不好。虽然这看起来像是一个gcc bug,但在垃圾发布bugzilla之前,我想问你 这是有效的c++1y代码(在当前草稿状态下)-仅仅因为clang编译了它,所以它没有理由是正确的代码,并且 如果有人能复制这个错误 使用clang编译和运行的代码段如下: 然而使用 g++-4.9 -o main main.cpp -std=c++1y 给出上述内部编译器错误: 如果没有长转储,它将显
g++-4.9 -o main main.cpp -std=c++1y
给出上述内部编译器错误:
如果没有长转储,它将显示:
g++-4.9-o main.cpp-std=c++1y
main.cpp:在“composer::operator()(Func&&,Funcs&&…):[with auto:2=float;Func=main(int,const char*)::;Funcs={main(int,const char*)::}]的实例化中:
main.cpp:33:88:从此处开始需要
main.cpp:19:41:内部编译器错误:在cp/pt.c:1042处的检索_专门化中
返回f(c(std::forward(fs)…(v));
^
为了完整起见,这里是代码片段(完整的main.cpp)
#包括
#包括
样板
结构作曲家;
样板
结构编写器{
自动运算符()(){
返回[&](自动v){return v;};
}
};
样板
结构编写器{
自动运算符(){
作曲家c;
返回[&](自动v){
返回f(c(std::forward(fs)…(v));
};
}
};
样板
自动合成(函数和…函数){
作曲家c;
返回c(std::forward(fs)…);
}
int main(int argc,char const*argv[]{
浮球v=3.5f;
auto t=compose([](auto v){return v>=3;},[](auto v){return int(v-0.5);})(v);
std::cout您的代码在C++1y中无效,至少在执行时无效
通过引用捕获变量,然后退出定义变量的范围,然后调用使用所述变量的lambda
现在,从未使用c
的状态,但是operator()
调用仍然是UB
类似地,虽然您的引用指向的是超出当前范围的数据,但不能保证捕获的是原始变量,而不是本地引用。实现本地捕获的一种方法是捕获指向本地堆栈帧的指针,并通过编译时静态偏移量从所述堆栈帧访问变量:如前所述如果使用堆栈帧,这样的读取将产生垃圾。(这将把[&]
lambda的大小减少到一个指针,这是一个非常好的优化!在某些机器上,通过指针的偏移量访问数据非常快。)
一般来说,如果您的闭包(或其副本)将超过当前范围,则不要通过引用捕获(尤其是通过全局引用)。在return
语句上通过全局引用捕获应该会产生警告
在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;
}
#包括
自动合成(){
return[](auto&&x){return std::forward(x);};
}
样板
自动合成(F&&F){
返回std::向前(f);
}
样板
自动合成(F1&&F1,F2&&F2){
返回[lhs=std::forward(f1),rhs=std::forward(f2)](自动和x){
返回左侧(右侧(std::forward(x));
};
}
样板
自动合成(F0&&F0,Fs&&Fs){
static_assert(sizeof…(Fs)>1,“其他覆盖应该已经处理了这种情况!出了什么问题?”);
返回撰写(
标准:正向(f0),
谱写(
标准::转发(fs)。。。
)
);
}
int main(){
auto a=compose([](bool b){return!b;},[](double d){return d您的代码在C++1y中无效,至少在执行时无效
通过引用捕获变量,然后退出定义变量的范围,然后调用使用所述变量的lambda
现在,从未使用c
的状态,但是operator()
调用仍然是UB
类似地,虽然您的引用指向的是超出当前范围的数据,但不能保证捕获的是原始变量,而不是本地引用。实现本地捕获的一种方法是捕获指向本地堆栈帧的指针,并通过编译时静态偏移量从所述堆栈帧访问变量:如前所述如果使用堆栈帧,这样的读取将产生垃圾。(这将把[&]
lambda的大小减少到一个指针,这是一个非常好的优化!在某些机器上,通过指针的偏移量访问数据非常快。)
一般来说,如果您的闭包(或其副本)将超过当前范围,则不要通过引用捕获(尤其是通过全局引用)。在return
语句上通过全局引用捕获应该会产生警告
在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;
}
#包括
自动合成(){
return[](auto&&x){return std::forward(x);};
}
样板
自动合成(F&&F){
返回std::向前(f);
}
样板
自动合成(F1&&F1,F2&&F2){
返回[lhs=std::forward(f1),rhs=std::forward(f2)](自动和x){
返回左侧(右侧(std::forward(x));
};
}
样板
自动合成(F0&&F0,Fs&&Fs){
static_assert(sizeof…(Fs)>1,“其他覆盖应该已经处理了这种情况!出了什么问题?”);
返回撰写(
标准:正向(f0),
谱写(
标准::转发(fs)。。。
)
);
}
int main(){
自动a=compose([](bool b){return!b;},[](double d){return d如果有人可以复制这个bug。
你检查了吗?很遗憾,我没有找到与这个问题相关的bug,没有。我可以在gcc版本4.9.0 20131223(实验性)(gcc)
好的,这是一个问题的答案,谢谢。Indep
#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;
}