David David - 22 days ago 9
C++ Question

Why does `std::sample` take `UniformRandomBitGenerator` as &&?

std::uniform_real_distribution::operator()
is:

template< class Generator >
result_type operator()( Generator& g );


while
std::sample
is:

template< class PopulationIterator, class SampleIterator,
class Distance, class UniformRandomBitGenerator >
SampleIterator sample( PopulationIterator first, PopulationIterator last,
SampleIterator out, Distance n,
UniformRandomBitGenerator&& g);


I'm only referencing
uniform_real_distribution
here because it's another place in the standard which takes a generator, and
sample
and
std::uniform_real_distribution::operator()
take them in different ways. Just curious about the rationale behind this.

Answer
  1. sample ultimately needs a non-const generator, but it's also very convenient to allow temporary generators to be passed in, which wouldn't be possible if it took the generator by non-const lvalue-reference. The obvious solution: a forwarding reference, and an inevitable compiler error if a const lvalue is supplied.

    On the other hand, I suppose it would not be nearly as usual to pass a temporary generator to a single distribution invocation – indeed, given the expense of constructing/initializing most generators, the vast majority of the time doing so would be a pit of inefficiency. In this light, as with e.g. std::vector's lack of push_front and pop_front, discouraging this inefficiency by actively making it an anti-pattern is probably the best thing to do.

  2. Chronologically, <random> predates C++11 significantly (it comes from TR1, and Boost before that), and was not necessarily thoroughly updated to exploit all new language features when incorporated into the standard.

Comments