未命名的命名空间中符号的模板访问

Fre*_*son 1 c++ templates standards-compliance

我们正在将我们的XL C/C++编译器从V8.0升级到V10.1,并发现一些代码现在给我们一个错误,即使它是在V8.0下编译的.这是一个最小的例子:

test.h:

#include <iostream>
#include <string>

template <class T>
void f()
{
  std::cout << TEST << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

TEST.CPP:

#include <string>
#include "test.h"

namespace
{
  std::string TEST = "test";
}

int main()
{
  f<int>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在V10.1下,我们收到以下错误:

"test.h", line 7.16: 1540-0274 (S) The name lookup for "TEST" did not find a declaration.
"test.cpp", line 6.15: 1540-1303 (I) "std::string TEST" is not visible.
"test.h", line 5.6: 1540-0700 (I) The previous message was produced while processing "f<int>()".
"test.cpp", line 11.3: 1540-0700 (I) The previous message was produced while processing "main()".
Run Code Online (Sandbox Code Playgroud)

我们发现g ++ 3.3.2和4.3.2之间存在类似的差异.我也发现在g ++中,如果我移动#include "test.h"到未命名的命名空间声明之后,编译错误就会消失.

所以这是我的问题:标准对此有何看法?实例化模板时,该实例是否被认为是在声明模板本身的位置声明的,或者在此点上标准不明确?我做了一些看起来虽然是n2461.pdf草案,但并没有真正想出任何确定的东西.

Joh*_*itb 5

这不是有效的C++代码.TEST不依赖于模板参数T,因此必须在解析模板定义的上下文中找到它.但是,在该上下文中没有TEST存在声明,因此存在错误.

该格式错误的模板的诊断消息可以延迟到编译器实例化,但如果编译器良好,它将更早地诊断错误.即使在实例化模板时,也没有为该代码提供任何诊断消息的编译器也不符合要求.它与未命名的命名空间无关.

另外,请注意,即使您将未命名的命名空间放在该模板之上,如果您在多个翻译单元中定义并调用该模板,它也将不是有效的C++程序.这是因为具有相同模板参数的相同模板的不同实例化将引用不同的事物(未命名的命名空间中的字符串将在每次在另一个转换单元中定义时产生不同的对象).这种程序的行为将是不确定的.