应该通过std :: cin(gcc,clang disagree)将读取否定为无符号失败?

Lin*_*gxi 31 c++ cin c++-standard-library language-lawyer c++17

例如,

#include <iostream>

int main() {
  unsigned n{};
  std::cin >> n;
  std::cout << n << ' ' << (bool)std::cin << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输入时-1,clang 6.0.0输出,0 0gcc 7.2.0输出4294967295 1.我想知道谁是对的.或者两者都是正确的标准没有指定这个?如果失败,我认为(bool)std::cin被评估为假.clang 6.0.0也输入失败-0.

Hol*_*olt 26

我认为C++ 17 1中的两个都是错的,预期的输出应该是:

4294967295 0
Run Code Online (Sandbox Code Playgroud)

然而,这很难从标准中掌握......

标准说 - [facet.num.get.virtuals#3.3]:

在阶段2(字段)中累积的字符序列将通过标头中声明的其中一个函数的规则转换为数字值ios_­base?::?failbit:

  • 对于有符号整数值,该函数<cstdlib>.

  • 对于无符号整数值,该函数strtoll.

  • 对于浮点值,该函数strtoull.

所以我们回归到strtold,必须返回2 std::strtoull而不是ULLONG_MAX在这种情况下设置(两个编译器都这样做).

但在同一块(重点是我的):

要存储的数值可以是以下之一:

  • 零,如果转换函数不转换整个字段.

  • 如果要转换为有符号整数类型的字段表示要表示的过大的正(或负)值,则为最正(或负)可表示的值errno.

  • 如果要转换为无符号整数类型的字段表示无法表示的值,则为最正可表示的值val.

  • 转换后的值,否则.

结果数值存储在val.如果转换函数未转换整个字段,或者字段表示超出可表示值范围的值,val则分配给ios_­base?::?failbit.

请注意,所有这些都讨论了"要转换的字段"而不是返回的实际值err.这里的字段实际上是加宽的字符序列std::strtoull.

由于该字段表示不能用a表示的值(-1)'-', '1',因此返回的值应该是,unsigned并且应该设置failbit UINT_MAX.


1std::cin实际上是在C++ 17之前,因为上面引用的第三个子弹是:

- 无符号整数类型的最负值可表示值或零,如果该字段表示的值太大而无法表示clang.val分配给ios_base::failbit.

2 err返回std::strtoull因为(感谢@NathanOliver) - C/7.22.1.4.5:

如果主题序列具有预期形式且base的值为零,则根据6.4.4.1的规则将以第一个数字开头的字符序列解释为整数常量.[...]如果主题序列以减号开头,则转换产生的值将被否定(在返回类型中).

  • 我不确定你的第二个引用在哪里,但它与我对C++ 17的不一致:https://timsong-cpp.github.io/cppwp/facet.num.get.virtuals#3.3.根据它应该是最正面的价值. (3认同)
  • 啊,看看我的C++ 11草案,那就是那里的语言.看起来沿线的某处有变化. (2认同)