是否正确定义了“ false <true”操作?


153

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 ++规范是否对此做了规定?还是允许混淆但符合规范的编译器确定true小于false?

#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;
}

6
@Ulterior有有效的用途。如使用std::minstd::vector<bool>&&
Angew不再为2014年

19
@Ulterior如果您能在StackOverflow的所有这些年中找到一个尚未被问到的好问题,那您值得一提。这不是拖钓。
Mark Ransom 2014年

35
@Ulterior询问的动机是真诚的:我对C ++相当陌生(来自C),想将一些对象存储在std :: set <>中。我对象的<运算符的实现主要基于对象的布尔属性,其次是其他辅助标识属性。在遍历集合时,我想确保首先使用“ false”对象。虽然它在此时此刻对我有用,但我正在寻找保证,可以保证它可以跨平台(包括嵌入式平台)工作,而不必在我对象的<操作员。
duncan 2014年

26
一个令人不安的后果是,p <= q手段p implies qpq为bool类型的!
西奥多·诺韦尔

4
@Technophile大概是令人不安的是,它<=可能会无意间被读为左箭头,并且“仅当”(即“(实质上)暗示”)右箭头有时被排版或非正式地写成类似于=>(即,双轴类似=)。 。左箭头有时甚至被理解为“如果”,尽管我认为这远不如将右箭头用于“仅当”。
伊利亚·卡根

Answers:


207

TL; DR:

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

细节

我们可以通过转到关系运算符的C ++标准部分草稿看到这一点(强调我的前进):5.9

操作数应具有算术,枚举,或指针类型,或类型的std :: nullptr_t。运算符<(小于),>(大于),<=(小于或等于)和> =(大于或等于)都产生false或true。结果的类型是布尔

和布尔是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类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1。

表达式如下:

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

使用这些规则将成为:

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

6
很好,这几乎与任何答案都一样明确,同时仍然易于阅读。尼特:我认为您用粗体显示了错误的“类型”:“ 操作数应具有算术,枚举或指针类型,或类型为std :: nullptr_t。” 为了清楚起见,添加括号给出了((算术,枚举或指针)类型)或(类型std :: nullptr_t)。

并不是说它改变了您的答案,而是N3485 [over.built] / 12:对于每对提升的算术类型L和R,都存在 ... bool operator <(L,R)形式的候选算子功能-在您引用的规则适用之前,提倡的论点难道不是吗?
克里斯

@chris我对这一部分不是很熟悉,所以我不得不考虑一下,但是我认为答案不会改变。
Shafik Yaghmour

是的,升迁是第一件事。
克里斯

63

布尔值是受到通常整数促销,与false定义为0true定义为1。这使得所有比较都定义良好。


2
...并且指定了关系运算符,以对算术或枚举类型的操作数执行常规的算术转换(包括整数提升)。
TC

5
我喜欢这个答案比Shafik的答案要短,但是我认为false定义为0true定义为1 标准的关键点(而不是仅仅通过惯例)需要证据支持。
KRyan 2014年

@KRyan什么,您不会相信我的话吗?:)在没有bool类型之前,甚至在C ++之前,布尔运算的结果都定义0为false和1true。如果您可以在K + R中找到它,我不会感到惊讶。
Mark Ransom

1
@KRyan我无法回溯到K + R,但是我掏出了1990 ANSI C标准的副本。第6.3.8节说:“ 如果指定的关系为真,则每个运算符<(小于),>(大于),<=(小于或等于)和>=(大于或等于)应产生1,如果为0,则产生0。 false。结果的类型为int。”
Mark Ransom 2014年

1
IIRC的最大问题是在K&R中enum bool { false = 0, true = 1}是合法的,但没有定义operator<
MSalters 2014年

22

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

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

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

和(3.9.1基本类型)

6 bool类型的值为true或false。49[注意:没有带符号,无符号,短或长的bool类型或值。—尾注] bool类型的值参与积分提升(4.5)。

和(4.5整体促销)

6 bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1

因此,在所有示例中,将true转换为int 1,将false转换为int 0

这些表达

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

完全等同于

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

8

布尔false值等效于int 0,布尔值true等效于int 1。因此,这解释了为什么表达式false < true=> 0 < 1是唯一返回的表达式true

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.