common_type<long, unsigned long>::type是unsigned long,因为关于整数提升后的操作数,标准说...
...如果无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,则需要将带符号整数类型的操作数转换为无符号整数类型的操作数类型
不是说整数提升系统是错误的,但似乎如果有更大的带符号整数类型可以表示有符号和无符号操作数的范围,那么就应该使用它。
我知道一些平台可能会有long == long long,在这种情况下,上面的规则可以生效。但是如果有更大的带符号整型可用,难道不应该使用它吗?
发布于 2013-03-13 23:04:39
首先,std::common_type (当然还有boost::type_traits::common_type)使用三元运算符来检索类型结果。在这种情况下,相关引用来自CppReference,6b)
、E2和E3具有算术或枚举类型:通常应用算术转换将它们转换为公共类型,该类型就是结果。
有了这些信息,我们可以在c++ standard,5p10,第88页找到常用算术转换的规则。
-否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则具有带符号整数类型的操作数应转换为具有无符号整数类型的操作数的类型。
所以基本上你的问题的答案是:...because,标准是这样说的。
但你并不是唯一一个发现这种行为出乎意料的人。下面是一个可以快速运行的示例:
#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;
}但是,目前的行为是一个问题是known,而proposal的存在是为了消除一些惊喜。
-Hannes
https://stackoverflow.com/questions/15211463
复制相似问题