[Bug libstdc++/85828] std::shuffle tries to swap element with itself

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri May 18 15:39:00 GMT 2018


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85828

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
This is ugly but it works:

--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -3827,7 +3827,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        if ((__urange % 2) == 0)
        {
          __distr_type __d{0, 1};
-         std::iter_swap(__i++, __first + __d(__g));
+         if (__d(__g) == 0)
+           std::iter_swap(__i, __first);
+         ++__i;
        }

        // Now we know that __last - __i is even, so we do the rest in pairs,
@@ -3841,8 +3843,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          const pair<__uc_type, __uc_type> __pospos =
            __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g);

-         std::iter_swap(__i++, __first + __pospos.first);
-         std::iter_swap(__i++, __first + __pospos.second);
+         _RandomAccessIterator __pos1 = __first + __pospos.first;
+         _RandomAccessIterator __pos2 = __first + __pospos.second;
+         if (__i != __pos1)
+           std::iter_swap(__i, __pos1);
+         ++__i;
+         if (__i != __pos2)
+           std::iter_swap(__i, __pos2);
+         ++__i;
        }

        return;


I think we also want to remove the __glibcxx_check_self_move_assign assertions
completely.


More information about the Gcc-bugs mailing list