未实例化模板函数的处理 以下代码在Visual C++ 2013中编译,但不在G++4.82:下编译 template<class T> int MyFunc(T& t) { return static_cast<int>(CCodes::blah); } template<> int MyFunc(float& t) { return 0; } int main() { float f = 10.f; return MyFunc(f); } 模板 int MyFunc(T&T) { 返回静态_cast(CCodes::blah); } 模板 int MyFunc(浮点和t) { 返回0; } int main(){ 浮点数f=10.f; 返回MyFunc(f); } VisualC++似乎忽略了一般的模板函数,因为只使用了专门的代码>代码MyFunc < /代码>。G++仍然解析常规函数,并发现CCodes枚举尚未定义

未实例化模板函数的处理 以下代码在Visual C++ 2013中编译,但不在G++4.82:下编译 template<class T> int MyFunc(T& t) { return static_cast<int>(CCodes::blah); } template<> int MyFunc(float& t) { return 0; } int main() { float f = 10.f; return MyFunc(f); } 模板 int MyFunc(T&T) { 返回静态_cast(CCodes::blah); } 模板 int MyFunc(浮点和t) { 返回0; } int main(){ 浮点数f=10.f; 返回MyFunc(f); } VisualC++似乎忽略了一般的模板函数,因为只使用了专门的代码>代码MyFunc < /代码>。G++仍然解析常规函数,并发现CCodes枚举尚未定义,c++,compiler-bug,template-function,C++,Compiler Bug,Template Function,哪个是对的?还是定义了这个实现?GCC是正确的,除MSVC之外的其他编译器都会做同样的事情 这是一个主要的错误,实际上出现在MSVC未来的路线图上。它属于“遥远的未来”类别。他们将不得不重写模板引擎来修复它 有一种观点认为,对格式错误的模板进行诊断是可选的,因为它实际上是一个没有格式正确的实例化的模板,并且不需要标记这些模板。但是, 该标准要求解析模板,无论实例化如何,都必须诊断解析失败 其他编译器都会进行诊断,因此实际上不这样做会导致MSVC用户生成不可移植的代码。抱怨的确是个好主意,即使这不

哪个是对的?还是定义了这个实现?

GCC是正确的,除MSVC之外的其他编译器都会做同样的事情

这是一个主要的错误,实际上出现在MSVC未来的路线图上。它属于“遥远的未来”类别。他们将不得不重写模板引擎来修复它

有一种观点认为,对格式错误的模板进行诊断是可选的,因为它实际上是一个没有格式正确的实例化的模板,并且不需要标记这些模板。但是,

  • 该标准要求解析模板,无论实例化如何,都必须诊断解析失败
  • 其他编译器都会进行诊断,因此实际上不这样做会导致MSVC用户生成不可移植的代码。抱怨的确是个好主意,即使这不是必须的

  • 不管怎样,格式错误的代码仍然是格式错误的代码。所以我想我的问题可以被改写:这是格式错误的代码吗?或者编译器不允许解析未实例化的模板定义吗?@Tom如果编写
    返回static_cast(CCodes::blah),会发生什么情况?我的坏消息缺少
    返回值
    ,但结果相同。我对问题进行了编辑以反映这一点。嗯,§14.6[temp.res]/p10说“如果名称不依赖于模板参数(如14.6.2所定义),则该名称的声明(或声明集)应在该名称出现在模板定义中的点的范围内”。与一般的“无有效专门化”规则不同,此规则不附带“无需诊断”。@T.C.对。由于C++是上下文敏感的(不上下文无关)语法,因此需要执行名称查找作为解析的一部分。这是我所说的(1)的一部分。实际上情况比这更糟——你可以在一个未实例化的模板函数体中放入几乎所有的垃圾,VC++编译器会忽略它。只要它不包含右括号,也不打乱预处理器,这似乎没什么关系。@Tom是的,这是“解析”的传统含义,这就是我所说的(1)的其余部分。仅仅是行噪声的例子使“可选诊断”的理由更难令人相信,但它有(而且可能仍然有)支持者。我原以为可维护性的影响是显而易见的和可怕的——模板函数可以放在库中,显然,只要没有人使用它,就可以愉快地编译多年。一旦被使用,该库显然已经自行“开发”了一个bug。谁知道编写代码的人是否还在这里工作,或者曾经在这里工作过。