为什么没有为 C++14 位分隔符选择 space 字符?

Why was the space character not chosen for C++14 digit separators?

从 C++14 开始,感谢 n3781(它本身并没有回答这个问题)我们可以编写如下代码:

const int x = 1'234; // one thousand two hundred and thirty four

目标是改进这样的代码:

const int y = 100000000;

并使其更具可读性。

下划线 (_) 字符在 C++11 中已经被用户定义的字面值所占用,逗号 (,) 存在本地化问题——许多欧洲国家莫名其妙 使用它作为小数点分隔符——并与逗号运算符冲突,尽管我确实想知道现实世界中的代码可能会被允许例如1,234,567.

无论如何,更好的解决方案似乎是 space 字符:

const int z = 1 000 000;

预处理器可以将这些相邻的数字文字标记连接起来,就像字符串文字一样:

const char x[5] = "a" "bc" "d";

取而代之的是撇号 ('),我所知道的任何书写系统都没有将其用作数字分隔符。

为什么选择撇号而不是简单的 space?


令人困惑,因为所有这些语言在文本中都保留逗号的概念 "breaking apart"句点对 "terminate" 句子起作用——至少对我来说,这非常类似于逗号 "breaking apart" 数字的整数部分和句点 "terminating" 它为小数输入做好准备。

之前有一篇论文,n3499,它告诉我们虽然 Bjarne 自己建议使用空格作为分隔符:

While this approach is consistent with one common typeographic style, it suffers from some compatibility problems.

  • It does not match the syntax for a pp-number, and would minimally require extending that syntax.
  • More importantly, there would be some syntactic ambiguity when a hexadecimal digit in the range [a-f] follows a space. The preprocessor would not know whether to perform symbol substitution starting after the space.
  • It would likely make editing tools that grab "words" less reliable.

我想下面的例子是主要的问题:

const int x = 0x123 a;

虽然在我看来这个理由相当薄弱。我仍然想不出一个现实世界的例子来打破它。

"editing tools" 的理由更糟糕,因为 1'234 基本上破坏了人类已知的所有语法荧光笔(例如,Markdown 在上述问题中使用的语法荧光笔!)并制作了所述荧光笔的更新版本更难实施。

不过,无论好坏,这都是导致采用撇号的基本原理。

我认为这是因为,在编写代码时,如果您到达 "line"(屏幕宽度)的末尾,则会发生自动换行(或 "word wrap")。这会导致你的 int 被分成两半,一半在第一行,另一半在第二行......这样在 word-wrap.[= 的情况下它们都会保持在一起11=]

来自wiki,我们有一个很好的例子:

auto floating_point_literal = 0.000'015'3;

在这里,我们有 . 运算符,然后如果要遇到另一个运算符,我的眼睛会等待可见的东西,比如逗号或其他东西,而不是白色 space。

所以撇号在这里比白色space好得多。

白色space会是

auto floating_point_literal = 0.000 015 3;

感觉不像带撇号的情况那么正确。


本着的相同精神,我认为撇号比space Lightness Races in Orbit 提出的更清楚。

type a = 1'000'000'000'000'000'544'445'555;
type a = 1 000 000 000 000 000 544 445 555;

Space 用于许多事情,例如 OP 提到的字符串连接,与撇号不同,在这种情况下,撇号对于用于分隔数字的人来说很清楚。

当代码行变多时,我认为这会提高可读性,但我怀疑这是他们选择它的原因。


关于 spaces,可能值得看一下这个 C question,它说:

该语言不允许 int i = 10 000;(整数文字是一个标记,中间的 whitespace 将其拆分为两个标记),但表达初始化器通常几乎不会产生任何开销作为文字计算的表达式:

int i = 10 * 1000; /* ten thousand */

这是真的,我认为没有实际意义:

if (a == 1 1 1 1 1) ...

所以数字可能会被合并而没有真正的歧义 但是十六进制数呢?

0 x 1 a B 2 3

这样做无法消除打字错误的歧义(通常我们应该看到错误)

不使用白色的明显原因 space 是换行也是 white space,并且 C++ 对所有 white space 都一视同仁。并关闭 手,我不知道任何接受任意白色的语言space 作为分隔符。

据推测,可以使用 Unicode 0xA0(不间断 space)——它是 排版时使用最广泛的解决方案。我看到两个问题 但是:首先,它不在基本字符集中,其次, 它在视觉上没有区别;你看不到它不是 space 只是在普通编辑器中查看文本。

除此之外,没有太多选择。你不能使用逗号,因为 这已经是一个合法的令牌(目前 1,234 之类的东西 合法的 C++,含义 234)。在可能发生的情况下 在法律代码中,例如a[1,234]。虽然我无法想象任何真实的 实际使用这个的代码,有一个基本规则,即没有合法的程序, 不管多么荒谬,都应该默默地改变语义。

类似的考虑意味着_也不能使用;如果有 #define _234 * 2,那么a[1_234]会默默的改变 代码。

我不能说我对'的选择特别满意,但它 确实有在欧洲大陆使用的优势,至少在 某些类型的文本。 (我好像记得在德语里看到过,因为 例如,虽然在典型的 运行 文本中,德语与大多数其他文本一样 语言,将使用一个点或一个不间断的space。但也许是 瑞士德语。) ' 的问题在于解析;序列 '1' 是 已经合法,'123'。所以像 1'234 这样的东西可能是 1, 接着是字符常量的开始;我不确定你有多远 必须向前看才能做出决定。没有合法的顺序 C++中整数常量后面可以跟一个字符 常量,所以打破合法代码没有问题,但这意味着 词法扫描突然变得非常依赖上下文。

(关于您的评论:选择a没有逻辑 小数点或千位分隔符。例如,小数点分隔符是 当然不是句号。它们只是任意约定。)

这与语言的解析方式有关。编译器作者很难重写他们的产品以接受 space 分隔文字。

此外,我认为用 space 分隔数字并不常见。我见过,它总是非白色space字符,即使在不同的国家也是如此。

float floating_point_literal = 0.0000153;   /* C, C++*/

auto floating_point_literal = 0.0000153;    // C++11

auto floating_point_literal = 0.000'015'3;  // C++14

评论无妨:

/*  0. 0000 1530 */ 
float floating_point_literal = 0.00001530; 

二进制字符串可能难以解析:

long bytecode = 0b1111011010011001; /* gcc , clang */  

long bytecode = 0b1111'0110'1001'1001;  //C++14
// 0b 1111 0110 1001 1001  would be better, really.
// It is how humans think.

供考虑的宏:

#define B(W,X,Y,Z)    (0b##W##X##Y##Z)
#define HEX(W,X,Y,Z)  (0x##W##X##Y##Z)
#define OCT(O)        (0##O)



long z = B(1001, 1001, 1020, 1032 ); 

// result :  long z = (0b1001100110201032);

 long h = OCT( 35); 

// result :  long h  = (035); // 35_oct => 29_dec

 long h = HEX( FF, A6, 3B, D0 ); 

// result :  long h  = (0xFFA6BD0);