Background: I'm shuffling the elements of a vector for a simple game. It should be possible to play the same game over again by passing the same integer seed — and vice versa, different seeds should produce different games. Cryptographic security (or any rigor at all) is not a design goal; cleanliness of code is a design goal.
C++98/C++03 introduced std::random_shuffle
, which is used like this:
int seed = ...;
std::srand(seed); // caveat, see below
std::vector<int> deck = ...;
std::random_shuffle(deck.begin(), deck.end());
However, as of C++14, random_shuffle
has been deprecated (source: N3924). The C++14 way of shuffling a deck is
int seed = ...;
std::vector<int> deck = ...;
std::shuffle(deck.begin(), deck.end(), std::mt19937(seed));
Here are the things that detract from each approach:
The
srand
/random_shuffle
way is deprecated in C++14, so we shouldn't use it.On some implementations,
random_shuffle
appears not to take its seed fromsrand
, i.e., seeding with a different value doesn't produce different output! (libstdc++ on Linux doesn't have this issue, but Xcode on OSX 10.9.5 does.)The
shuffle
/mt19937
way isn't part of C++03, so we can't use it.The
shuffle
/mt19937
way appears to require that we pass the seed all the way down into the deck-shuffling code. For my application, I'd prefer to just "set it and forget it" via a mechanism such assrand
that hides the global variable, rather than have to define my own global PRNG of typemt19937
. In other words: I don't want to be bothered with PRNG details, I just want to shuffle my vector!I am mildly worried about thread-safety (being able to simultaneously shuffle two different decks from different threads), but obviously not about thread-safety and "seedableness" at the same time. Consider thread-safety a "nice-to-have".
The first candidate I've thought of is:
bite the bullet and pass
int seed
all the way down into the deck-shuffling code (avoiding global variables)use something like
#if __cplusplus >= 20110000
to userandom_shuffle
pre-C++11 andshuffle
post-C++11to work around the
srand
"bug" on OSX, use the three-argument version ofrandom_shuffle
with some complicated functor... this sounds ugly
The second candidate is:
- screw C++03; just drop support for any implementation that doesn't provide
std::shuffle
andstd::mt19937
out of the box
But is there some nice way to solve this problem? I know it's a problem that nobody has unless their program is a toy program; but there must be hundreds of toy programs out there that have hit this problem!
Aucun commentaire:
Enregistrer un commentaire