C++11随机数生成器UIntType矛盾

17

C++11标准(N3242)第26.5.1.1节第1段说:

在整个子句26.5中,实例化一个模板的效果是:

[...]

f) 具有名为UIntType的模板类型参数的模板是未定义的,除非相应的模板参数是cv-unqualified, 并且是unsigned shortunsigned intunsigned longunsigned long long之一。

它在26.5.3.1中定义了线性同余生成器。该类的定义开头是这样的:

template<class UIntType, UIntType a, UIntType c, UIntType m>
class linear_congruential_engine

minstd_rand0 似乎违反了这个限制:

typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647>
    minstd_rand0;

由于minstd_rand0使用名为UIntType的模板参数中的uint_fast32_t(不能保证是unsigned shortunsigned intunsigned longunsigned long long之一),因此似乎对于#include <random>,或者至少对于使用minstd_rand0,具有未定义的效果。这个问题也适用于其他预定义的RNG,并且在C++14中似乎没有得到修复。

我的问题是:

  • 这真的是一个矛盾(或者说是极端的未定义行为),还是我漏掉了什么?
  • 这是否已经在缺陷报告中提到过?

编辑:我注意到这个缺陷报告似乎与这个问题有关。


好的,紧随其后的所需行为条款可以说必须要求使用这种类型是明确定义的。不管怎样,是否存在一个实际的系统,其中uint_fast32_t不是这些类型之一? - T.C.
@T.C. 我想可能是这样,但我认为只需要第10000次调用正确即可。第10001次调用仍然可能会导致问题(或者说,一个没有默认构造的引擎)。 - qbt937
@T.C. MSVC可能使用他们的unsigned __int32类型来定义uint_fast32_t(我不知道,因为我不使用MSVC)。尽管如此,我认为这个问题是学术性的。 - qbt937
1
@T.C. avr-gcc(适用于Atmel 8位微控制器的GCC)具有__uint24和__int24,它们不是“short”、“int”等之一。不幸的是,这是一个未记录的功能,但是gcc维基上的这个页面提到了它:https://gcc.gnu.org/wiki/avr-gcc#Types - qbt937
1
@T.C. 确实,但它也不是shortint等之一。很抱歉我误解了您所说的内置类型。我不应该和您争论。但是,任何标准库实际上都不会遇到这个问题(因为它们将制作一个能够使用uint_fast32_tlinear_congruential_engine实现),因此这更多地涉及标准中的矛盾,而不是任何实际问题。 - qbt937
显示剩余2条评论
3个回答

1
是和不是。根据18.4.1节,uint_fast32_t必须是无符号整数类型的别名。虽然在C++中唯一的无符号整数类型是unsigned char、short、int、long、long long(3.9.1),所以你提到的这个部分唯一可能矛盾的情况就是char以某种方式为32位或更宽,并且uint_fast32_t被定义为unsigned char的别名。

1

uint_fast32_t被指定为至少具有32位宽度的最快无符号整数类型。

在C++类型系统中,字符和整数类型都是整数类型,但字符类型不是整数类型(反之亦然)。

最后,无符号整数类型恰好是随机生成器枚举的类型。

我的结论是,使用uint_fast32_t符合标准(除非我错过了标准的某个部分,其中明确允许uint_fast32_t成为非标准类型,或者将整数类型的定义包括非标准类型)。

然而,我认为规范应该修正以避免模棱两可的解释。


0

虽然我不是专家,但我的答案是,如果您正确地指出了根据标准,uint_fast32_t 不需要成为这些类型之一,那么它确实是一个缺陷。

您提到的 NAD 问题 2326 中的建议似乎也可以解决此缺陷。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接