C++ 为什么不是';t普通_型<;长,无符号长>;::类型=长?

C++ 为什么不是';t普通_型<;长,无符号长>;::类型=长?,c++,language-lawyer,integer-promotion,C++,Language Lawyer,Integer Promotion,common_type::type是无符号长,因为关于整数提升后的操作数,标准规定 […]如果具有无符号整数类型的操作数的秩大于或 等于另一个操作数类型的秩,该操作数具有 有符号整数类型应转换为具有 无符号整数类型 不想调用整数提升系统,但似乎有一个更大的有符号整数类型,它可以表示有符号和无符号操作数的范围,应该使用它 我知道一些平台可能有long==long-long,在这种情况下,上述规则可以生效。但是如果有一个更大的有符号整数类型可用,难道不应该使用它吗?首先,std::common_ty

common_type::type
无符号长
,因为关于整数提升后的操作数,标准规定

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

不想调用整数提升系统,但似乎有一个更大的有符号整数类型,它可以表示有符号和无符号操作数的范围,应该使用它


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

首先,std::common_type(当然还有boost::type_traits::common_type)使用三元运算符来检索类型结果。在这种情况下,相关报价来自于(6b)

E2和E3具有算术或枚举类型:通常的算术转换用于将它们转换为公共类型,该类型是结果

有了这些信息,我们可以在第88页5p10中找到常用算术转换的规则

-否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,则具有有符号整数类型的操作数应转换为具有无符号整数类型的操作数类型

所以基本上你的问题的答案是:……因为标准上是这么说的

但你不是唯一一个发现这种行为出人意料的人。下面是一个可快速运行的示例:

#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;
}
#包括
#包括
#包括
int main(int argc,const char*argv[]
{

std::难道我不相信有任何保证
long
将涵盖
无符号long
的整个范围。如果它与尺寸规格的其余部分一样,唯一的要求是它至少用
long
的位数表示。无论平台如何,类型升级都应表现一致,因此,在重载解析方面有一些可预测性。
std::common_type
与确定三元运算符返回类型的规则相匹配。从这个角度来看,三元运算符返回的类型比其两个分支中的任何一个都大似乎是明显错误的。@KevinBallard我并不认为这似乎是正确的显然是错误的。当分支返回不同的有符号属性时,返回一个大于其任何一个分支的类型似乎是保证无错误的唯一方法。@KevinBallard,您希望
(b?(无符号字符)255:(有符号字符)-1)
做什么?@Sh3ljohn积分提升规则是…奇怪的。类型小于
int
提升到
int
。我发布的规则在积分提升后适用。那么你的问题是什么?我回答“为什么公共类型::type=long?”你的例子没有比我的例子添加更多的信息,如果我错了,请纠正我。但当然,1