Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::uniform_int_distribution<std::size_t> undefined behavior?

Tags:

c++

c++11

According to the cppreference documentation on std::uniform_int_distribution,

The effect is undefined if [IntType] is not one of: short, int, long, long long, unsigned short, unsigned int, unsigned long, or unsigned long long.

I'm not sure of how this applies to std::size_t - namely with these 3 confusions:

  1. On one hand, std::size_t, as far as I know, is usually a typedef of one of the unsigned types in that list.
  2. However, I'm not sure if the standard mandates that always be the case.
  3. I'm not sure if "undefined if [IntType] is not one of: ..." implies IntType has to nominally match something from that list (the type has to explicitly be one of those, by name) or whether it can structurally match (so a typedef to one of those is considered acceptable as well).

Is std::uniform_int_distribution<std::size_t> undefined behavior?

like image 860
RaisinCrab Avatar asked Oct 16 '25 21:10

RaisinCrab


1 Answers

On one hand, std::size_t, as far as I know, is usually a typedef of one of the unsigned types in that list.

Yes, usually.

However, I'm not sure if the standard mandates that always be the case.

No, it can technically also be unsigned char or an implementation-defined extended unsigned integer type. The former seems extremely unlikely to me to ever make sense and I don't know any example of the latter either.

I'm not sure if "undefined if [IntType] is not one of: ..." implies IntType has to nominally match something from that list (the type has to explicitly be one of those, by name) or whether it can structurally match (so a typedef to one of those is considered acceptable as well).

It means that the type named by the template argument shall be one of the ones listed. How it is named is not relevant. A template can not detect that anyway.


In practice std::size_t will normally be one of unsigned int, unsigned long and unsigned long long. So you can use a simple static_assert to make sure that you are not being compiled on some exotic platform that needs extra considerations, as suggested by @Sheff'sCat in the comments under the question:

static_assert(std::is_same_v<std::size_t, unsigned> || std::is_same_v<std::size_t, unsigned long> || std::is_same_v<std::size_t, unsigned long long>);
like image 90
user17732522 Avatar answered Oct 19 '25 12:10

user17732522