This change fixes std::inplace_merge to be stable for all inputs and adds corresponding tests.
Fixes Bug 31166: https://bugs.llvm.org//show_bug.cgi?id=31166
Differential D32788
Fix std::inplace_merge to be stable for all inputs jdoerrie on May 3 2017, 1:21 AM. Authored by
Details
This change fixes std::inplace_merge to be stable for all inputs and adds corresponding tests. Fixes Bug 31166: https://bugs.llvm.org//show_bug.cgi?id=31166
Diff Detail Event Timeline
Comment Actions Note: I suspect that the proposed change to <algorithm> fixes the problem, but the new tests don't check that. Comment Actions I committed as r311952 which fixes this - based on Jan's suggestion, but not quite the same as this patch. Comment Actions Thanks for applying a fix based on my patch! I could have sworn the added tests failed locally before applying the algorithm patch, though... oh well. |
As marshall pointed out in https://bugs.llvm.org//show_bug.cgi?id=31166 this is where the problem lies. While reversing the input ranges is a very nifty trick to be able to use the moved out space at the end of [first, last), simply negating the comparison functor is not enough to preserve stability.
Assuming a default __comp of std::less, in line 4431 a negated __comp will evaluate to true for equivalent elements, resulting in a move from *__first2 and thus breaking stability. The fix for this to to still have __comp evaluate to false for equivalent elements, what the change in 748 accomplishes.
Given that now __negate technically does not negate anymore, maybe it should be renamed to a more suiting __reverse or __swap or similar. Doing a quick grep over the code base line 4471 seems to be the only place where this is used, so a rename should not have further consequences. Furthermore, the unary bool operator() could be deleted.