首先,std::common_type(当然还有 boost::type_traits::common_type)使用三元运算符来检索类型结果。在这种情况下,相关报价来自CppReference , 6b)
E2 和 E3 具有算术或枚举类型:应用通常的算术转换将它们带入公共类型,该类型就是结果。
有了这些信息,我们可以在c++ 标准,5p10,第 88 页中找到常用算术转换的规则。
— 否则,如果无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,则将有符号整数类型的操作数转换为无符号整数类型的操作数的类型。
所以基本上你的问题的答案是:......因为标准是这样说的。
但您并不是唯一一个发现这种行为出乎意料的人。这是一个可以尝试的快速运行示例:
#include <iostream>
#include <typeinfo>
#include <type_traits>
int main(int argc, const char* argv[])
{
std::cout << typeid(std::common_type<char, unsigned char>::type).name() << std::endl;
// I would expect "short", and the result is "int", ok so far.
std::cout << typeid(std::common_type<short, unsigned short>::type).name() << std::endl;
// I would expect "int", and the result is "int", yay.
std::cout << typeid(std::common_type<int, unsigned int>::type).name() << std::endl;
// I would expect "long", but the result is "unsigned int"
std::cout << typeid(std::common_type<long, unsigned long>::type).name() << std::endl;
// I would expect "long long", but the result is "unsigned long"
// So this usual arithmetic conversion can lead to unexpected behavior:
auto var_auto = true ? var_i : var_ui;
std::cout << typeid(var_auto).name() << std::endl; // unsigned int
std::cout << var_auto << std::endl; // 4294967173
return 0;
}
但是当前的行为是一个问题是已知的,并且存在消除一些意外的提议。
-汉内斯