GCC 4.6.3 - 模板专业化受优化级别的影响?

时间:2013-11-12 11:34:44

标签: c++ gcc

在我正在开发的应用程序中,我有一个像这样的模板函数:

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进行编译是正常的,但随后链接将失败并显示undefined reference to void CIO::writeln<std::string>(std::string)。使用-O2或更低时,一切正常,链接成功。

我对此进行了深入研究,并在程序集输出中发现了一些奇怪的东西:使用-O2编译时,我可以找到函数的两个特化:一个用于const char *(_ZN3CIO7writelnIPKcEEvT_),另一个用于std :: string(_ZN3CIO7writelnISsEEvT_),但在使用-O3进行编译时,缺少第二个特化,这解释了链接错误。

这是编译器错误吗?这个奇怪的优化变成了邪恶吗?

提前致谢!

编辑:此功能位于源文件中。在Mike Seymour的评论之后,我把它移到标题上,现在一切都很好。我承认我应该早点意识到这一点。尽管如此,根据优化标志,仍然会检查是否检查语言规则。

1 个答案:

答案 0 :(得分:1)

与其他答案不同,这可能不是编译器错误。

-O3启用的优化之一是函数内联。我认为发生的事情是:

源文件1在没有定义的情况下调用CIO::writeln。它被编译为目标文件1.

源文件2在定义可用时调用CIO::writeln。它被编译为目标文件2.

目标文件1仅在目标文件2包含CIO::writeln的定义时才可用。如果源文件2中的调用被内联,则对象文件2将不包含它的定义。如果没有内联调用,则可以使用定义。

注释中给出的解决方案将定义移动到头文件中是正确的。