2013-03-04 115 views
18

common_type<long, unsigned long>::typeunsigned long因为涉及以后整体推广的标准说,操作数...为什么不是common_type <long,unsigned long> :: type = long long?

[...]如果具有无符号整数类型操作数的秩大于或等于 的类型的秩另一个操作数,与 符号整型操作数应转换为操作数的类型与 无符号整型

不叫整体推进体制越野车,但它好像如果有一个更大有符号整数类型wh它可以表示它应该使用的有符号和无符号操作数的范围。

我知道一些平台可能有很长的== long long,在这种情况下上述规则可以生效。但是如果有有更大的有符号整型可用,不应该使用它吗?

+4

我不相信有任何保证'long long'将包含'unsigned long'的整个范围。如果它与其他规格说明一样,唯一的要求是它至少与“long”一样多。无论平台如何,类型提升都应该是一致的,所以对重载解析有一定的可预测性。 – jpm 2013-03-04 21:36:20

+2

'std :: common_type'匹配确定三元运算符返回类型的规则。从这个角度来看,三元运算符返回比两个分支都大的类型显然是错误的。 – 2013-03-04 21:37:53

+0

@KevinBallard我其实并不觉得这显然是错的。当分支返回不同的签名时,返回比其中任何一个分支更大的类型似乎是唯一可以保证无缺陷的事情。 – David 2013-03-04 21:52:36

回答

6

首先,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; 
} 

但是,目前的行为是一个问题是knownproposal的存在是为了去除一些惊喜。

-Hannes

+0

那么你的问题是什么?我回答“为什么不是common_type :: type = long long?”您的示例不会添加比我的示例更多的信息,请纠正我,如果我错了。但当然,1 <* Maxulong * -1 ... – 2013-03-13 19:42:00

+0

这个问题很清楚,标准确实说明了它是这样的,我不需要一个答案来重申它是这样的,因为标准是这样说的* 。但就像我说的,我很高兴你的链接在底部,它们是相关的并且是部分答案(因为这是一个已知的'问题',但并没有说明为什么它是以这种方式开始的) – David 2013-03-13 21:10:49