C++ 运算符在不同名称空间中时的重载不明确
文件A.hpp:C++ 运算符在不同名称空间中时的重载不明确,c++,namespaces,overloading,ambiguous,C++,Namespaces,Overloading,Ambiguous,文件A.hpp: struct foo { int x; } foo; inline bool operator ==(const foo &lhs, const foo &rhs) { /* ... */ } 文件B.hpp #include "A.hpp" namespace SomeNamespace { bool operator==(const foo &lhs, const foo &rhs) { /* ...
struct foo
{
int x;
} foo;
inline bool operator ==(const foo &lhs, const foo &rhs)
{
/* ... */
}
文件B.hpp
#include "A.hpp"
namespace SomeNamespace
{
bool operator==(const foo &lhs, const foo &rhs)
{
/* ... */
}
/* ... */
void someFunction(const foo &foo_instance1, const foo &foo_instance2)
{
CPPUNIT_ASSERT(foo_instance1 == foo_instance2);
}
}
带有断言的行的编译器错误为:
error: ambiguous overload for 'operator==' ...
因此,问题是编译器同时看到两个比较运算符
A.hpp的全局命名空间中的定义和B.hpp的SomeNamespace中的定义不明确
为什么编译器不使用SomeNamespace中的定义?您已经定义了两次相同的函数;你期望得到什么 发生编译器使用查找
SomeNamespace::operator==
非限定名称查找,并使用ADL执行::operator=
。自从
两者都有完全相同的签名,没有办法
编译器选择其中一个
一般来说,类型的重载运算符应该是
在与类型相同的命名空间中定义,而不在其他地方定义。
(如果重载运算符采用两种不同的类型,则定义
在两个不同的名称空间中,我将操作符放在全局
但是这种情况很少。)您已经定义了两次相同的函数;你期望得到什么 发生编译器使用查找
SomeNamespace::operator==
非限定名称查找,并使用ADL执行::operator=
。自从
两者都有完全相同的签名,没有办法
编译器选择其中一个
一般来说,类型的重载运算符应该是
在与类型相同的命名空间中定义,而不在其他地方定义。
(如果重载运算符采用两种不同的类型,则定义
在两个不同的名称空间中,我将操作符放在全局
在你的程序中,
操作符==
是在全局名称空间和Somenamespace中定义的
因此,当您试图访问运算符==
时,编译器无法解析要调用的函数,因为这两个函数具有相同的签名,并且编译器都可以看到它们
因此,要使用在SomeNamespace中定义的
operator==
,必须使用SomeNamespace::operator==
,对于在全局命名空间中定义的运算符,必须在程序中使用::operator=,operator=
在全局命名空间和SomeNamespace中定义
因此,当您试图访问运算符==
时,编译器无法解析要调用的函数,因为这两个函数具有相同的签名,并且编译器都可以看到它们
因此,要使用在SomeNamespace中定义的operator=
,您必须使用SomeNamespace::operator=
,对于在全局命名空间中定义的运算符,您必须使用::operator=
,,否则它不会发生。。。。?提问时请尝试提供。抱歉,已通过编辑更正。请问foo
在哪里声明?或者它没有发生。而foo_instance1
是。。。。?问问题时请尽量提供一个。抱歉,用edit更正。那么foo
声明在哪里?我不知道ADL也在全局范围内(如果这是你的意思的话?)@JamesKanze你能解释一下区别吗?好的,可以看出ADL是实际的“问题”,因为foo和它的==运算符是在同一个(全局)中定义的命名空间。因此,此定义也被视为“本地”命名空间中的定义。Thx@PetrBudnik区别是什么?@jrok ADL在参数所隐含的名称空间中查找;在本例中,它在全局名称空间中查找,因为这是定义foo
的地方。我不知道ADL也在全局范围中查找(如果这是您的意思的话?)@JamesKanze您能解释一下区别吗?好的,请看一下ADL是实际的“问题”,因为foo及其==运算符是在同一个(全局)名称空间中定义的。因此,此定义也被视为“本地”命名空间中的定义。Thx@PetrBudnik区别是什么?@jrok ADL在参数所隐含的名称空间中查找;在本例中,它在全局名称空间中查找,因为在全局名称空间中定义了foo
?我认为SomeNamespace中的运算符==应该首先被考虑,因为它应该首先被找到。难道编译器不是以自下而上的方式搜索名称(名称空间)并在找到第一个正确的定义时停止吗?这不是自上而下或自底向上。当您编译代码编译器时,两个函数“同时”可见。@shobi您能解释一下区别吗?@Juergen请参考此@PetrBudnik抱歉,我没有得到您。查找规则是什么?我认为SomeNamespace中的运算符==应该首先被考虑,因为它应该首先被找到。难道编译器不是以自下而上的方式搜索名称(名称空间)并在找到第一个正确的定义时停止吗?这不是自上而下或自底向上。当你在编译代码编译器时,两个函数“同时”可见。@shobi你能解释一下区别吗?@Juergen请参考这个@PetrBudnik抱歉,我没有得到你。