mike - 6 months ago 18

C++ Question

We have

`uniform_int_distribution`

`uniform_real_distribution`

`uniform_distribution`

Why standard has not choosen this path?

Answer

AFAIU, the comments above by @user877329 and @revolver_ocelot explain this correctly, and the other answer is completely wrong.

It is wrong to unify the interfaces of `uniform_int`

and `uniform_real`

, not because they are implemented differently (which can be solved via template specialization), but because *the interfaces mean different things*.

Suppose we unify the interfaces (using a variation of the suggestion in the other answer), like so:

```
template <typename T>
using uniform_distribution =
typename std::conditional<
std::is_integral<T>::value,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>
>::type;
```

Then if we define `uniform_distribution<some_type> u(0, 9)`

, the meaning is very different:

if

`some_type`

is integral, then u will output 9 approximately 1/10ths of the time.if

`some_type`

is not, then`u`

will*never*output 9.

The following code (whose output is `true`

and then `false`

) illustrates this:

```
#include <random>
#include <iostream>
#include <type_traits>
template <typename T>
using uniform_distribution =
typename std::conditional<
std::is_integral<T>::value,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>
>::type;
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
{
uniform_distribution<int> u(0, 9);
bool over_found = false;
for(size_t i = 0; i < 99999; ++i)
over_found = over_found || u(gen) >= 9;
std::cout << std::boolalpha << over_found << std::endl;
}
{
uniform_distribution<float> u(0, 9);
bool over_found = false;
for(size_t i = 0; i < 99999; ++i)
over_found = over_found || u(gen) >= 9;
std::cout << std::boolalpha << over_found << std::endl;
}
}
```

This code illustrates that writing generic code using this class is dangerous. For example, if you'd write a generic function calculating a histogram of the results in the subranges: *[0, 1), [1, 2), ..., [8, 9)*, the results would be incompatible.

As @revolver_ocelot points out, the standard library's [inclusive-begin, exclusive_end) convention cannot be used for uniform integers (because it would be impossible to specify a uniform integer random number generator generating also the maximum uint value), making this an exceptional signature.