为什么auto被推导为int而不是uint16_t

Ves*_*niK 19 c++ integer-promotion auto c++11

我有以下代码:

uint16_t getLastMarker(const std::string &number);
...
const auto msgMarker = getLastMarker(msg.number) + static_cast<uint16_t>(1);
static_assert(std::is_same<decltype(msgMarker), const int>::value, "Should fail");
static_assert(std::is_same<decltype(msgMarker), const uint16_t>::value, "Should not fail");
Run Code Online (Sandbox Code Playgroud)

我希望第一个断言会失败而第二个断言不会失败.然而,gcc 4.9.2clang 3.6做相反的事情.如果我在我的代码中使用uint16_t而不是auto,则正确的断言失败而另一个成功.

PS最初我只是1代替static_cast<uint16_t>(1)并且认为问题是由数字文字1具有int类型但错误断言甚至在此处显式转换后失败的事实引起的.

Sha*_*our 16

Addition将对其操作数执行通常的算术转换,在这种情况下,由于整数提升,操作数将被提升为int,结果也将为int.

您可以使用uint16_t而不是auto来强制转换,或者在一般情况下可以使用static_cast.

有关为什么小于int的类型被提升为更大类型的原因,请参阅为什么在C和C++中的算术运算之前必须将short转换为int?.

供参考,从草案C++标准部分5.7 添加运算符:

[...]通常的算术转换是针对算术或枚举类型的操作数执行的[...]

并从章节5 表达:

[...]否则,应在两个操作数上执行整体促销(4.5).59然后,以下规则应适用于推广的操作数[...]

4.5 整体促销(强调我的)部分:

如果int可以表示源类型的所有值,则除了bool,char16_t,char32_t或wchar_t之外的整数类型的prvalue(其整数转换等级(4.13)小于int的等级)可以转换为int类型的prvalue ; 否则,源prvalue可以转换为unsigned int类型的prvalue.

假设int大于16位.


Mik*_*our 8

算术运算不适用于任何小于的类型int.因此,如果uint16_t小于int,将提升int(或可能更大的类型,如果需要的话,以匹配另一个操作数)进行相加之前.

添加的结果将是提升类型.如果你想要另一种类型,你必须在之后进行转换.