为什么 C++ 流将布尔值视为数字?
Why do C++ streams treat bools as numerics?
在 C++ 中,当您输出 bool
时,流 I/O 库默认不会打印“true”或“false”,而是打印“1”或“0”。相反,需要通过 std::boolalpha
/std::noboolalpha
:
明确请求基于字的打印
#include <iostream>
int main()
{
std::cout << bool{ false }; //Prints "0"
std::cout << std::boolalpha; //Print all bools with alphanumerics
std::cout << bool{ false }; //Prints "false"
std::cout << std::noboolalpha; //Return to default
}
撇开这作为默认值是否合适(这对初学者来说肯定会造成混淆),我完全不确定为什么 C++ 提供 bool
-as-numeric 功能。我能想到的一些似是而非的理由:
- C89、C99 和 C++ 之间
bool
的标准化混乱,可能意味着 operator<<
的重载无法区分 bool
和 int
小号,
- 原始本地化支持(英语中的“true”与德语中的“Wahr”不同,但“1”在任何地方都是“1”...使用阿拉伯数字),或者只是
- 序列化到磁盘时的“输出参数”问题(
std::ofstream{"filename"} << static_cast<int>(my_bool_variable);
不是特别麻烦,但输入模拟需要一个临时变量。)
无论如何,我在网上找不到实际(历史)原因;例如,该主题从未在 C++FAQ 中提及。所以:为什么 C++ 在其 input/output 流中提供这种 bool
-as-numeric 功能?
std::cout << bool{b}
使用 std::use_facet<std::num_put<char>>(std::cout.getloc()).put(std::cout, std::cout, std::cout.fill(), bool{b})
进行实际输出。
这基本上是制作一个 printf 说明符并打印它(由标志修改)。
这是猜测,但可能是因为在 C++98 中,当它最初被标准化时(可能在准标准 C++ 中),C 中的布尔类型是 int
,所以 printf("%d", 0 == 0);
输出 1
。 (这仍然是 _Bool
提升为 int
的情况)。所以 C++ 希望在这种特定情况下将 bool
s 视为数字类型(特别是因为它使用了语言环境的 numeric 方面),并且只使用 [= 的 printf 说明符18=],以匹配相应 C 代码中的输出。
请注意 std::cout << std::setfill('0') << std::setw(5) << true;
输出 00001
(可能甚至 commas/spaces/full 也会停止,具体取决于语言环境)。没有 std::boolalpha
,std::cout << bool{b}
从字面上等同于 std::cout << static_cast<int>(bool{b})
,就像 C 可变参数提升一样。
此外,通过修改语言环境的 std::numpunct
方面并覆盖 std::numpunct<CharT>::do_truename
and do_falsename
可获得本地化支持。但这与默认行为是否应为 std::boolalpha
.
是正交的
在 C++ 中,当您输出 bool
时,流 I/O 库默认不会打印“true”或“false”,而是打印“1”或“0”。相反,需要通过 std::boolalpha
/std::noboolalpha
:
#include <iostream>
int main()
{
std::cout << bool{ false }; //Prints "0"
std::cout << std::boolalpha; //Print all bools with alphanumerics
std::cout << bool{ false }; //Prints "false"
std::cout << std::noboolalpha; //Return to default
}
撇开这作为默认值是否合适(这对初学者来说肯定会造成混淆),我完全不确定为什么 C++ 提供 bool
-as-numeric 功能。我能想到的一些似是而非的理由:
- C89、C99 和 C++ 之间
bool
的标准化混乱,可能意味着operator<<
的重载无法区分bool
和int
小号, - 原始本地化支持(英语中的“true”与德语中的“Wahr”不同,但“1”在任何地方都是“1”...使用阿拉伯数字),或者只是
- 序列化到磁盘时的“输出参数”问题(
std::ofstream{"filename"} << static_cast<int>(my_bool_variable);
不是特别麻烦,但输入模拟需要一个临时变量。)
无论如何,我在网上找不到实际(历史)原因;例如,该主题从未在 C++FAQ 中提及。所以:为什么 C++ 在其 input/output 流中提供这种 bool
-as-numeric 功能?
std::cout << bool{b}
使用 std::use_facet<std::num_put<char>>(std::cout.getloc()).put(std::cout, std::cout, std::cout.fill(), bool{b})
进行实际输出。
这基本上是制作一个 printf 说明符并打印它(由标志修改)。
这是猜测,但可能是因为在 C++98 中,当它最初被标准化时(可能在准标准 C++ 中),C 中的布尔类型是 int
,所以 printf("%d", 0 == 0);
输出 1
。 (这仍然是 _Bool
提升为 int
的情况)。所以 C++ 希望在这种特定情况下将 bool
s 视为数字类型(特别是因为它使用了语言环境的 numeric 方面),并且只使用 [= 的 printf 说明符18=],以匹配相应 C 代码中的输出。
请注意 std::cout << std::setfill('0') << std::setw(5) << true;
输出 00001
(可能甚至 commas/spaces/full 也会停止,具体取决于语言环境)。没有 std::boolalpha
,std::cout << bool{b}
从字面上等同于 std::cout << static_cast<int>(bool{b})
,就像 C 可变参数提升一样。
此外,通过修改语言环境的 std::numpunct
方面并覆盖 std::numpunct<CharT>::do_truename
and do_falsename
可获得本地化支持。但这与默认行为是否应为 std::boolalpha
.