2013-11-29 95 views
2

我明白问题所在,我只是不确定为什么我没有从gcc获得任何错误输出。gcc 4.7.3使用make_shared与构造函数时出现内部编译器错误

有关其产生问题的线路有:

std::string type,rel,pred; 
std::tie(type, rel, pred) = tuple; 
auto supertype = std::make_shared<Node>(Token(type)); // This 
auto predicate = std::make_shared<Node>(Token(pred)); // and this 

仅供参考,节点构造函数是:

Node (Token & token) 

如果我这样做,我没有得到任何错误:

auto type_token = Token(type); 
auto pred_token = Token(pred); 
auto supertype = std::make_shared<Node>(type_token); 
auto predicate = std::make_shared<Node>(pred_token); 

我的GCC是:

posix gcc version 4.7.3 (Debian 4.7.3-8)

实际的错误是:

> Internal compiler error: Error reporting routines re-entered. Please 
> submit a full bug report, with preprocessed source if appropriate. See 
> <file:///usr/share/doc/gcc-4.7/README.Bugs> for instructions. 

有趣的是,这个目录上面甚至不存在。

在make_shared构造函数中构造一个对象时出现了什么问题?

回答

3

临时对象无法绑定到非const左值引用。因此,您无法将其传递给指定的Node构造函数。编译器应该拒绝:

Node node1(Token(type)); 
Node node2(Token(pred)); 

也是一样的试图让std::make_shared与您的代码在内部执行相同的初始化:

auto supertype = std::make_shared<Node>(Token(type)); 
auto predicate = std::make_shared<Node>(Token(pred)); 

你试图让make_shared到临时对象传递给非const左值构造函数。编译器应该将程序诊断为格式错误,并且无法编译它。这显然与ICE崩溃不一样,它总是表示编译器错误。

解决方法是做你在暗示你“但这样做的工作”的代码 - 通过一个左参考make_shared - 或编写Node右值参考构造函数:

Node(Token&&); 

编辑:我认为,这是GCC bug# 56869,它似乎已在4.6.4和4.7.4中修复,并于2013年11月18日关闭。如果有人阅读,可以在4.7.4中轻松运行此测试用例:

#include <memory> 
#include <string> 

struct Token { 
    Token(std::string lex); 
}; 

struct Node { 
    Node(Token& token); 
}; 

int main() { 
    auto supertype = std::make_shared<Node>(Token{"foo"}); 
    auto predicate = std::make_shared<Node>(Token{"bar"}); 
} 

请将结果发布在评论中。

+0

Ty为答案。出于好奇,这个^^对于临时对象是正确的,但是不是**堆分配对象,例如, std :: make_shared (new Token(foo)),假设构造函数接受一个指针。 http://coliru.stacked-crooked.com/a/f94c856dd5f3800b –

+0

GCC 4.8正确编译这个程序,[喷出大量的错误信息。](http://coliru.stacked-crooked.com/a/777204dbaf03dc45) – Casey

+1

@Alex rvalues对于临时值,函数返回值和左值的'std :: move(...)'的结果是正确的。指针会很好。 – Casey