首先,std :: common_type(當然boost :: type_traits :: common_type)使用三元運算符來檢索類型結果。在這種情況下,相關的報價來自CppReference,6B)
E2和E3已經算術或枚舉型:常見的算術轉換應用,使他們的常見類型,該類型是結果。
有了這個信息,我們可以找到一個通常的算術轉換規則在c++ standard,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;
}
但是,目前的行爲是一個問題是known和proposal的存在是爲了去除一些驚喜。
-Hannes
我不相信有任何保證'long long'將包含'unsigned long'的整個範圍。如果它與其他規格說明一樣,唯一的要求是它至少與「long」一樣多。無論平臺如何,類型提升都應該是一致的,所以對重載解析有一定的可預測性。 – jpm 2013-03-04 21:36:20
'std :: common_type'匹配確定三元運算符返回類型的規則。從這個角度來看,三元運算符返回比兩個分支都大的類型顯然是錯誤的。 – 2013-03-04 21:37:53
@KevinBallard我其實並不覺得這顯然是錯的。當分支返回不同的簽名時,返回比其中任何一個分支更大的類型似乎是唯一可以保證無缺陷的事情。 – David 2013-03-04 21:52:36