为什么 common_type<long, unsigned long>::type = long long 不是?
Why isn't common_type<long, unsigned long>::type = long long?
common_type<long, unsigned long>::type
是unsigned long
,因为对于积分提升后的操作数,标准规定…
[…如果操作数为无符号整数类型,其排名大于或等于另一个操作数类型的秩有符号整数类型应转换为带的操作数类型无符号整型
不是说整型提升系统有问题,但如果有一个更大的符号整数类型,可以表示有符号操作数和无符号操作数的范围,就应该使用它。
我知道有些平台可能有long == long,在这种情况下,上述规则可以生效。但是如果是一个更大的符号整型可用,不应该使用它吗?
首先,std::common_type(当然还有boost::type_traits::common_type)使用三元操作符来检索类型结果。在本例中,相关的引用来自CppReference, 6b)
有了这些信息,我们可以在c++标准5p10第88页中找到常用算术转换的规则。E2和E3具有算术或枚举类型:应用通常的算术转换将它们转换为公共类型,该类型是结果。
所以基本上你的问题的答案是:…因为标准是这么说的—否则,如果无符号整数类型的操作数的排名大于或等于另一个操作数类型的排名,则将有符号整数类型的操作数转换为无符号整数类型的操作数的类型。
但你不是唯一一个发现这种行为出乎意料的人。下面是一个可以快速运行的示例:
#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;
}
但是,当前的行为是一个问题是已知的,并且存在一个建议来消除一些意外。
hannes
相关文章:
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 在 QVector<std::unique_ptr 上使用 std::find<Type>>
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 使用 cmake 的 Linux 终端上的"Conversion to non-scalar type is requested"错误
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 控制到达非空函数clang(-Wreturn-type)的末尾
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- 将系数存储在头文件的数组中("does not name a type"错误)
- 尝试打开 ifstream 时出现"Incomplete type"错误
- 错误:隐式转换更改符号:'int'到'unsigned long'
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 在"结构提升::enable_if<提升::is_pod<T>,无效>"中没有名为"type"的类型
- "Missing type specifier - int assumed"无法通过向主函数添加"return 0"来解决
- "How to use long long data-type rather than pointers data-type to modify other variables ?"
- vtkTypeTraits.h 错误:"Type long is not 4 or 8 bytes in size."
- 编译器错误"character constant too long for its type" 。怎么了?
- 为什么 common_type<long, unsigned long>::type = long long 不是?