I had thought that this would be an easy question resolve via Google, but I can't seem to find a definitive (or even speculative) answer:
When using a comparator statement, in which order does implicit casting occur?
int i = -1;
size_t t = 1;
bool result = i < t;
Is this equivalent to:
bool result = i < int(t); // equals true
or:
bool result = size_t(i) < t; // equals false
That is the easy part of the question - the second part is "what is the general rule", as it could be:
- The 'simpler' argument is always converted into the 'more complex' argument (i.e. size_t->int), or
- The first (or second) argument is always converted to the type of the second (or first) argument, or
- The inbuilt primitives such as size_t and ints have specific comparator operators which specify the casting case-by-case.
All three seem reasonable, although the second would yield significantly different behaviour to what most people would intuitively expect.
The VC++ compiler seems to think it's worth a level 3 warning when you compare an int with a size_t - and yet it only gives a level 4 warning when you return a negative number from a function that returns a size_t (which results in a number just over half the maximum integer being returned).
In an effort to get rid of all level 4 warnings, I now explicitly cast everything anyway, but I wanted to know "the truth". This must be defined somewhere...
The rules are fairly complex, and depend on the implementation.
Basically, however:
Both types are "promoted". This means that anything
smaller than int
is promoted to int
. (In the unlikely case
that size_t
is smaller than int
, it will be promoted to
a signed int
, and loose its unsignedness.)
If one of the types can contain all of the values of the
other, the other is converted to this type.
If one of the types is unsigned, and the other signed, and
they have the same size, the signed is converted to the
unsigned.
For int
and size_t
(which is required to be unsigned), this
means that unless size_t
is smaller than int
, the int
will
be converted to a size_t
.
$18.2/6- The type size_t is an implementation-defined unsigned integer
type that is large enough to contain the size in bytes of any object.
$5.9 - Otherwise, if the operand that has unsigned integer type has
rank greater than or equal to the rank of the type of the other
operand, the operand with signed integer type shall be converted to
the type of the operand with unsigned integer type. For the first
part, bool is promoted to an int, before the conversion as specified
by the C++ standard.
So, this means that 'i' is converted to the type of 'size_t' (assuming size_t is of type 'unsigned int' or greater). Then the results which is of type 'unsigned int' is converted to 'bool' (which is the type of result
).
Note that the Standard specifies that the rank of signed int
and unsigned int
the same.
Refer Section 4 and 5 of the C++ standard for the exact rules for conversions/promotions.