From: Vladimir Grigoriev on
Why is the RandomNumber Generator parameter passed by reference in the
std::random_shuffle() while other algorithms take a function parameter by
value? What is the reason? When a function parameter is passed by reference
it can not be built on the fly.

For example

std::random_shuffle( first, last, UserRandomNumberGenerator() ); // is not
compiled

Vladimir Grigoriev



From: Igor Tandetnik on
Vladimir Grigoriev wrote:
> Why is the RandomNumber Generator parameter passed by reference in the
> std::random_shuffle() while other algorithms take a function parameter by
> value?

Random number generators usually have state. Things like, say, predicates are typically stateless.

> What is the reason? When a function parameter is passed by reference
> it can not be built on the fly.

Why would you want to?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
From: Vladimir Grigoriev on
However a state can be kept inside a functional class. So I think your
reason is not sufficient.

Vladimir Grigoriev

"Igor Tandetnik" <itandetnik(a)mvps.org> wrote in message
news:%23pE395FmKHA.1824(a)TK2MSFTNGP04.phx.gbl...
Vladimir Grigoriev wrote:
> Why is the RandomNumber Generator parameter passed by reference in the
> std::random_shuffle() while other algorithms take a function parameter by
> value?

Random number generators usually have state. Things like, say, predicates
are typically stateless.

> What is the reason? When a function parameter is passed by reference
> it can not be built on the fly.

Why would you want to?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily
a good idea. It is hard to be sure where they are going to land, and it
could be dangerous sitting under them as they fly overhead. -- RFC 1925


From: Tamas Demjen on
Vladimir Grigoriev wrote:
> However a state can be kept inside a functional class. So I think your
> reason is not sufficient.

Because you usually don't want to reset the seed of the random number
generator. Instead, you want to continue where your previous random
number was left off.

Imagine that you are writing a card game, and random_shuffle's last
parameter is passed by value in the following code:

UserRandomNumberGenerator rand(initial_seed);
while(!quit)
{
int A[] = {1, 2, 3, 4, 5, 6, 7, 8};
random_shuffle(A, A + N, rand);
PlayCardGame(A, A + N);
}

So if this is a solitaire game, the player would see the exact same
order of cards in every single game. :-)

However, since random_shuffle's last argument is a reference, this
problem does not exist.

Tom
From: Stephan T. Lavavej [MSFT] on
There's a little more to the story than this.

First, I want to correct an earlier reply:

[Igor Tandetnik]
> Things like, say, predicates are typically stateless.

This is incorrect. Some predicates are stateless, like is_even. Other
predicates are stateful, like bind(less<int>(), _1, 1729). Predicates (and
comparators) almost never *modify* their state as they are invoked, because
they must return consistent answers, but constructing a stateful predicate
and giving it to an STL algorithm is a common and useful thing to do.

Tamas explained most of the story below - PRNGs modify their state, and
typically you want to keep using the modified state instead of discarding
it. However, the STL has an algorithm that takes a functor by value,
invokes it on every element of a sequence, and *returns* that functor,
allowing the functor to modify its state along the way so that it can be
inspected later. This algorithm is called for_each().

So why doesn't random_shuffle() behave like for_each()? I can think of a
couple of reasons. First, taking the PRNG by reference makes it difficult
to drop the modified state on the floor. (This was probably the most
important reason during C++98's standardization.) Second, PRNGs often
maintain a lot of state, unlike other functors which are expected to be
lightweight (the STL usually passes functors by value). For example (an
anachronistic example), mersenne_twister maintains a lot of state. Copying
that around, in the absence of move semantics, is undesirable.

STL

"Tamas Demjen" <tdemjen(a)yahoo.com> wrote in message
news:%23fEVQiImKHA.4872(a)TK2MSFTNGP05.phx.gbl...
> Vladimir Grigoriev wrote:
>> However a state can be kept inside a functional class. So I think your
>> reason is not sufficient.
>
> Because you usually don't want to reset the seed of the random number
> generator. Instead, you want to continue where your previous random
> number was left off.
>
> Imagine that you are writing a card game, and random_shuffle's last
> parameter is passed by value in the following code:
>
> UserRandomNumberGenerator rand(initial_seed);
> while(!quit)
> {
> int A[] = {1, 2, 3, 4, 5, 6, 7, 8};
> random_shuffle(A, A + N, rand);
> PlayCardGame(A, A + N);
> }
>
> So if this is a solitaire game, the player would see the exact same
> order of cards in every single game. :-)
>
> However, since random_shuffle's last argument is a reference, this
> problem does not exist.
>
> Tom