This rule exists because it is the best solution to the problem.
You can't compare apples and oranges. The only options are:
- convert orange to apple
- convert apple to orange
- convert both to some other common type
Out of the first two options, converting both to unsigned makes more sense than converting both to signed.
How about the third option? I suppose a possibility would be to convert both values to long and then do the comparison. This might seem like a good idea at first, but if you think about it some more then there are some problems:
- If longandintare the same size then this doesn't actually help
- Even if longis bigger thanint, you have just moved the problem off to the case of comparing alongwith anunsigned long.
- It would be harder to write portable code.
The last point is important.  The historical rules about short and char being promoted to int are actually extremely annoying when you are writing template code or code with overloaded functions, because it changes which overload is called.
We would not want to introduce any more rules of the same type (e.g. promote int to long if it is in comparison with unsigned int but only if sizeof(long) > sizeof(int) yada yada yada).