Search code examples
c++c++11language-lawyerstdlibrary-design

Confusion about the interface design of C++11 random distributions


Let's take uniform_int_distribution for example. In my opinion, despite the fact that it stores a default set of distribution parameters, it is practically stateless. As such, wouldn't it be better and more convenient to design it as a function template like

template <class Engine, class IntType = int>
IntType uniform_int(Engine& engine, IntType a = 0, IntType b = numeric_limits<IntType>::max());

Quite often, I find myself write something like

std::uniform_int_distribution<int> uniform_int(a, b);
... = uniform_int(engine);

Or to compress it into a single line

... = std::uniform_int_distribution<int>(a, b)(engine);

Either way, this feels contrived and awkward. With a function interface, this can be done naturally as

... = std::uniform_int(engine, a, b);

You can still store a default set of distribution parameters if you like

auto my_uniform_int = std::bind(std::uniform_int<int>, placeholders::_1, a, b);

Am I missing something?


Solution

  • In my opinion, despite the fact that it stores a default set of distribution parameters, it is practically stateless.

    No, not necessarily. For example, if the underlying engine generates X random bits at a time, and uniform_int_distribution (with the given range) requires only Y random bits (where Y < X), the implementation may choose as an optimization to store the remaining random bits for use later.

    Besides, you want to keep a uniform interface with things like normal_distribution (where many methods generate 2 random numbers at once, so you'd return one and store the other for the next invocation), and distributions where you'd want to precompute some parameters at construction time.