【问题标题】:Is the operation "false < true" well defined?操作“false < true”是否定义明确?
【发布时间】:2014-11-26 10:44:45
【问题描述】:

C++ 规范是否定义:

  1. 布尔参数是否存在“小于”运算符,如果存在,
  2. 4 个参数排列的结果?

换句话说,规范定义了以下操作的结果吗?

false < false
false < true
true < false
true < true

在我的设置 (Centos 7, gcc 4.8.2) 中,下面的代码给出了我的预期(鉴于 C 将 false 表示为 0 并将 true 表示为 1 的历史):

false < false = false
false < true = true
true < false = false
true < true = false

虽然我很确定大多数(所有?)编译器都会给出相同的输出,但这是由 C++ 规范规定的吗?还是允许混淆但符合规范的编译器决定真小于假?

#include <iostream>

const char * s(bool a)
{
  return (a ? "true" : "false");
}

void test(bool a, bool b)
{
  std::cout << s(a) << " < " << s(b) << " = " << s(a < b) << std::endl;
}

int main(int argc, char* argv[])
{
  test(false, false);
  test(false, true);
  test(true, false);
  test(true, true);
  return 0;
}

【问题讨论】:

  • @Ulterior 有有效的用途。比如在std::vector&lt;bool&gt;上使用std::min作为&amp;&amp;
  • @Ulterior 如果你能找出一个在 StackOverflow 这么多年之后还没有被问到的好问题,那么你值得加分。这不是拖钓。
  • @Ulterior 询问的动机是真实的:我对 C++(来自 C)相当陌生,并且想将一些对象存储在 std::set 中。我的对象
  • 一个令人不安的结果是当pq 是bool 类型时,p &lt;= q 表示p implies q
  • @Technophile 大概令人不安的是&lt;= 可能会被无意中读作左箭头,并且“仅当”(即“[实质上] 暗示”)右箭头有时会被排版或非正式书写类似于=&gt;(即,具有类似于= 的双轴)。左箭头有时甚至被读作“如果”,尽管我相信这远不如右箭头用于“仅当”那么常见。

标签: c++ boolean language-lawyer comparison-operators


【解决方案1】:

TL;DR:

这些操作根据 C++ 标准草案进行了很好的定义。

详情

我们可以通过转到 draft C++ standard 部分 5.9 关系运算符看到这一点(强调我的未来):

操作数应具有算术、枚举或指针类型,或类型std::nullptr_t。运营商 (大于)、=(大于或等于)全部产量 虚假或真实。结果的类型是bool

和 bool 是 3.9.1 基本类型中的算术类型

类型bool、char、char16_t、char32_t、wchar_t,有符号和无符号整数类型统称为 称为整数类型。

整数和浮点类型统称为算术 类型。

truefalse 是来自2.14.6 布尔文字的布尔文字:

boolean-literal:
    false
    true

回到5.9 部分,进一步了解关系运算符的机制,它说:

通常的算术转换是在算术或枚举类型的操作数上执行的。

通常的算术转换5 部分中介绍,其中说:

否则,应在两个操作数上执行积分提升 (4.5)

4.5 部分说:

bool 类型的纯右值可以转换为 int 类型的纯右值,false 变为 0 和 true 合而为一。

等等表达式:

false < false
false < true
true < false
true < true

使用这些规则变成:

0 < 0
0 < 1
1 < 0
1 < 1

【讨论】:

  • 很好,这与任何答案可能一样明确,同时仍然易于阅读。尼特:我认为你加粗了错误的“类型”:“操作数应具有算术、枚举或指针type,或类型std::nullptr_t。”为清楚起见添加括号给出 ((arithmetic, enumeration, or pointer) type) 或 (type std::nullptr_t)。
  • 不是它会改变你的答案,而是 N3485 [over.built]/12:对于每一对提升的算术类型 L 和 R,存在形式为的候选运算符函数 ... bool operator - 在您引用的规则之前提出的论点是否适用?
  • @chris 我对那部分不是很熟悉,所以我必须考虑一下,但我认为答案不会与我所看到的有所不同。
  • 是的,无论哪种方式,促销都是第一件事。
【解决方案2】:

布尔值服从通常的整数提升,false 定义为 0true 定义为 1。这使得所有的比较都得到了很好的定义。

【讨论】:

  • ...和关系运算符被指定为对算术或枚举类型的操作数执行通常的算术转换(包括整数提升)。
  • 我喜欢这个答案比Shafik的短,但我认为false定义为0true的关键点在标准中定义为1 (而不是仅仅通过惯例)需要证据来支持它。
  • @KRyan 什么,你不会相信我的话吗? :) 在 bool 类型出现之前,甚至在 C++ 出现之前,布尔运算的结果被定义为 0 为 false 和 1 为 true。如果你能在 K+R 中找到它,我不会感到惊讶。
  • @KRyan 我不能回溯到 K+R,但我挖出了 1990 年 ANSI C 标准的副本。第 6.3.8 节说“每个运算符&lt;(小于)、&gt;(大于)、&lt;=(小于或等于)和&gt;=(大于或等于)应产生如果指定的关系为真,则为 1,如果为假,则为 0。结果的类型为 int。"
  • IIRC 最大的问题是,在 K&R 中,enum bool { false = 0, true = 1} 是合法的,但没有定义 operator&lt;
【解决方案3】:

根据 C++ 标准(5.9 关系运算符)

2 通常的算术转换是在操作数上执行的 算术或枚举类型。

1...结果的类型是bool。

和(3.9.1 基本类型)

6 bool 类型的值为 true 或 false.49 [ 注意:没有 有符号、无符号、短或长布尔类型或值。 ——尾注] bool 类型的值参与积分促销 (4.5)。

和(4.5 整体促销)

6 bool 类型的纯右值可以转换为 int 类型的纯右值, false 变为 0,true 变为 1

所以在你所有的例子中,true 被转换为 int 1,而 false 被转换为 int 0

这些表达

false < false
false < true
true < false
true < true

完全等价于

0 < 0
0 < 1
1 < 0
1 < 1

【讨论】:

    【解决方案4】:

    布尔值false 等价于int 0,布尔值true 等价于int 1。 所以这就解释了为什么表达式 false &lt; true => 0 &lt; 1 是唯一返回 true 的表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-11
      • 2017-03-15
      • 2011-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-11
      • 2015-03-06
      相关资源
      最近更新 更多