c – GCC 4.6.3 – 模板专业化受优化级别的影响?
在我正在开发的应用程序中,我有一个这样的模板函数:
template<class T> void CIO::writeln(T item) { stringstream ss; ss << item << 'r' << endl; write(ss.str()); } 从多个地方调用此函数,T = const char *和T = std :: string.使用CodeSourcery Lite 2008.03-41(GCC 4.3.2),使用-O3编译器标志编译和链接.但是,由于我更改为CodeSourcery Lite 2012.03-57(GCC 4.6.3),使用-O3进行编译是正常的,但是然后链接失败,未定义引用void CIO :: writeln< std :: string>(std :: string) .使用-O2或更低的一切都可以,链接成功. 我对此进行了深入研究,并在程序集输出中发现了一些奇怪的东西:当使用-O2进行编译时,我可以找到函数的两个特化:一个用于const char *(_ ZN3CIO7writelnIPKcEEvT_),另一个用于std :: string(_ZN3CIO7writelnISsEEvT_),但在使用-O3进行编译时,缺少第二个特化,这解释了链接错误. 这是编译器错误吗?这是一些奇怪的优化变成了邪恶吗? 提前致谢! 编辑:此功能位于源文件中.在Mike Seymour的评论之后,我把它移到标题上,现在一切都很好.我承认我应该早点意识到这一点.然而,根据优化标志,检查或不检查语言规则仍然让我感到害怕. 解决方法
与其他答案所说的不同,这可能不是编译器错误.
-O3启用的优化之一是函数内联.我认为发生的是: 源文件1在没有定义的情况下调用CIO :: writeln.它被编译为目标文件1. 源文件2在其定义可用时调用CIO :: writeln.它被编译为目标文件2. 只有当目标文件2包含CIO :: writeln的定义时,目标文件1才可用.如果源文件2中的调用被内联,则对象文件2将不包含它的定义.如果调用没有内联,则可以使用定义. 注释中给出的解决方案将定义移动到头文件中是正确的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |