Is the operation "false < true" well defined?
C++BooleanLanguage LawyerComparison OperatorsC++ Problem Overview
Does the C++ specification define:
- the existence of the 'less than' operator for boolean parameters, and if so,
- the result of the 4 parameter permutations?
In other words, are the results from the following operations defined by the specification?
false < false
false < true
true < false
true < true
On my setup (Centos 7, gcc 4.8.2) , the code below spits out what I'd expect (given C's history of representing false as 0 and true as 1):
false < false = false
false < true = true
true < false = false
true < true = false
Whilst I'm pretty sure most (all?) compilers will give the same output, is this legislated by the C++ specification? Or is an obfuscating, but specification-compliant compiler allowed to decide that true is less than 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;
}
C++ Solutions
Solution 1 - C++
TL;DR:
The operations are well defined according to the draft C++ standard.
Details
We can see that by going to the draft C++ standard section 5.9
Relational operators which says (emphasis mine going forward):
>The operands shall have arithmetic, enumeration, or pointer type, or type std::nullptr_t. The operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all yield false or true. The type of the result is bool
and bools are arithematic types from 3.9.1 Fundamental types
>Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types.
and
>Integral and floating types are collectively called arithmetic types.
and true
and false
are boolean literals from 2.14.6
Boolean literals:
boolean-literal:
false
true
Going back to section 5.9
to see the mechanics of the relational operators further, it says:
>The usual arithmetic conversions are performed on operands of arithmetic or enumeration type.
the usual arithmetic conversions are covered in section 5
which says:
>Otherwise, the integral promotions (4.5) shall be performed on both operands
and section 4.5
says:
>A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
and so the expressions:
false < false
false < true
true < false
true < true
using these rules become:
0 < 0
0 < 1
1 < 0
1 < 1
Solution 2 - C++
Boolean values are subject to the usual integer promotions, with false
defined as 0
and true
defined as 1
. That makes all the comparisons well defined.
Solution 3 - C++
According to the C++ Standard (5.9 Relational operators)
> 2 The usual arithmetic conversions are performed on operands of > arithmetic or enumeration type.
and
> 1...The type of the result is bool.
and (3.9.1 Fundamental types)
> 6 Values of type bool are either true or false.49 [ Note: There are no > signed, unsigned, short, or long bool types or values. —end note ] > Values of type bool participate in integral promotions (4.5).
and (4.5 Integral promotions)
> 6 A prvalue of type bool can be converted to a prvalue of type int, > with false becoming zero and true becoming one.
So in all your examples true is converted to int 1 and false is converted to int 0
These expressions
false < false
false < true
true < false
true < true
are entirely equivalent to
0 < 0
0 < 1
1 < 0
1 < 1
Solution 4 - C++
Boolean false
is equivalent to int 0
, and boolean true
is equivalent to int 1
.
So this explains why the expression false < true
=> 0 < 1
is the only one which returns true
.