Date: Mon, 6 Apr 2026 11:06:05 -0700
That actually is quite interesting. std::partition only really registered
as a sorting function for me.
At the risk of going off into the weeds with you, I would normally use the
code I posted in a single invocation to remove a single element once
found. Whereas unstable_remove_if would have required invoking all of the
following in the version you linked to:
template<class BidirIt, class UnaryPredicate>
#if __cplusplus >= 201703L
[[nodiscard]]
#endif
BidirIt unstable_remove_if(BidirIt first, BidirIt last, UnaryPredicate p) {
while (true) {
// Find the first instance of "p"...
while (true) {
if (first == last) {
return first;
}
if (p(*first)) {
break;
}
++first;
}
// ...and the last instance of "not p"...
while (true) {
--last;
if (first == last) {
return first;
}
if (!p(*last)) {
break;
}
}
// ...and move the latter over top of the former.
*first = std::move(*last);
++first;
}
}
template<class FwdIt>
void destroy(FwdIt begin, FwdIt end) {
typedef typename std::iterator_traits<FwdIt>::value_type T;
while (begin != end) {
begin->~T();
++begin;
}
}
On Mon, Apr 6, 2026 at 10:41 AM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:
> On Mon, Apr 6, 2026 at 1:28 PM Adrian Johnston via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>
>> If your array is unordered then you can just swap the end element down
>> when erasing an element.
>>
>> From my own code:
>>
>> template<hxarray_concept_ T_, size_t capacity_>
>>
>> void hxarray<T_, capacity_>::erase_unordered(const T_* pos_) {
>>
>> hxassertmsg(pos_ >= this->data() && pos_ < m_end_,
>> "invalid_iterator");
>>
>> if(pos_ != --m_end_) {
>>
>> *const_cast<T_*>(pos_) = hxmove(*m_end_);
>>
>> }
>>
>> m_end_->~T_();
>>
>> }
>>
>> This is something I think the std::vector could definitely use.
>>
>
> This is properly an algorithm: `stdx::unstable_remove{,_if}`.
> See
> Brent Friedman, 2015:
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0041r0.html
> Brent Friedman, 2016:
> https://iterator.wordpress.com/2016/01/31/algorithms_0/ (archived
> <https://archive.is/pd5v6>)
> Arthur O'Dwyer, 2023-ish:
> https://github.com/Quuxplusone/SG14?tab=readme-ov-file#efficient-removal-algorithms-future--c14
> Ted Lyngmo, 2025:
> https://discourse.bemanproject.org/t/help-getting-started-writing-a-propsal-for-unstable-remove-and-friends-wanted/335
>
> Note that David Sankel asked (in the last link above) how
> std::unstable_remove_if was different from std::partition. The answer is
> that std::partition swaps; std::unstable_remove_if leaves the right-hand
> elements in a moved-from state (à la std::shift_left).
> Note that (AIUI) Ted Lyngmo abandoned his proposal because the benchmark
> numbers weren't good enough to justify the standardization effort; see
> here <https://lists.isocpp.org/std-proposals/2025/02/12297.php>.
>
> HTH,
> Arthur
>
as a sorting function for me.
At the risk of going off into the weeds with you, I would normally use the
code I posted in a single invocation to remove a single element once
found. Whereas unstable_remove_if would have required invoking all of the
following in the version you linked to:
template<class BidirIt, class UnaryPredicate>
#if __cplusplus >= 201703L
[[nodiscard]]
#endif
BidirIt unstable_remove_if(BidirIt first, BidirIt last, UnaryPredicate p) {
while (true) {
// Find the first instance of "p"...
while (true) {
if (first == last) {
return first;
}
if (p(*first)) {
break;
}
++first;
}
// ...and the last instance of "not p"...
while (true) {
--last;
if (first == last) {
return first;
}
if (!p(*last)) {
break;
}
}
// ...and move the latter over top of the former.
*first = std::move(*last);
++first;
}
}
template<class FwdIt>
void destroy(FwdIt begin, FwdIt end) {
typedef typename std::iterator_traits<FwdIt>::value_type T;
while (begin != end) {
begin->~T();
++begin;
}
}
On Mon, Apr 6, 2026 at 10:41 AM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:
> On Mon, Apr 6, 2026 at 1:28 PM Adrian Johnston via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>
>> If your array is unordered then you can just swap the end element down
>> when erasing an element.
>>
>> From my own code:
>>
>> template<hxarray_concept_ T_, size_t capacity_>
>>
>> void hxarray<T_, capacity_>::erase_unordered(const T_* pos_) {
>>
>> hxassertmsg(pos_ >= this->data() && pos_ < m_end_,
>> "invalid_iterator");
>>
>> if(pos_ != --m_end_) {
>>
>> *const_cast<T_*>(pos_) = hxmove(*m_end_);
>>
>> }
>>
>> m_end_->~T_();
>>
>> }
>>
>> This is something I think the std::vector could definitely use.
>>
>
> This is properly an algorithm: `stdx::unstable_remove{,_if}`.
> See
> Brent Friedman, 2015:
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0041r0.html
> Brent Friedman, 2016:
> https://iterator.wordpress.com/2016/01/31/algorithms_0/ (archived
> <https://archive.is/pd5v6>)
> Arthur O'Dwyer, 2023-ish:
> https://github.com/Quuxplusone/SG14?tab=readme-ov-file#efficient-removal-algorithms-future--c14
> Ted Lyngmo, 2025:
> https://discourse.bemanproject.org/t/help-getting-started-writing-a-propsal-for-unstable-remove-and-friends-wanted/335
>
> Note that David Sankel asked (in the last link above) how
> std::unstable_remove_if was different from std::partition. The answer is
> that std::partition swaps; std::unstable_remove_if leaves the right-hand
> elements in a moved-from state (à la std::shift_left).
> Note that (AIUI) Ted Lyngmo abandoned his proposal because the benchmark
> numbers weren't good enough to justify the standardization effort; see
> here <https://lists.isocpp.org/std-proposals/2025/02/12297.php>.
>
> HTH,
> Arthur
>
Received on 2026-04-06 18:06:20
