代码如下:
namespace n1
{
template <class T>
void n2();
template <class T>
void n2(T);
}
namespace n2 /* line 12 */
{
class c {};
}
using namespace n1;
namespace n3
{
void foo(n2::c);
}
void n3::foo(n2::c) /* line 24 */
{
}
尝试使用最新版本的Visual C ++进行编译时,出现以下错误:
1>test.cpp(24): error C2872: 'n2': ambiguous symbol
1>test.cpp(12): note: could be 'n2'
1>test.cpp(24): note: or 'n2'
在前面的代码段中,第12行和第24行带有注释。
这里发生了什么?如果我删除foo的定义并在函数参数列表之外声明类型为n2 :: c的变量,则它可以很好地编译,我认为这是因为编译器发现我是在引用该类,而不是在引用任何模板函数。另外,如果我改为删除命名空间n1中两个n2模板函数的第二个定义,那么编译器会给我一条错误消息,但要引用正确的行:第12行和其中n2被定义为函数的行(而不是第24行) )。这是编译器错误吗?
我认为微软在这里是正确的。引用工作中的C ++标准草案$ 7.3.4.6,它说
如果名称查找在两个不同的命名空间中找到名称的声明,并且声明未声明相同的实体且未声明函数,则名称的使用格式不正确。
然后给出一个类似于您的示例,如下所示:
namespace A { class X { }; extern "C" int g(); extern "C++" int h(); } namespace B { void X(int); extern "C" int g(); extern "C++" int h(int); } using namespace A; using namespace B; void f() { X(1); // error: name X found in two namespaces g(); // OK: name g refers to the same entity h(); // OK: overload resolution selects A::h }
虽然,gcc和clang都接受代码。我认为他们在这里错了。
返回引用的段落,并注意“ ...不要声明相同的实体,不要声明函数... ”行。
在您的代码中,名称n2
空间中的名称n1
是函数模板而不是函数。因为,功能模板不是功能。参见$ 8.3.5.15(重点是我的):
非模板功能是不是功能模板专门化的功能。[注意:功能模板不是功能。—尾注]
要解决您的问题,请n2
使用全局命名空间进行限定...像这样
namespace n1
{
template <class T>
void n2();
template <class T>
void n2(T);
}
namespace n2 /* line 12 */
{
class c {};
}
using namespace n1;
namespace n3
{
void foo(::n2::c);
}
void n3::foo(::n2::c) /* line 24 */
{
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句