Why Aren't `std::uniform_int_distribution<uint8_t>` and `std::uniform_int_distribution<int8_t>` Allowed?
Asked Answered
E

1

40

As the documentation says:

The effect is undefined if this is not one of short, int, long, long long, unsigned short, unsigned int, unsigned long, or unsigned long long.

If I don't care about the range, I can just mask off the bits of a larger type to generate random numbers. If not, it's more complex. Why aren't the byte types provided just by default?

Ethelethelbert answered 16/7, 2015 at 17:24 Comment(5)
Isn't int8_t – if the implementation provides it at all – necessarily a typedef to one of the listed integers?Urbain
@Urbain it is likely signed char which is indeed missing from that list.Toro
I asked std-discussion about this once.Reilly
@ShafikYaghmour Ah, thanks. Now I see the point and understand your answer. I didn't notice it was missing.Urbain
You can also use uniform_int_distribution<int> d{0, std::numeric_limits<uint8_t>::max()} to get uniformly distributed values that will fit in a uint8_tJonna
T
21

There is a library working group unresolved[1] issue on this uniform_int_distribution<unsigned char> should be permitted and it says, amongst other things:

I am not aware of anything in <random> that works with 16-bit integers but fails with 8-bit integers, so I suspect that IntType and UIntType could simply be extended to permit the char family. Alternatively, this change could be limited to uniform_int_distribution alone, where it is definitely safe. A <random> expert should decide which change is best.

The proposed resolution is to change the restriction to allow standard integer types:

that has a template type parameter named IntType is undefined unless the corresponding template argument is cv-unqualified and is a a standard integer type (3.9.1 [basic.fundamental]

and:

that has a template type parameter named UIntType is undefined unless the corresponding template argument is cv-unqualified and is a standard unsigned integer type (3.9.1 [basic.fundamental])

This gets you unsigned / signed char although not uint8_t or int8_t but they are likely equivalent. Extended integral types were exluded to simplify the wording and maximize consensus:

This also excludes extended integral types and wide char types, which seem like nice-to-haves at best. I have no objection to supporting any of those types; I just picked this to simplify the wording and hopefully maximize consensus.

Note, this excludes char since it is implementation defined whether char is signed or not.

Note this topic was also brought up in the std-discussion list.

Jonathan Wakely notes this proposal is controversial and commented that his notes from the last discussion include the following:

that it was very definitely intentional that single byte integers are not supported, not an accidental omission, and so we should be careful about just changing that without consulting the designers of the C++11

He suggests adding a member to random_device to provide single bytes, which is seems like a reasonable alternative.


[1] The issue has been closed as "Not A Defect", meaning that it will not be resolved as a defect report. Instead a formal proposal for the change will be required.

Toro answered 16/7, 2015 at 17:29 Comment(13)
The proposed change is fairly controversial. I have suggested that if what's really wanted is a source of random bytes (which it seems is what people really want when they ask for this) then an alternative interface to get N random bytes would be better than making every distribution support 1-byte integers.Jonna
@JonathanWakely thank you for the comment, can you explain what the issue is? Your proposal makes a lot of sense, I am just wondering why the proposed fixed is problematic.Toro
My notes from the last discussion say that it was very definitely intentional that single byte integers are not supported, not an accidental omission, and so we should be careful about just changing that without consulting the designers of the C++11 <random> facilities. My suggestion was to add a member function to random_device to obtain random bytes, and not touch any engines or distributions. That is likely to perform much better than extracting one byte at a time from a distribution.Jonna
FYI: LWG Issue 2326, which considered the lack of signed/unsigned char types in IntType to be defective was closed as "Not A Defect" That's not to say that it will not be fixed. This is only to say that the current behavior is by design, so a change should be a formal proposal, not a defect fixup.Livingston
The link for library - open-std.org/jtc1/sc22/wg21/docs/lwg-unresolved.html#2326 Doesn't seem to have uniform_int_distribution anymore.Bathsheba
@JonathanWakely Do your notes say anything about why the committee initially intentionally excluded the character types?Tonsillotomy
@Brian no, but if I had to guess it's because characters are not integers, integers are not characters.Jonna
@chaitanya as already noted, the issue changed status so it's no longer in that list of unresolved issues. You can always go directly to any specific issue with a link like wg21.link/lwg2326Jonna
None of this explains why on Earth I can't generate, say, dice rolls from 1 to 6 in the smallest standard integer type that can hold these values. This very much looks like an oversight, and in the lengthy answer and discussion not a single rationale was mentioned. "integers are not characters" is a lousy argument.Graphemics
@VioletGiraffe Well, the wording gives me the feeling that the committee went out of their way to exclude character types in general, not just small integer types. For example, the same problem exists for wchar_t and possibly char32_t.Tiu
@Spencer: so the 8-bit integer types fell victim of being aliases for char / unsigned char?Graphemics
@VioletGiraffe That's my impression, too. short is allowed so it doesn't have anything to do with integer promotion.Tiu
That the designer would say, "Nope, no byte sizes allowed" without any explanation is very odd. Sounds like a good Monty Python sketch. Preacher: "Ye may eat this sandwich, but ye may not eat half of it! So saith the lord!" Peon: "But, I'm not that hungry atm. I'll just save the other half for later." Preacher: "Blasphemer! Thou shall be smited!"Accommodation

© 2022 - 2024 — McMap. All rights reserved.