为什么没有为 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);
从 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;
感觉不像带撇号的情况那么正确。
本着
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);