Kir*_*lev 40 c++ static-methods operator-overloading
C++语法允许在struct/class中定义重载运算符,如:
struct X
{
void operator+(X);
}
Run Code Online (Sandbox Code Playgroud)
或者在struct/class之外,如:
void operator+(X, X);
Run Code Online (Sandbox Code Playgroud)
但不是
struct X
{
static void operator+(X, X);
}
Run Code Online (Sandbox Code Playgroud)
有没有人知道这个决定的理由?为什么不允许第三种形式?(MSVC给出语法错误).也许这背后有一些故事?
ps同时存在第一个和第二个定义会产生歧义:
1>CppTest1.cxx
1>c:\ballerup\misc\cf_html\cpptest1.cxx(39) : error C2593: 'operator +' is ambiguous
1> c:\ballerup\misc\cf_html\cpptest1.cxx(13): could be 'void B1::operator +(B1 &)'
1> c:\ballerup\misc\cf_html\cpptest1.cxx(16): or 'void operator +(B1 &,B1 &)'
1> while trying to match the argument list '(B1, B1)'
Run Code Online (Sandbox Code Playgroud)
我不明白为什么这种模糊性比1,3或2,3更好.
Nic*_*las 18
我对这个概念的任何C++讨论都没有具体的了解,所以可以随意忽略它.
但对我来说,你有倒退的问题.问题应该是,"为什么允许这种语法?"
它在当前语法上完全没有优势.非静态成员函数版本与建议的静态版本具有相同的私有成员访问权限.因此,如果您需要访问私有来实现它,只需使其成为非静态成员,就像您通常对类的大多数成员一样.
它不会使实现非对称运算符变得更容易(即:)operator+(const X &x, const Y &y).如果您需要私有访问来实现这一点,您仍然需要在其中一个类中为他们提供朋友声明.
所以我会说它不存在的原因是它没有必要.在非成员函数和非静态成员之间,涵盖了所有必要的用例.
或者,换句话说:
自由函数可以执行静态函数系统可以执行的所有操作,等等.
通过使用自由函数,您可以为模板中使用的运算符进行参数依赖查找.你不能用静态函数做到这一点,因为那些必须是特定类的成员.而且你也不可以添加从外部类的一类,而你可以添加到命名空间.因此,如果您需要将操作符放在特定的命名空间中以使某些ADL代码有效,则可以.你不能用静态函数操作符来做到这一点.
因此,自由函数是您提出的静态函数系统将提供的所有内容的超集.由于允许它没有任何好处,因此没有理由允许它,因此不允许它.
哪个可以使用仿函数而无需实例化它们?
这是一个矛盾."仿函数"是"函数对象".类型不是对象 ; 因此,它不能是一个算子.它可以是一种类型,在实例化时,将生成一个仿函数.但这种类型本身不会是一个仿函数.
此外,能够声明Typename::operator()静态并不意味着它Typename()会做你想要的.该语法已经具有实际意义:Typename通过调用默认构造函数来实例化临时.
最后,即使并非如此,实际上会有什么好处呢?大多数采用某种类型的可调用函数的模板函数与函数指针和函子一样工作.你为什么要限制你的界面,不仅仅是仅限于仿函数,还要限制那些不能拥有内部数据的仿函数?这意味着你将无法通过捕获lambda等等.
一个不可能包含国家的仿函数有什么用呢?为什么要强制用户传递没有状态的"仿函数"?为什么要阻止用户使用lambdas?
所以你的问题来自一个错误的假设:即使我们拥有它,它也不会给你你想要的东西.
Mar*_*k B 14
因为没有明显的语法来调用这样的运算符,这意味着我们必须要构成一些东西.考虑以下变量:
X x1;
X x2;
Run Code Online (Sandbox Code Playgroud)
现在,让我们假装我们正在使用普通的成员函数而不是运算符 - 假设我在你的例子中改变operator+了plus.
三个调用中的每一个看起来都像:
x1.plus(x2);
plus(x1, x2);
X::plus(x1, x2);
Run Code Online (Sandbox Code Playgroud)
现在,当使用+编译器如何知道在运行范围内查找运算符时进行操作员调用X?它不能用于普通的静态成员函数,并且操作符没有给出特殊的消除歧义.
现在考虑一下你的程序中是否同时声明了第二个和第三个表单.如果你说x1 + x2编译器要么总是选择自由函数,要么调用不明确.唯一真正的替代方案x1 X::+ x2就是看起来很丑陋.鉴于这一切,我确信标准委员会决定简单地禁止静态成员版本,因为它可以完成的任何事情都可以通过朋友免费功能完成.