操作员功能的过载解决方案



为什么不编译此代码?我本以为内置的一元运算符&使得两个二进制运算符&应该无关紧要。如果您注释掉其中一个二进制运算符&,代码编译(使用gcc11.2(和内置的一元运算符&被选中。

struct A
{ int operator&(int) const { return 1; }
};
struct B
{ int operator&(int) const { return 2; }
};
struct C : A, B
{};
C* test(C& c)
{ return &c; } //error: request for member 'operator&' is ambiguous

问题是过载解决方案。第一个函数名称应该匹配,如果发现邻接,应该报告错误。之后执行参数的匹配。下面是一个具有正则函数的示例:https://godbolt.org/z/nYfjdn1Td

正如您所看到的,在所有编译器上,即使两个foo都有不同数量的参数,也会报告foo的模糊性。

operator&应该会出现同样的问题,所以这里更像gcc。

过载解决方案是一个复杂的主题。通常你不必去想它。这里有一个很好的来源,它解释了这是多么复杂。

如果你想解决这个问题,并有二进制运算符可用于这样的代码,你可以这样做:

struct C : A, B 
{
using A::operator&;
using B::operator&;
};

这修复了在所有编译器上测试的问题。

当然,instaceOfC & intValue的歧义仍然存在,但您可以通过掺杂一个using语句来解决它。

https://godbolt.org/z/ds3W4GYcT

这是由于不合格的名称查找。

最初,名称查找在类C的范围内开始。未找到operator&的声明。

然后依次查找基类。在AB中的每一个中都有一个名称为operator&的不同声明。

此时,通过名称查找找到的声明集是A::operator&B::operator&。这些在名称查找阶段被认为是不明确的,因此永远不会达到重载分辨率,即一元和二进制operator&之间的差异。

有关更多信息,请参阅cppreference中的示例以获取非限定名称查找。

如果只继承了AB中的一个,那么名称查找集就不会是成员函数名称查找集。它将进行过载解析并正确推导出一元CCD_ 16。

using声明添加到类C的主体中,使它们都进入范围C::以进行名称查找。。

struct C : A, B
{
using A::operator&;
using B::operator&;
};

C的范围是在基类之前搜索的,因此永远不会达到不明确的步骤。

最新更新