57

According to the cppreference.com reference site on std::shufle, the following method is being deprecated in c++14:

template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );

Why will we no longer be able to call the following function without passing a third parameter?

std::random_shuffle(v.begin(),v.end()); //no longer valid in c++14

It doesn't appear as though a different function deceleration has a default parameter set. What is the reason behind this? Was there some kind of alternative added?

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271

5 Answers5

53

std::random_shuffle may make use, under the hood, of random C family of functions. These functions use global state for seeds and other state.

So it is being deprecated because shuffle will do the same, but better. Namely, it uses the new <random> header from C++11 that doesn't use global state, but its own objects making use of generators, devices and distributions.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Germán Diago
  • 7,473
  • 1
  • 36
  • 59
47

std::random_shuffle is (effectively) replaced by std::shuffle. You do need to pass a third parameter (a random number generator), but in exchange for that you get substantially better definition and (typically) behavior.

std::random_shuffle was fairly poorly defined. It typically used rand() to generate the random numbers, but nothing said whether (and if so how) it called srand, so you couldn't depend (for one example) in rand being seeded how you wanted (and if you seeded it, you couldn't depend on that being put to use). If memory serves, there was also some confusing (and somewhat self-contradictory) language that could be interpreted as saying that random_shuffle couldn't use rand at all, and/or that it couldn't seed it with srand. Even at best, many implementations of rand() were quite poor, so even at very best you couldn't depend on useful results.

Bottom line: random_shuffle is no loss. Use std::shuffle instead, and your code will be much better for it.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • There seems to be a second overload that accepts an RNG though... is that one fine to use? – user541686 Mar 24 '14 at 03:01
  • @Mehrdad: I believe so, yes. It's basically equivalent to `std::shuffle`. I don't see any real reason to prefer it over `std::shuffle` though. – Jerry Coffin Mar 24 '14 at 03:05
  • 14
    The `RandomNumberGenerator` in `random_shuffle` has a different API than the `UniformRandomNumberGenerator` in `shuffle` does. The latter has an API consistent with the Uniform random number generator requirements in [rand.req.urng]. The former has an API specified only in the requires clause of `random_shuffle`. – Howard Hinnant Mar 24 '14 at 03:15
16

We can find the rationale in this document N3775: Deprecating rand and Friends which says:

We therefore now propose to execute the next step of this plan to discourage the use of the traditional C function rand as well as its associated seeding function srand and upper limit macro RAND_MAX.6 In particular, we propose to begin this transition by formally deprecating:

  • rand, srand, and RAND_MAX and
  • algorithm random_shuffle() (keeping shuffle, however).

The rationale for deprecating random_shuffle() is that one overload is specified so as to depend on rand, while the other overload is specified so as to require a hard-to-produce distribution object from the user; such a distribution is already an implicit part of shuffle, which we retain.

and the later document Discouraging rand() in C++14, v2 which reiterates this position.

Update

As Howard Hinnant notes N3775 has an error: rand_shuffle() is allowed but not required to use rand() under the hood but that would not change the rationale.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • 2
    N3775 is in error in saying that `rand_shuffle()` is specified so as to depend on `rand`. It is correct to say that it is allowed to be implemented on top of `rand`. But it is not required to be implemented on top of `rand`. – Howard Hinnant Mar 24 '14 at 03:10
  • @HowardHinnant Thank you for pointing that out, I was wondering why cppreference used that wording, I should have just looked it up in the standard myself. – Shafik Yaghmour Mar 24 '14 at 09:31
6

random_shuffle is being deprecated because its RNG is unspecified -- not just that you don't have to specify it, but that the standard itself doesn't specify it. On VC++, for instance, it uses rand(), which is implemented really poorly!

Cory Nelson
  • 29,236
  • 5
  • 72
  • 110
4

The other responses answer the question, but if anyone is looking for some cut-n-paste code that may suit your needs, the following will probably do the trick:

#include <random>
...
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(v.begin(), v.end(), g);

rd yields non-deterministic random data on many platforms and the generator g uses a Mersenne Twister pseudo-random generator with a large state.

wcochran
  • 10,089
  • 6
  • 61
  • 69