C++ Logo

std-proposals

Advanced search

Re: [std-proposals] consteval int relocatability

From: Oliver Hunt <oliver_at_[hidden]>
Date: Mon, 10 Nov 2025 02:08:02 -0800
> On Nov 10, 2025, at 1:01 AM, Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> On Mon, Nov 10, 2025 at 8:39 AM Frederick Virchanza Gotham wrote:
>>
>> I have further edited my compiler patch, and now
>> __builtin_restart_lifetime runs without crashing.
>
>
> One other thing we need to talk about though is 'qsort' as follows:
>
> template<class T>
> void my_sort(T *first, T *last)
> {
> auto *cmp = +[](const void *va, const void *vb) {
> T const &a = *std::restart_lifetime<T>(static_cast<void*>(va));
> T const &b = *std::restart_lifetime<T>(static_cast<void*>(vb));
> return a < b;
> };
> std::qsort(first, last - first, sizeof(T), cmp);
> }


As you note below the P3858 restart_lifetime API does not work for its stated purpose, but the rest of the problems come from using qsort(3) instead of std::sort.

Using qsort over an array of non-POD types is already UB, which already precludes it from being used on an array of polymorphic objects. Given the canonical case where restart_lifetime or trivially_relocate do have to do actual work are types that are or contain polymorphic objects, the only time that restart_lifetime would be required to do anything in the above comparison function is when the use of qsort is fundamentally incorrect.

You discuss a number of issues below but they do pretty much all cease to exist once you use std::sort, but to help clear things up


>
> In the above snippet, 'restart_lifetime' must be called every time an

It’s always required for any use of the objects in the container being sorted, but you’re in implementation territory and are making assumptions about when/if objects are move

> object is relocated by the 'qsort' algorithm

Clarifying the “qsort is C” thing again - qsort does not relocate the object, nor does it copy or move it. It performs a memmove, because C only has POD types, and those are the only types for which such behavior is sound.

> -- but the problem is
> that we don't have its previous address.

Correct, because that is an implementation detail of the underlying sorting algorithm. When you are performing your comparisons you don’t know if/when the objects being compared are or have been moved. std::sort is required to ensure that the comparison operation is only performed on live objects: e.g. if the type traits _did_ permit trivial relocation it would use it, and your comparisons would always be correct.

APIs like trivially_relocate or restart_lifetime are not really something you should ever be calling - they really are considered the primitives to be used for library behavior, not things you would need to perform yourself. Definitely not as past of callbacks provided to <algorithm>s, because then you’re messing with object lifetime during sort without knowing the lifetime requirements of the implementation.

> What we have here is a form
> of 'restart_lifetime' that only takes one argument instead of two. But
> I think for pointer authentication on arm64e, we need the old address,
> right? I wonder why arm64e just can't take the vtable address (which
> is known at compiler time from the template type T) and write a new
> authenticated pointer at runtime?

This was discussed in the EWG/LEWG combined session on TR - the restart_lifetime API presented in P3858 is fundamentally insufficient and did not achieve the stated goal.

> I wonder had anyone considered altering the specification of 'qsort'
> so that it internally invokes 'restart_lifetime'?

The correct thing to do is std::sort - I’m not being glib here: qsort is incorrect for any non-POD type (anything with copy or move constructors, assignment operators, or that is, or contains polymorphic types).

> This would mean we
> have access to the old address and can therefore pass two addresses to
> 'restart_lifetime'. Or would it be too funky to have a C library
> function invoking a C++ library function like that?
> Well actually the
> C library function would be invoking a compiler builtin:
> __restart_lifetime.

Re: funky - it would actually just be impossible, it is not defined in a context where C++ exists, and it has no support for the C++ type system, hence it being invalid to use it over most C++ types.

But more to the point: restart_lifetime needs to know the types involved, it’s not a function that can be call in any other case and qsort has no types. Once the types are gone there is no way to correctly copy or move any non-POD type.

Higher level C sort functions generally have method for specifying how objects should be moved, but obviously that comes with an indirection cost.

All this said and done, there is no urgency here, not any need to rush design.

—Oliver

> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2025-11-10 10:08:04