This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
random_shuffle
signatures are inconsistentSection: 26.7.13 [alg.random.shuffle] Status: C++11 Submitter: INCITS Opened: 2010-08-25 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [alg.random.shuffle].
View all issues with C++11 status.
Duplicate of: 1433
Discussion:
Addresses US-121, GB-119
random_shuffle
and shuffle
should be consistent in how
they accept their source of randomness: either both by rvalue reference or
both by lvalue reference.
[ Post-Rapperswil, Daniel provided wording ]
The signatures of the shuffle
and random_shuffle
algorithms are different
in regard to the support of rvalues and lvalues of the provided generator:
template<class RandomAccessIterator, class RandomNumberGenerator> void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator&& rand);
template<class RandomAccessIterator, class UniformRandomNumberGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator& g);
The first form uses the perfect forwarding signature and that change compared to
C++03
was done intentionally as shown in the first rvalue proposal
papers.
While it is true, that random generators are excellent examples of stateful functors, there still exist good reasons to support rvalues as arguments:
std::generate
and std::generate_n
)
accept both rvalues and lvalues as well.
C++03
. In the specific
cases, where rvalues are provided, the argument will be accepted instead of being rejected.
Arguments have been raised that accepting rvalues is error-prone or even fundamentally wrong. The author of this proposal disagrees with that position for two additional reasons:
instead of writingmy_generator get_generator(int size);
they will just writestd::vector<int> v = ...; std::shuffle(v.begin(), v.end(), get_generator(v.size()));
and feel annoyed about the need for it.std::vector<int> v = ...; auto gen = get_generator(v.size()); std::shuffle(v.begin(), v.end(), gen);
CopyConstructible
and this is obviously a generally useful property for such objects. It is also useful and sometimes necessary to start a
generator with exactly a specific seed again and again and thus to provide a new generator (or a copy) for each call. The
CopyConstructible
requirements allow providing rvalues of generators and thus this idiom must be useful as well.
Therefore preventing [random_]shuffle
to accept rvalues is an unnecessary restriction which doesn't prevent any
user-error, if there would exist one.
Thus this proposal recommends to make both shuffle
functions consistent and perfectly forward-able.
Moved to Tentatively Ready after 6 positive votes on c++std-lib.
[ Adopted at 2010-11 Batavia ]
Proposed resolution:
<algorithm>
synopsis as indicated:
template<class RandomAccessIterator, class UniformRandomNumberGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& rand);
template<class RandomAccessIterator, class UniformRandomNumberGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& rand);