未命名命名空间中符号的模板访问
我们正在将 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;
}
test.cpp:
#include <string>
#include "test.h"
namespace
{
std::string TEST = "test";
}
int main()
{
f<int>();
return 0;
}
在 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()".
我们发现 g++ 3.3.2 和 4.3.2 之间存在类似差异。我还发现在 g++ 中,如果我将 #include "test.h"
移到未命名的命名空间声明之后,编译错误就会消失。
所以这是我的问题:标准对此有何规定?当模板被实例化时,该实例是否被认为是在声明模板本身的地方声明的,或者标准在这一点上不是很清楚?我仔细查看了 n2461.pdf 草案,但并没有真正得出任何明确的结论。
We are upgrading our XL C/C++ compiler from V8.0 to V10.1 and found some code that is now giving us an error, even though it compiled under V8.0. Here's a minimal example:
test.h:
#include <iostream>
#include <string>
template <class T>
void f()
{
std::cout << TEST << std::endl;
}
test.cpp:
#include <string>
#include "test.h"
namespace
{
std::string TEST = "test";
}
int main()
{
f<int>();
return 0;
}
Under V10.1, we get the following error:
"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()".
We found a similar difference between g++ 3.3.2 and 4.3.2. I also found in g++, if I move the #include "test.h"
to be after the unnamed namespace declaration, the compile error goes away.
So here's my question: what does the Standard say about this? When a template is instantiated, is that instance considered to be declared at the point where the template itself was declared, or is the standard not that clear on this point? I did some looking though the n2461.pdf draft, but didn't really come up with anything definitive.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此测试未通过 Comeau 在线编译器,该编译器在过去已被证明是最标准的之一 -周围兼容的编译器。那么,我倾向于认为代码编写时是不正确的,尽管我无法向您指出标准中的一行来说明原因。但请注意,在宽松模式下编译代码会成功。
This test fails the Comeau online compiler which in the past has shown to be one of the most standards-compliant compilers around. I would lean in favor, then, that the code is incorrect as written, though I could not point you to a line in the standard as to why. Note that compiling the code in relaxed mode succeeds, however.
这不是有效的 C++ 代码。
TEST
不依赖于模板参数T
,因此在解析时必须在模板定义的上下文中找到它。但是,在该上下文中不存在TEST
声明,因此存在错误。该格式错误的模板的诊断消息可能会延迟到编译器实例化为止,但如果编译器良好,它会更早地诊断错误。即使模板被实例化,编译器也不给出该代码的任何诊断消息,这是不合格的。它与未命名的名称空间无关。
另外,请注意,即使您将未命名的命名空间放在该模板之上,如果您在多个翻译单元中定义并调用该模板,它也不会是有效的 C++ 程序。这是因为具有相同模板参数的同一模板的不同实例将引用不同的事物(未命名命名空间中的字符串每次在另一个翻译单元中定义时都会生成不同的对象)。这样的程序的行为是未定义的。
This is not valid C++ code.
TEST
is not dependent on the template parameterT
, so it must be found in the context of the template definition when it's parsed. However, in that context no declaration ofTEST
exists, and so there is an error.The diagnostic message for that ill-formed template can be delayed until instantiation by the compiler, but if the compiler is good, it will diagnose the error earlier. Compilers that don't give any diagnostic message for that code even when the template is instantiated are not conforming. It has nothing to do with unnamed namespaces.
In addition, notice that even if you put the unnamed namespace above that template, it will not be a valid C++ program either if you define and call that template in multiple translation units. This is because different instantiations of the same template with the same template arguments will refer to different things (the string in the unnamed namespace will produce a different object each time it's defined in another translation unit). Behavior for such a program would be undefined.