[libc++] Fix random_shuffle signature in C++03 mode with frozen headers (#186443)

The frozen C++03 headers got an invalid simplification in #134045 that
changed the signature of random_shuffle to use a forwarding reference
instead of a lvalue reference. This patch fixes it and adds a test.

---------

Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
This commit is contained in:
Zibi Sarbinowski 2026-03-20 11:22:42 -04:00 committed by GitHub
parent 0506c03802
commit fa49ad564b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 33 deletions

View File

@ -109,7 +109,7 @@ _LIBCPP_HIDE_FROM_ABI void random_shuffle(_RandomAccessIterator __first, _Random
template <class _RandomAccessIterator, class _RandomNumberGenerator>
_LIBCPP_HIDE_FROM_ABI void
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _RandomNumberGenerator&& __rand) {
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _RandomNumberGenerator& __rand) {
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
difference_type __d = __last - __first;
if (__d > 1) {

View File

@ -8,11 +8,11 @@
// <algorithm>
// template<RandomAccessIterator Iter, Callable<auto, Iter::difference_type> Rand>
// requires ShuffleIterator<Iter>
// && Convertible<Rand::result_type, Iter::difference_type>
// void
// random_shuffle(Iter first, Iter last, Rand&& rand);
// template<class RandomAccessIterator, class RandomFunc>
// void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomFunc& rand); // until C++11
//
// template<class RandomAccessIterator, class RandomFunc>
// void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomFunc&& rand); // since C++11
// REQUIRES: c++03 || c++11 || c++14
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
@ -20,42 +20,43 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include "test_macros.h"
#include "test_iterators.h"
struct gen
{
std::ptrdiff_t operator()(std::ptrdiff_t n)
{
return n-1;
}
struct RandomGenerator {
std::ptrdiff_t operator()(std::ptrdiff_t n) { return n - 1; }
};
template <class Iter>
void
test_with_iterator()
{
void test_with_iterator() {
RandomGenerator gen;
int values[] = {1, 2, 3, 4};
int ia[] = {1, 2, 3, 4};
int ia1[] = {4, 1, 2, 3};
const unsigned sa = sizeof(ia)/sizeof(ia[0]);
gen r;
// Make sure the algorithm shuffles
{
int arr[] = {1, 2, 3, 4};
std::random_shuffle(Iter(std::begin(arr)), Iter(std::end(arr)), gen);
int libcxx_expected[] = {4, 1, 2, 3};
LIBCPP_ASSERT(std::equal(std::begin(arr), std::end(arr), std::begin(libcxx_expected)));
assert(std::is_permutation(std::begin(arr), std::end(arr), std::begin(values)));
std::random_shuffle(Iter(std::begin(arr)), Iter(std::end(arr)), gen);
assert(std::is_permutation(std::begin(arr), std::end(arr), std::begin(values)));
}
std::random_shuffle(ia, ia+sa, r);
LIBCPP_ASSERT(std::equal(ia, ia+sa, ia1));
assert(std::is_permutation(ia, ia+sa, ia1));
std::random_shuffle(ia, ia+sa, r);
assert(std::is_permutation(ia, ia+sa, ia1));
// Test the signature in C++03 mode, which takes a lvalue reference
#if TEST_STD_VER == 03
{
int arr[] = {1, 2, 3, 4};
std::random_shuffle<Iter, RandomGenerator>(Iter(std::begin(arr)), Iter(std::end(arr)), gen);
assert(std::is_permutation(std::begin(arr), std::end(arr), std::begin(values)));
}
#endif
}
int main(int, char**)
{
test_with_iterator<random_access_iterator<int*> >();
test_with_iterator<int*>();
return 0;
int main(int, char**) {
test_with_iterator<random_access_iterator<int*> >();
test_with_iterator<int*>();
return 0;
}