为什么重载运算符不能定义为类的静电成员?

C++语法允许在结构/类中定义重载运算符,如下所示:

struct X
{
   void operator+(X);
}

或在结构/类之外,如:

void operator+(X, X);

但不是作为:

struct X
{
   static void operator+(X, X);
}

有人知道这个决定的原因吗?为什么不允许第三种形式呢?(MSVC给出语法错误。)也许这背后有什么故事?

附注:第一个和第二个定义同时存在会造成歧义:

1>CppTest1.cxx
1>c:allerupmisccf_htmlcpptest1.cxx(39) : error C2593: 'operator +' is ambiguous
1>        c:allerupmisccf_htmlcpptest1.cxx(13): could be 'void B1::operator +(B1 &)'
1>        c:allerupmisccf_htmlcpptest1.cxx(16): or       'void operator +(B1 &,B1 &)'
1>        while trying to match the argument list '(B1, B1)'

我不明白为什么此歧义比介于1、3或2、3之间的更好。


解决方案

我没有关于此概念的任何C++讨论的具体知识,因此请随意忽略此问题。

但对我来说,你把问题倒过来了。问题应该是"为什么允许使用此语法?"

与当前语法相比,它没有提供任何优势。非静电会员函数版本与您建议的静电版本拥有相同的私有会员访问权限。因此,如果您需要访问私有来实现它,只需将其设置为非静电成员,就像您通常对类的大多数成员所做的那样。

它并没有使实现非对称运算符(即:operator+(const X &x, const Y &y))变得更容易。如果您需要私有访问来实现这一点,那么您仍然需要在其中一个类中为它们声明一个友元。

所以我会说它不存在的原因是它不是必需的。在非成员函数和非静电成员之间,涵盖了所有必要的用例。


或者,换一种说法:

免费函数可以做静电函数系统所能做的一切,甚至更多。

通过使用自由函数,可以对模板中使用的运算符进行参数相关的查找。使用静电函数不能做到这一点,因为它们必须是特定类的成员。而且您不能从类外部将添加到类,而可以添加到命名空间。因此,如果您需要将运算符放在特定的名称空间中以使某些ADL代码工作,您可以这样做。使用静电函数运算符无法做到这一点。

因此,免费函数是您提议的静电函数系统将提供的所有功能的超集。由于允许它没有任何好处,因此没有原因允许它,因此不允许它。


哪些选项可以在不实例化函数的情况下使用它们?

这在术语上是自相矛盾的。"函数器"是一个"函数对象"。类型是不是对象;以是它不能是函数器。它可以是这样一种类型,在实例化时将产生一个函数器。但该类型本身不会是函数器。

此外,能够声明Typename::operator()静电并不意味着Typename()可以随心所欲。该语法已具有实际意义:通过调用默认构造函数实例化Typename临时。

最后,即使所有都不是情况,那实际上有什么好处呢?大多数接受某种类型的可调用对象的模板函数在使用函数指针时与使用函数器时效果一样好。为什么要将接口限制为不仅限于函数,而且限制为不能具有内部数据的函数?这意味着您无法通过捕获lambdas等操作。

不可能包含状态的函数器有什么用处?为什么要强制用户传递没有状态的"函数"呢?为什么要阻止用户使用lambdas?

所以您的问题源自一个错误的假设:即使我们有它,它也不会给您您想要的。

相关文章