为什么C++语言设计者会不断重复使用关键字?

And*_*ner 64 c++ language-design keyword c++11

支持重新使用短关键字(并添加依赖于上下文的含义)而不仅仅是添加更多关键字的主要论点是什么?

是否只是想要避免破坏可能已经使用建议的新关键字的现有代码,还是有更深层次的原因?

C++ 11中新的"枚举类"让我想到了这一点,但这是一个通用的语言设计问题.

Jon*_*ely 68

是否只是想要避免破坏可能已经使用建议的新关键字的现有代码,还是有更深层次的原因?

不,这就是原因.

根据定义,关键字始终被视为关键字,无论它们出现在源中,因此它们不能用于其他目的.使某个关键字成为关键字会破坏可能将该标记用作变量,函数或类型名称的任何代码.

与c委员会采取不同的方法,并添加新的关键字使用_Reserved的名称,例如_Atomic,_Bool,然后他们添加一个新的头(<stdatomic.h>,<stdbool.h>)有一个更好的宏,这样您就可以选择是否包含头获取的名称atomicbool,但它不会自动声明,也不会破坏恰好使用这些名称的代码.

C++委员会不喜欢宏并希望它们成为合适的关键字,因此要么重用现有的关键字(例如auto),要么添加依赖于上下文的"关键字"(它们不是真正的关键字,而是"具有特殊含义的标识符"因此它们可以用于其他事情,例如override)或使用不太可能与用户代码冲突的奇怪拼写(例如decltype代替广泛支持的typeof扩展).

  • 我认为C++委员会不喜欢宏的原因之一就是C语言在C++中不起作用,因为在C++中允许包含任何其他标准头的方式.因此,即使你没有包含`<stddecltype>`或者它所调用的任何东西,你用于另一个目的的`decltype`的现有代码也可能会破坏,因为`<vector>`会拉入宏.由于委员会一般也不太喜欢宏,我怀疑通过限制哪些标准头可以相互包含来定义他们摆脱这种尴尬的方式有任何兴趣. (13认同)
  • 它不是"**只是**你想避免破坏现有的代码".对于C++标准委员会以及数百万用户中的许多用户来说,不打破现有C++行的数十个生产线是非常重要的.请参阅<http://www.stroustrup.com/C++11FAQ.html#specific-aims> (5认同)
  • wrt覆盖和最终[为什么覆盖和最终标识符具有特殊含义而不是保留关键字?](http://stackoverflow.com/q/30404388/1708801)也是相关的.它只是为您已经说过的内容添加了更多细节. (2认同)

Bas*_*tch 17

一些旧的语言中没有关键字可言,特别是PL/1,其中

IF IF=THEN THEN BEGIN;
  /* some more code */
END;
Run Code Online (Sandbox Code Playgroud)

是一段合法的代码,但完全不可读.(另请参阅APL作为编写主要编程语言的示例,几个月后读取完全神秘,即使是代码的原始作者).

C和C++语言系列具有由语言规范定义的一组关键字.但是有非常广泛使用的语言,有数十亿的遗留源代码行.如果您(或他们的标准化委员会)添加一个新关键字,可能会与某些现有程序发生冲突,正如您猜测的那样,其他人回答这一点很糟糕.因此,如果标准添加为例如enum_class新关键字,则可能有人已将其用作标识符,并且该实体将不满意(在采用新的C++标准时必须更改其代码).

另外,众所周知,C++被慢慢解析(特别是因为标准的头文件<vector>正在拉动十几行源代码,并且因为模块还没有在C++中,并且因为语法非常模糊),所以将解析器复杂化为处理新语法并不是什么大问题(解析C++一直都很可怕).例如,GCC社区在新的优化上比在新的C++特性上更加努力(显然,C++标准库的最新特性比解析新语法需要更多的工作),即使从C++ 03跳转到C++ 11是一个巨大的跳跃,需要在C++前端做很多工作.对于C++ 11到C++ 14的跳转,这不太正确.

其他一些语言(如Lisp的一些方言,如Common Lisp的和一些计划,在那里你可以重新定义letif宏,homoiconic这样的语言是非常不同的,因为在操作AST S,从粗文本替换机制用C或C++ ...)允许重新定义现有关键字; 另请阅读有关卫生宏的内容.但这可能会在几个月后难以理解源代码.

  • 对于糟糕的打字员来说,Fortran固定格式的源代码更加有趣.`do 100 i = 1,5`是循环的开始但是`do 100 i = 1. 5`是赋值语句.空白被忽略,所以`do 100 I`是与`do100i`相同的变量. (6认同)
  • PL/1的一个有趣部分.只有你感到非常残忍才能做到.如IF IF =那么那么= ELSE; ELSE ELSE =那么; .欢乐时光. (3认同)

Ste*_*ein 10

我认为这主要是因为添加关键字会破坏在其他环境中使用此关键字的现有代码,正如您所建议的那样.


Mat*_* M. 10

是否只是想要避免破坏可能已经使用建议的新关键字的现有代码,还是有更深层次的原因?

根据定义,关键字是一种特殊的标记,不能在其他任何地方使用; 因此,引入关键字会破坏碰巧使用给定拼写的标识符的任何代码.

有些语言使用术语上下文关键字来指代仅在特定上下文中被解释为关键字的拼写.如果之前在此上下文中不能使用"wild"标识符,则可以保证contextual关键字的引入不会破坏现有代码.例如,由于在函数签名中的右括号之后不会立即出现标识符,因此可以引入所谓的上下文关键字(例如overridefinal).

另一方面,在先前允许任何标识符的位置,添加关键字会带来风险.例如:

  • struct H { my_type f; enum { g }; };:使用enum class而不是新关键字是因为在此上下文中任何新单词都可能被错误地视为数据成员声明的开头; 只有一个关键字是明确的(在LL(1)中),并且引入一个新关键字可能会破坏代码.
  • void h() { my_type f; auto x = g(); }:使用auto而不是新关键字是因为任何新单词都可能与现有类型冲突.这仍然是一个令人惊讶的选择,因为它已经是C中这个位置可用的关键字(默认为int类型)但其含义被改变(理由是其使用的概率很低).

正如一些人所提到的,语言可以完全没有关键字设计(Haskell非常接近),或者以某种方式设计,而不是关键字可以无缝地引入(例如,如果每个声明都是以关键字开头,那么引入新的关键字就不会发生冲突).它恰好比没有这样的C和C++,以及许多类C语言.

  • 对 - 但仅限于C90及更早版本.C99删除了"隐含`int`"规则,使`auto i = 0;`非法.有趣的是,在C99之前的C中,`auto i = 0.0`使`i`成为`int`,而在C++ 11及更高版本中,同样的声明使`i`成为`double`. (2认同)