为什么C++不允许用户定义运算符?

4
我一直在思考这个问题。已经有很多运算符了,而且它们可以被重载,那为什么不彻底做到让它支持自定义运算符呢?我认为这将是一个很好的补充。
我被告知这将使编译语言变得太困难了。这让我想到,C++本来就不是为易于编译而设计的,所以真的不可行吗?当然,如果你使用带有静态表格和语法的LR解析器
E → T + E | T
T → F * T | F
F → id | '(' E ')'

这是无法实现的。据我所知,Prolog通常使用运算符优先级解析器进行解析,可以轻松定义新运算符,但该语言要简单得多。现在,显然可以重写语法以接受标识符,用于替换语法中硬编码的运算符。

还有哪些解决方案和解析器方案?还有哪些因素影响了这个设计决策?


你必须有所取舍。如果你曾经尝试过编写编译器,你会意识到它们并不容易编码。 - hookenz
7个回答

10

http://www2.research.att.com/~bs/bs_faq2.html#overload-operator

虽然我们曾多次考虑过这种可能性,但每次我(或者我们)都决定潜在的问题超过了潜在的好处。

这不是一个语言技术问题。即使在1983年我第一次考虑它时,我就知道它如何实现。然而,我的经验表明,当我们超越最琐碎的例子时,人们似乎对运算符使用的“显而易见”的含义有微妙的不同意见。一个经典的例子是 a**b**c。假设 ** 已被赋予指数的意义。现在,a**b**c 应该意味着 (a**b)**c 还是 a**(b**c)?我认为答案很明显,我的朋友也同意——然后我们发现我们对哪种解决方案是显而易见的并不一致。我的猜测是,这样的问题会导致微妙的错误。


5
添加相关引用。通常在SO上,仅仅发布链接作为答案是被不赞成的做法。这会使读者更难获得概述(如果有5个不同的答案,每个答案只包含一个链接而没有其他内容,那么确定哪些答案是好的、哪些答案是坏的或者无关紧要就需要花费很多精力)。此外,你链接到的页面可能会在未来被删除或者其上的文本发生变化。简而言之,如果你想让人们给予你的答案点赞,那么必须贡献一些东西。即使只是从你链接到的页面中直接引用一段话。 - jalf

2

这将会比现有的编译更加困难。另外,运算符优先级也会带来问题:如何定义它?你需要一种方法告诉编译器一个用户定义的运算符优先级高于另一个运算符。

几乎肯定是可行的,但我认为C++不需要其他方式让自己“开枪打脚”:-)


1

这会使语言变得更加复杂。显然这是不可取的。

不过,你可以看看Boost Spirit。它使用大量的模板元编程技巧,可以实现像你提到的那样的功能。


0

我刚刚发现,实际上可以实现非常类似于重载运算符的东西。考虑以下内容:

Vector v, a, b; v = a /vectorProduct/ b;

原来你可以通过使用由现有运算符分隔的虚拟类来实现自定义运算符的行为。=)

0

实际上,它的设计非常容易解析和编译。C语言有32个定义关键字,所有其他标记都是函数和变量。

C++只多了一些。人们可以很容易地识别哪个标记是哪个,因此当使用+标记或其他标记时,知道要查找什么。


1
易于解析和编译吗?普遍共识是,C++是现存最难编写编译器的编程语言之一(参见例如http://stackoverflow.com/questions/575143/writing-my-own-c-compiler/575155#575155)。 - Martin B
实际上,我简直不敢相信……C++拥有一个运行时类型推断子系统,它本身就非常复杂,模板替换中进行的类型推导并不是微不足道的。此外,从纯解析步骤来看,我认为某些结构相当令人印象深刻(函数指针和typedef是两个我的内心C++解析器有时会遇到限制的东西)。 - Felix Dombek
与自然语言解析相比,编程语言的解析要容易得多 :) ,因为它的设计目的是相对容易地被机器解析。哪些类似的语言更容易解析是另一个问题。从机器的角度来看,汇编语言无疑是最容易的。而且C比C++更容易,因为它没有运算符重载和模板。所以公平起见,我们应该将其与其他面向对象的语言进行比较,与这些语言相比,它相对平等。 - ewanm89
C++与其他面向对象的编程语言不同。请看看Walter Bright所说的(http://port70.net/~nsz/16_c++.html):“它很难解析,因为特定的标记序列可以产生多个完全不同的解析树,这取决于某些符号被声明为什么。更糟糕的是,许多这些符号在解析时并不是已知的,因为它们尚未声明。因此,它必须被解析成一些不确定的状态,稍后会被“修复”。这个问题使得在没有构建大部分C++编译器前端(包括所有困难的东西)的情况下正确地解析C++代码变得不可能。” - Martin B
这甚至会让Java变得更简单...也许这就是为什么Netbeans和Eclipse总是能准确地预测编译器错误,而Visual Studio的行为相当不稳定的原因,有时会在没有错误的情况下发现错误,但大多数情况下只是没有标记语法/类型错误,这些错误将在后来显示为晦涩的编译器错误。 - Felix Dombek

0
允许自定义运算符的问题在于你必须允许程序员指定运算符的语法。我想C++类型系统可能会有所帮助,但它只能帮助解决结合性等问题。
这将使本来就复杂的语言变得更加复杂...

0

这通常是被避免的,因为大多数代码都是由多个人编写的,所以代码应该是“可审查的”,而这几乎不是语言的“期望”特性。

Joel Spolsky有一篇好文章关于这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接